PluginProbe
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin / 1.8.1
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin v1.8.1
trunk 1.5 1.6 1.7 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 All 71 releases
pdf-print / mpdf / mpdf.php

mpdf.php in PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin 1.8.1, at mpdf/mpdf.php

32,752 lines 1.3 MB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // ******************************************************************************
4 // Software: mPDF, Unicode-HTML Free PDF generator *
5 // Version: 6.0 based on *
6 // FPDF by Olivier PLATHEY *
7 // HTML2FPDF by Renato Coelho *
8 // Date: 2014-11-24 *
9 // Author: Ian Back <ianb@bpm1.com> *
10 // License: GPL *
11 // *
12 // Changes: See changelog.txt *
13 // ******************************************************************************
14
15
16 define('mPDF_VERSION','6.0');
17
18 //Scale factor
19 define('_MPDFK', (72/25.4));
20
21
22 // Specify which font metrics to use:
23 // 'winTypo' uses sTypoAscender etc from the OS/2 table and is the one usually recommended - BUT
24 // 'win' use WinAscent etc from OS/2 and inpractice seems to be used more commonly in Windows environment
25 // 'mac' uses Ascender etc from hhea table, and is used on Mac/OSX environment
26 if (!defined('_FONT_DESCRIPTOR')) define("_FONT_DESCRIPTOR", 'win'); // Values: '' [BLANK] or 'win', 'mac', 'winTypo'
27
28
29 /*-- HTML-CSS --*/
30
31 define('_BORDER_ALL',15);
32 define('_BORDER_TOP',8);
33 define('_BORDER_RIGHT',4);
34 define('_BORDER_BOTTOM',2);
35 define('_BORDER_LEFT',1);
36 /*-- END HTML-CSS --*/
37
38 // mPDF 6.0
39 // Used for $textvars - user settings via CSS
40 define('FD_UNDERLINE',1); // font-decoration
41 define('FD_LINETHROUGH',2);
42 define('FD_OVERLINE',4);
43 define('FA_SUPERSCRIPT',8); // font-(vertical)-align
44 define('FA_SUBSCRIPT',16);
45 define('FT_UPPERCASE',32); // font-transform
46 define('FT_LOWERCASE',64);
47 define('FT_CAPITALIZE',128);
48 define('FC_KERNING',256); // font-(other)-controls
49 define('FC_SMALLCAPS',512);
50
51
52 if (!defined('_MPDF_PATH')) define('_MPDF_PATH', dirname(preg_replace('/\\\\/','/',__FILE__)) . '/');
53 if (!defined('_MPDF_URI')) define('_MPDF_URI',_MPDF_PATH);
54
55 require_once(_MPDF_PATH.'includes/functions.php');
56 require_once(_MPDF_PATH.'config_lang2fonts.php');
57
58 require_once(_MPDF_PATH.'classes/ucdn.php'); // mPDF 6.0
59
60 /*-- OTL --*/
61 require_once(_MPDF_PATH.'classes/indic.php'); // mPDF 6.0
62 require_once(_MPDF_PATH.'classes/myanmar.php'); // mPDF 6.0
63 require_once(_MPDF_PATH.'classes/sea.php'); // mPDF 6.0
64 /*-- END OTL --*/
65
66
67 if (!defined('_JPGRAPH_PATH')) define("_JPGRAPH_PATH", _MPDF_PATH.'jpgraph/');
68
69 if (!defined('_MPDF_TEMP_PATH')) define("_MPDF_TEMP_PATH", _MPDF_PATH.'tmp/');
70
71 if (!defined('_MPDF_TTFONTPATH')) { define('_MPDF_TTFONTPATH',_MPDF_PATH.'ttfonts/'); }
72 if (!defined('_MPDF_TTFONTDATAPATH')) { define('_MPDF_TTFONTDATAPATH',_MPDF_PATH.'ttfontdata/'); }
73
74 $errorlevel=error_reporting();
75 $errorlevel=error_reporting($errorlevel & ~E_NOTICE);
76
77 //error_reporting(E_ALL);
78
79 if(function_exists("date_default_timezone_set")) {
80 if (ini_get("date.timezone")=="") { date_default_timezone_set("Europe/London"); }
81 }
82 if (!function_exists("mb_strlen")) { die("Error - mPDF requires mb_string functions. Ensure that PHP is compiled with php_mbstring.dll enabled."); }
83
84 if (!defined('PHP_VERSION_ID')) {
85 $version = explode('.', PHP_VERSION);
86 define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
87 }
88
89 class mPDF
90 {
91
92 ///////////////////////////////
93 // EXTERNAL (PUBLIC) VARIABLES
94 // Define these in config.php
95 ///////////////////////////////
96 var $useFixedNormalLineHeight; // mPDF 6
97 var $useFixedTextBaseline; // mPDF 6
98 var $adjustFontDescLineheight; // mPDF 6
99 var $interpolateImages; // mPDF 6
100 var $defaultPagebreakType; // mPDF 6 pagebreaktype
101
102 var $indexUseSubentries; // mPDF 6
103
104 var $autoScriptToLang; // mPDF 6
105 var $baseScript; // mPDF 6
106 var $autoVietnamese; // mPDF 6
107 var $autoArabic; // mPDF 6
108
109 var $CJKforceend;
110 var $h2bookmarks;
111 var $h2toc;
112 var $decimal_align;
113 var $margBuffer;
114 var $splitTableBorderWidth;
115
116 var $bookmarkStyles;
117 var $useActiveForms;
118
119 var $repackageTTF;
120 var $allowCJKorphans;
121 var $allowCJKoverflow;
122
123 var $useKerning;
124 var $restrictColorSpace;
125 var $bleedMargin;
126 var $crossMarkMargin;
127 var $cropMarkMargin;
128 var $cropMarkLength;
129 var $nonPrintMargin;
130
131 var $PDFX;
132 var $PDFXauto;
133
134 var $PDFA;
135 var $PDFAauto;
136 var $ICCProfile;
137
138 var $printers_info;
139 var $iterationCounter;
140 var $smCapsScale;
141 var $smCapsStretch;
142
143 var $backupSubsFont;
144 var $backupSIPFont;
145 var $debugfonts;
146 var $useAdobeCJK;
147 var $percentSubset;
148 var $maxTTFFilesize;
149 var $BMPonly;
150
151 var $tableMinSizePriority;
152
153 var $dpi;
154 var $watermarkImgAlphaBlend;
155 var $watermarkImgBehind;
156 var $justifyB4br;
157 var $packTableData;
158 var $pgsIns;
159 var $simpleTables;
160 var $enableImports;
161
162 var $debug;
163 var $showStats;
164 var $setAutoTopMargin;
165 var $setAutoBottomMargin;
166 var $autoMarginPadding;
167 var $collapseBlockMargins;
168 var $falseBoldWeight;
169 var $normalLineheight;
170 var $progressBar;
171 var $incrementFPR1;
172 var $incrementFPR2;
173 var $incrementFPR3;
174 var $incrementFPR4;
175
176 var $SHYlang;
177 var $SHYleftmin;
178 var $SHYrightmin;
179 var $SHYcharmin;
180 var $SHYcharmax;
181 var $SHYlanguages;
182 // PageNumber Conditional Text
183 var $pagenumPrefix;
184 var $pagenumSuffix;
185 var $nbpgPrefix;
186 var $nbpgSuffix;
187 var $showImageErrors;
188 var $allow_output_buffering;
189 var $autoPadding;
190 var $useGraphs;
191 var $tabSpaces;
192 var $autoLangToFont;
193 var $watermarkTextAlpha;
194 var $watermarkImageAlpha;
195 var $watermark_size;
196 var $watermark_pos;
197 var $annotSize;
198 var $annotMargin;
199 var $annotOpacity;
200 var $title2annots;
201 var $keepColumns;
202 var $keep_table_proportions;
203 var $ignore_table_widths;
204 var $ignore_table_percents;
205 var $list_number_suffix;
206 var $list_auto_mode; // mPDF 6
207 var $list_indent_first_level; // mPDF 6
208 var $list_indent_default; // mPDF 6
209 var $list_marker_offset; // mPDF 6
210 var $useSubstitutions;
211 var $CSSselectMedia;
212
213 var $forcePortraitHeaders;
214 var $forcePortraitMargins;
215 var $displayDefaultOrientation;
216 var $ignore_invalid_utf8;
217 var $allowedCSStags;
218 var $onlyCoreFonts;
219 var $allow_charset_conversion;
220
221 var $jSWord;
222 var $jSmaxChar;
223 var $jSmaxCharLast;
224 var $jSmaxWordLast;
225
226 var $max_colH_correction;
227
228
229 var $table_error_report;
230 var $table_error_report_param;
231 var $biDirectional;
232 var $text_input_as_HTML;
233 var $anchor2Bookmark;
234 var $shrink_tables_to_fit;
235
236 var $allow_html_optional_endtags;
237
238 var $img_dpi;
239
240 var $defaultheaderfontsize;
241 var $defaultheaderfontstyle;
242 var $defaultheaderline;
243 var $defaultfooterfontsize;
244 var $defaultfooterfontstyle;
245 var $defaultfooterline;
246 var $header_line_spacing;
247 var $footer_line_spacing;
248
249 var $pregCJKchars;
250 var $pregRTLchars;
251 var $pregCURSchars; // mPDF 6
252
253 var $mirrorMargins;
254 var $watermarkText;
255 var $watermarkImage;
256 var $showWatermarkText;
257 var $showWatermarkImage;
258
259 var $fontsizes;
260
261 var $defaultPageNumStyle; // mPDF 6
262
263 //////////////////////
264 // CLASS OBJECTS
265 //////////////////////
266 var $otl; // mPDF 5.7.1
267 var $cssmgr;
268 var $grad;
269 var $bmp;
270 var $wmf;
271 var $tocontents;
272 var $mpdfform;
273 var $directw;
274
275 //////////////////////
276 // INTERNAL VARIABLES
277 //////////////////////
278 var $script2lang;
279 var $viet;
280 var $pashto;
281 var $urdu;
282 var $persian;
283 var $sindhi;
284
285 var $extrapagebreak; // mPDF 6 pagebreaktype
286 var $uniqstr; // mPDF 5.7.2
287 var $hasOC;
288
289 var $textvar; // mPDF 5.7.1
290 var $fontLanguageOverride; // mPDF 5.7.1
291 var $OTLtags; // mPDF 5.7.1
292 var $OTLdata; // mPDF 5.7.1
293 var $writingToC;
294 var $layers;
295 var $current_layer;
296 var $open_layer_pane;
297 var $decimal_offset;
298 var $inMeter;
299
300 var $CJKleading;
301 var $CJKfollowing;
302 var $CJKoverflow;
303
304 var $textshadow;
305
306 var $colsums;
307 var $spanborder;
308 var $spanborddet;
309
310 var $visibility;
311
312 var $useRC128encryption;
313 var $uniqid;
314
315 var $kerning;
316 var $fixedlSpacing;
317 var $minwSpacing;
318 var $lSpacingCSS;
319 var $wSpacingCSS;
320
321 var $spotColorIDs;
322 var $SVGcolors;
323 var $spotColors;
324 var $defTextColor;
325 var $defDrawColor;
326 var $defFillColor;
327
328 var $tableBackgrounds;
329 var $inlineDisplayOff;
330 var $kt_y00;
331 var $kt_p00;
332 var $upperCase;
333 var $checkSIP;
334 var $checkSMP;
335 var $checkCJK;
336
337 var $watermarkImgAlpha;
338 var $PDFAXwarnings;
339 var $MetadataRoot;
340 var $OutputIntentRoot;
341 var $InfoRoot;
342 var $current_filename;
343 var $parsers;
344 var $current_parser;
345 var $_obj_stack;
346 var $_don_obj_stack;
347 var $_current_obj_id;
348 var $tpls;
349 var $tpl;
350 var $tplprefix;
351 var $_res;
352
353 var $pdf_version;
354 var $noImageFile;
355 var $lastblockbottommargin;
356 var $baselineC;
357 // mPDF 5.7.3 inline text-decoration parameters
358 var $baselineSup;
359 var $baselineSub;
360 var $baselineS;
361 var $subPos;
362 var $subArrMB;
363 var $ReqFontStyle;
364 var $tableClipPath ;
365
366 var $fullImageHeight;
367 var $inFixedPosBlock; // Internal flag for position:fixed block
368 var $fixedPosBlock; // Buffer string for position:fixed block
369 var $fixedPosBlockDepth;
370 var $fixedPosBlockBBox;
371 var $fixedPosBlockSave;
372 var $maxPosL;
373 var $maxPosR;
374
375 var $loaded;
376
377 var $extraFontSubsets;
378 var $docTemplateStart; // Internal flag for page (page no. -1) that docTemplate starts on
379 var $time0;
380
381 // Classes
382 var $indic;
383 var $barcode;
384
385 var $SHYpatterns;
386 var $loadedSHYpatterns;
387 var $loadedSHYdictionary;
388 var $SHYdictionary;
389 var $SHYdictionaryWords;
390
391 var $spanbgcolorarray;
392 var $default_font;
393 var $headerbuffer;
394 var $lastblocklevelchange;
395 var $nestedtablejustfinished;
396 var $linebreakjustfinished;
397 var $cell_border_dominance_L;
398 var $cell_border_dominance_R;
399 var $cell_border_dominance_T;
400 var $cell_border_dominance_B;
401 var $table_keep_together;
402 var $plainCell_properties;
403 var $shrin_k1;
404 var $outerfilled;
405
406 var $blockContext;
407 var $floatDivs;
408
409
410 var $patterns;
411 var $pageBackgrounds;
412
413 var $bodyBackgroundGradient;
414 var $bodyBackgroundImage;
415 var $bodyBackgroundColor;
416
417 var $writingHTMLheader; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
418 var $writingHTMLfooter;
419 var $angle;
420
421 var $gradients;
422
423 var $kwt_Reference;
424 var $kwt_BMoutlines;
425 var $kwt_toc;
426
427 var $tbrot_BMoutlines;
428 var $tbrot_toc;
429
430 var $col_BMoutlines;
431 var $col_toc;
432
433 var $currentGraphId;
434 var $graphs;
435
436 var $floatbuffer;
437 var $floatmargins;
438
439 var $bullet;
440 var $bulletarray;
441
442
443 var $currentLang;
444 var $default_lang;
445 var $default_available_fonts;
446 var $pageTemplate;
447 var $docTemplate;
448 var $docTemplateContinue;
449
450 var $arabGlyphs;
451 var $arabHex;
452 var $persianGlyphs;
453 var $persianHex;
454 var $arabVowels;
455 var $arabPrevLink;
456 var $arabNextLink;
457
458
459 var $formobjects; // array of Form Objects for WMF
460 var $InlineProperties;
461 var $InlineAnnots;
462 var $InlineBDF; // mPDF 6 Bidirectional formatting
463 var $InlineBDFctr; // mPDF 6
464 var $ktAnnots;
465 var $tbrot_Annots;
466 var $kwt_Annots;
467 var $columnAnnots;
468 var $columnForms;
469
470 var $PageAnnots;
471
472 var $pageDim; // Keep track of page wxh for orientation changes - set in _beginpage, used in _putannots
473
474 var $breakpoints;
475
476 var $tableLevel;
477 var $tbctr;
478 var $innermostTableLevel;
479 var $saveTableCounter;
480 var $cellBorderBuffer;
481
482 var $saveHTMLFooter_height;
483 var $saveHTMLFooterE_height;
484
485 var $firstPageBoxHeader;
486 var $firstPageBoxHeaderEven;
487 var $firstPageBoxFooter;
488 var $firstPageBoxFooterEven;
489
490 var $page_box;
491 var $show_marks; // crop or cross marks
492
493 var $basepathIsLocal;
494
495 var $use_kwt;
496 var $kwt;
497 var $kwt_height;
498 var $kwt_y0;
499 var $kwt_x0;
500 var $kwt_buffer;
501 var $kwt_Links;
502 var $kwt_moved;
503 var $kwt_saved;
504
505 var $PageNumSubstitutions;
506
507 var $table_borders_separate;
508 var $base_table_properties;
509 var $borderstyles;
510
511 var $blockjustfinished;
512
513 var $orig_bMargin;
514 var $orig_tMargin;
515 var $orig_lMargin;
516 var $orig_rMargin;
517 var $orig_hMargin;
518 var $orig_fMargin;
519
520 var $pageHTMLheaders;
521 var $pageHTMLfooters;
522
523 var $saveHTMLHeader;
524 var $saveHTMLFooter;
525
526 var $HTMLheaderPageLinks;
527 var $HTMLheaderPageAnnots;
528 var $HTMLheaderPageForms;
529
530 // See config_fonts.php for these next 5 values
531 var $available_unifonts;
532 var $sans_fonts;
533 var $serif_fonts;
534 var $mono_fonts;
535 var $defaultSubsFont;
536
537 // List of ALL available CJK fonts (incl. styles) (Adobe add-ons) hw removed
538 var $available_CJK_fonts;
539
540 var $HTMLHeader;
541 var $HTMLFooter;
542 var $HTMLHeaderE;
543 var $HTMLFooterE;
544 var $bufferoutput;
545
546
547 // CJK fonts
548 var $Big5_widths;
549 var $GB_widths;
550 var $SJIS_widths;
551 var $UHC_widths;
552
553 // SetProtection
554 var $encrypted; //whether document is protected
555 var $Uvalue; //U entry in pdf document
556 var $Ovalue; //O entry in pdf document
557 var $Pvalue; //P entry in pdf document
558 var $enc_obj_id; //encryption object id
559 var $last_rc4_key; //last RC4 key encrypted (cached for optimisation)
560 var $last_rc4_key_c; //last RC4 computed key
561 var $encryption_key;
562 var $padding; //used for encryption
563
564
565 // Bookmark
566 var $BMoutlines;
567 var $OutlineRoot;
568 // INDEX
569 var $ColActive;
570 var $Reference;
571 var $CurrCol;
572 var $NbCol;
573 var $y0; //Top ordinate of columns
574 var $ColL;
575 var $ColWidth;
576 var $ColGap;
577 // COLUMNS
578 var $ColR;
579 var $ChangeColumn;
580 var $columnbuffer;
581 var $ColDetails;
582 var $columnLinks;
583 var $colvAlign;
584 // Substitutions
585 var $substitute; // Array of substitution strings e.g. <ttz>112</ttz>
586 var $entsearch; // Array of HTML entities (>ASCII 127) to substitute
587 var $entsubstitute; // Array of substitution decimal unicode for the Hi entities
588
589
590 // Default values if no style sheet offered (cf. http://www.w3.org/TR/CSS21/sample.html)
591 var $defaultCSS;
592
593 var $lastoptionaltag; // Save current block item which HTML specifies optionsl endtag
594 var $pageoutput;
595 var $charset_in;
596 var $blk;
597 var $blklvl;
598 var $ColumnAdjust;
599 var $ws; // Word spacing
600 var $HREF;
601 var $pgwidth;
602 var $fontlist;
603 var $oldx;
604 var $oldy;
605 var $B;
606 var $I;
607
608 var $tdbegin;
609 var $table;
610 var $cell;
611 var $col;
612 var $row;
613
614 var $divbegin;
615 var $divwidth;
616 var $divheight;
617 var $spanbgcolor;
618
619 // mPDF 6 Used for table cell (block-type) properties
620 var $cellTextAlign;
621 var $cellLineHeight;
622 var $cellLineStackingStrategy;
623 var $cellLineStackingShift;
624
625 // mPDF 6 Lists
626 var $listcounter;
627 var $listlvl;
628 var $listtype;
629 var $listitem;
630
631 var $pjustfinished;
632 var $ignorefollowingspaces;
633 var $SMALL;
634 var $BIG;
635 var $dash_on;
636 var $dotted_on;
637
638 var $textbuffer;
639 var $currentfontstyle;
640 var $currentfontfamily;
641 var $currentfontsize;
642 var $colorarray;
643 var $bgcolorarray;
644 var $internallink;
645 var $enabledtags;
646
647 var $lineheight;
648 var $basepath;
649 var $textparam;
650
651 var $specialcontent;
652 var $selectoption;
653 var $objectbuffer;
654
655 // Table Rotation
656 var $table_rotate;
657 var $tbrot_maxw;
658 var $tbrot_maxh;
659 var $tablebuffer;
660 var $tbrot_align;
661 var $tbrot_Links;
662
663 var $keep_block_together; // Keep a Block from page-break-inside: avoid
664
665 var $tbrot_y0;
666 var $tbrot_x0;
667 var $tbrot_w;
668 var $tbrot_h;
669
670 var $mb_enc;
671 var $directionality;
672
673 var $extgstates; // Used for alpha channel - Transparency (Watermark)
674 var $mgl;
675 var $mgt;
676 var $mgr;
677 var $mgb;
678
679 var $tts;
680 var $ttz;
681 var $tta;
682
683 // Best to alter the below variables using default stylesheet above
684 var $page_break_after_avoid;
685 var $margin_bottom_collapse;
686 var $default_font_size; // in pts
687 var $original_default_font_size; // used to save default sizes when using table default
688 var $original_default_font;
689 var $watermark_font;
690 var $defaultAlign;
691
692 // TABLE
693 var $defaultTableAlign;
694 var $tablethead;
695 var $thead_font_weight;
696 var $thead_font_style;
697 var $thead_font_smCaps;
698 var $thead_valign_default;
699 var $thead_textalign_default;
700 var $tabletfoot;
701 var $tfoot_font_weight;
702 var $tfoot_font_style;
703 var $tfoot_font_smCaps;
704 var $tfoot_valign_default;
705 var $tfoot_textalign_default;
706
707 var $trow_text_rotate;
708
709 var $cellPaddingL;
710 var $cellPaddingR;
711 var $cellPaddingT;
712 var $cellPaddingB;
713 var $table_border_attr_set;
714 var $table_border_css_set;
715
716 var $shrin_k; // factor with which to shrink tables - used internally - do not change
717 var $shrink_this_table_to_fit; // 0 or false to disable; value (if set) gives maximum factor to reduce fontsize
718 var $MarginCorrection; // corrects for OddEven Margins
719 var $margin_footer;
720 var $margin_header;
721
722 var $tabletheadjustfinished;
723 var $usingCoreFont;
724 var $charspacing;
725
726 //Private properties FROM FPDF
727 var $DisplayPreferences;
728 var $flowingBlockAttr;
729 var $page; //current page number
730 var $n; //current object number
731 var $offsets; //array of object offsets
732 var $buffer; //buffer holding in-memory PDF
733 var $pages; //array containing pages
734 var $state; //current document state
735 var $compress; //compression flag
736 var $DefOrientation; //default orientation
737 var $CurOrientation; //current orientation
738 var $OrientationChanges; //array indicating orientation changes
739 var $k; //scale factor (number of points in user unit)
740 var $fwPt;
741 var $fhPt; //dimensions of page format in points
742 var $fw;
743 var $fh; //dimensions of page format in user unit
744 var $wPt;
745 var $hPt; //current dimensions of page in points
746 var $w;
747 var $h; //current dimensions of page in user unit
748 var $lMargin; //left margin
749 var $tMargin; //top margin
750 var $rMargin; //right margin
751 var $bMargin; //page break margin
752 var $cMarginL; //cell margin Left
753 var $cMarginR; //cell margin Right
754 var $cMarginT; //cell margin Left
755 var $cMarginB; //cell margin Right
756 var $DeflMargin; //Default left margin
757 var $DefrMargin; //Default right margin
758 var $x;
759 var $y; //current position in user unit for cell positioning
760 var $lasth; //height of last cell printed
761 var $LineWidth; //line width in user unit
762 var $CoreFonts; //array of standard font names
763 var $fonts; //array of used fonts
764 var $FontFiles; //array of font files
765 var $images; //array of used images
766 var $PageLinks; //array of links in pages
767 var $links; //array of internal links
768 var $FontFamily; //current font family
769 var $FontStyle; //current font style
770 var $CurrentFont; //current font info
771 var $FontSizePt; //current font size in points
772 var $FontSize; //current font size in user unit
773 var $DrawColor; //commands for drawing color
774 var $FillColor; //commands for filling color
775 var $TextColor; //commands for text color
776 var $ColorFlag; //indicates whether fill and text colors are different
777 var $autoPageBreak; //automatic page breaking
778 var $PageBreakTrigger; //threshold used to trigger page breaks
779 var $InFooter; //flag set when processing footer
780 var $InHTMLFooter;
781
782 var $processingFooter; //flag set when processing footer - added for columns
783 var $processingHeader; //flag set when processing header - added for columns
784 var $ZoomMode; //zoom display mode
785 var $LayoutMode; //layout display mode
786 var $title; //title
787 var $subject; //subject
788 var $author; //author
789 var $keywords; //keywords
790 var $creator; //creator
791
792 var $aliasNbPg; //alias for total number of pages
793 var $aliasNbPgGp; //alias for total number of pages in page group
794 //var $aliasNbPgHex; // mPDF 6 deleted
795 //var $aliasNbPgGpHex; // mPDF 6 deleted
796
797 var $ispre;
798
799 var $outerblocktags;
800 var $innerblocktags;
801
802
803 // **********************************
804 // **********************************
805 // **********************************
806 // **********************************
807 // **********************************
808 // **********************************
809 // **********************************
810 // **********************************
811 // **********************************
812
813 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') {
814
815 /*-- BACKGROUNDS --*/
816 if (!class_exists('grad', false)) { include(_MPDF_PATH.'classes/grad.php'); }
817 if (empty($this->grad)) { $this->grad = new grad($this); }
818 /*-- END BACKGROUNDS --*/
819 /*-- FORMS --*/
820 if (!class_exists('mpdfform', false)) { include(_MPDF_PATH.'classes/mpdfform.php'); }
821 if (empty($this->mpdfform)) { $this->mpdfform = new mpdfform($this); }
822 /*-- END FORMS --*/
823
824 $this->time0 = microtime(true);
825 //Some checks
826 $this->_dochecks();
827
828 $this->writingToC = false;
829 $this->layers = array();
830 $this->current_layer = 0;
831 $this->open_layer_pane = false;
832
833 $this->visibility='visible';
834
835 //Initialization of properties
836 $this->spotColors=array();
837 $this->spotColorIDs = array();
838 $this->tableBackgrounds = array();
839 $this->uniqstr = '20110230'; // mPDF 5.7.2
840 $this->kt_y00 = '';
841 $this->kt_p00 = '';
842 $this->iterationCounter = false;
843 $this->BMPonly = array();
844 $this->page=0;
845 $this->n=2;
846 $this->buffer='';
847 $this->objectbuffer = array();
848 $this->pages=array();
849 $this->OrientationChanges=array();
850 $this->state=0;
851 $this->fonts=array();
852 $this->FontFiles=array();
853 $this->images=array();
854 $this->links=array();
855 $this->InFooter=false;
856 $this->processingFooter=false;
857 $this->processingHeader=false;
858 $this->lasth=0;
859 $this->FontFamily='';
860 $this->FontStyle='';
861 $this->FontSizePt=9;
862 $this->U=false;
863 // Small Caps
864 $this->upperCase = array();
865 $this->smCapsScale = 1;
866 $this->smCapsStretch = 100;
867 $this->margBuffer = 0;
868 $this->inMeter = false;
869 $this->decimal_offset = 0;
870
871 $this->defTextColor = $this->TextColor = $this->SetTColor($this->ConvertColor(0),true);
872 $this->defDrawColor = $this->DrawColor = $this->SetDColor($this->ConvertColor(0),true);
873 $this->defFillColor = $this->FillColor = $this->SetFColor($this->ConvertColor(255),true);
874
875 //SVG color names array
876 //http://www.w3schools.com/css/css_colornames.asp
877 $this->SVGcolors = array('antiquewhite'=>'#FAEBD7','aqua'=>'#00FFFF','aquamarine'=>'#7FFFD4','beige'=>'#F5F5DC','black'=>'#000000',
878 'blue'=>'#0000FF','brown'=>'#A52A2A','cadetblue'=>'#5F9EA0','chocolate'=>'#D2691E','cornflowerblue'=>'#6495ED','crimson'=>'#DC143C',
879 'darkblue'=>'#00008B','darkgoldenrod'=>'#B8860B','darkgreen'=>'#006400','darkmagenta'=>'#8B008B','darkorange'=>'#FF8C00',
880 'darkred'=>'#8B0000','darkseagreen'=>'#8FBC8F','darkslategray'=>'#2F4F4F','darkviolet'=>'#9400D3','deepskyblue'=>'#00BFFF',
881 'dodgerblue'=>'#1E90FF','firebrick'=>'#B22222','forestgreen'=>'#228B22','fuchsia'=>'#FF00FF','gainsboro'=>'#DCDCDC','gold'=>'#FFD700',
882 'gray'=>'#808080','green'=>'#008000','greenyellow'=>'#ADFF2F','hotpink'=>'#FF69B4','indigo'=>'#4B0082','khaki'=>'#F0E68C',
883 'lavenderblush'=>'#FFF0F5','lemonchiffon'=>'#FFFACD','lightcoral'=>'#F08080','lightgoldenrodyellow'=>'#FAFAD2','lightgreen'=>'#90EE90',
884 'lightsalmon'=>'#FFA07A','lightskyblue'=>'#87CEFA','lightslategray'=>'#778899','lightyellow'=>'#FFFFE0','lime'=>'#00FF00','limegreen'=>'#32CD32',
885 'magenta'=>'#FF00FF','maroon'=>'#800000','mediumaquamarine'=>'#66CDAA','mediumorchid'=>'#BA55D3','mediumseagreen'=>'#3CB371',
886 'mediumspringgreen'=>'#00FA9A','mediumvioletred'=>'#C71585','midnightblue'=>'#191970','mintcream'=>'#F5FFFA','moccasin'=>'#FFE4B5','navy'=>'#000080',
887 'olive'=>'#808000','orange'=>'#FFA500','orchid'=>'#DA70D6','palegreen'=>'#98FB98',
888 'palevioletred'=>'#D87093','peachpuff'=>'#FFDAB9','pink'=>'#FFC0CB','powderblue'=>'#B0E0E6','purple'=>'#800080',
889 'red'=>'#FF0000','royalblue'=>'#4169E1','salmon'=>'#FA8072','seagreen'=>'#2E8B57','sienna'=>'#A0522D','silver'=>'#C0C0C0','skyblue'=>'#87CEEB',
890 'slategray'=>'#708090','springgreen'=>'#00FF7F','steelblue'=>'#4682B4','tan'=>'#D2B48C','teal'=>'#008080','thistle'=>'#D8BFD8','turquoise'=>'#40E0D0',
891 'violetred'=>'#D02090','white'=>'#FFFFFF','yellow'=>'#FFFF00',
892 'aliceblue'=>'#f0f8ff', 'azure'=>'#f0ffff', 'bisque'=>'#ffe4c4', 'blanchedalmond'=>'#ffebcd', 'blueviolet'=>'#8a2be2', 'burlywood'=>'#deb887',
893 'chartreuse'=>'#7fff00', 'coral'=>'#ff7f50', 'cornsilk'=>'#fff8dc', 'cyan'=>'#00ffff', 'darkcyan'=>'#008b8b', 'darkgray'=>'#a9a9a9',
894 'darkgrey'=>'#a9a9a9', 'darkkhaki'=>'#bdb76b', 'darkolivegreen'=>'#556b2f', 'darkorchid'=>'#9932cc', 'darksalmon'=>'#e9967a',
895 'darkslateblue'=>'#483d8b', 'darkslategrey'=>'#2f4f4f', 'darkturquoise'=>'#00ced1', 'deeppink'=>'#ff1493', 'dimgray'=>'#696969',
896 'dimgrey'=>'#696969', 'floralwhite'=>'#fffaf0', 'ghostwhite'=>'#f8f8ff', 'goldenrod'=>'#daa520', 'grey'=>'#808080', 'honeydew'=>'#f0fff0',
897 'indianred'=>'#cd5c5c', 'ivory'=>'#fffff0', 'lavender'=>'#e6e6fa', 'lawngreen'=>'#7cfc00', 'lightblue'=>'#add8e6', 'lightcyan'=>'#e0ffff',
898 'lightgray'=>'#d3d3d3', 'lightgrey'=>'#d3d3d3', 'lightpink'=>'#ffb6c1', 'lightseagreen'=>'#20b2aa', 'lightslategrey'=>'#778899',
899 'lightsteelblue'=>'#b0c4de', 'linen'=>'#faf0e6', 'mediumblue'=>'#0000cd', 'mediumpurple'=>'#9370db', 'mediumslateblue'=>'#7b68ee',
900 'mediumturquoise'=>'#48d1cc', 'mistyrose'=>'#ffe4e1', 'navajowhite'=>'#ffdead', 'oldlace'=>'#fdf5e6', 'olivedrab'=>'#6b8e23', 'orangered'=>'#ff4500',
901 'palegoldenrod'=>'#eee8aa', 'paleturquoise'=>'#afeeee', 'papayawhip'=>'#ffefd5', 'peru'=>'#cd853f', 'plum'=>'#dda0dd', 'rosybrown'=>'#bc8f8f',
902 'saddlebrown'=>'#8b4513', 'sandybrown'=>'#f4a460', 'seashell'=>'#fff5ee', 'slateblue'=>'#6a5acd', 'slategrey'=>'#708090', 'snow'=>'#fffafa',
903 'tomato'=>'#ff6347', 'violet'=>'#ee82ee', 'wheat'=>'#f5deb3', 'whitesmoke'=>'#f5f5f5', 'yellowgreen'=>'#9acd32');
904
905 // Uppercase alternatives (for Small Caps)
906 if (empty($this->upperCase)) { @include(_MPDF_PATH.'includes/upperCase.php'); }
907 $this->extrapagebreak = true; // mPDF 6 pagebreaktype
908
909 $this->ColorFlag=false;
910 $this->extgstates = array();
911
912 $this->mb_enc='windows-1252';
913 $this->directionality='ltr';
914 $this->defaultAlign = 'L';
915 $this->defaultTableAlign = 'L';
916
917 $this->fixedPosBlockSave = array();
918 $this->extraFontSubsets = 0;
919
920 $this->SHYpatterns = array();
921 $this->loadedSHYdictionary = false;
922 $this->SHYdictionary = array();
923 $this->SHYdictionaryWords = array();
924 $this->blockContext = 1;
925 $this->floatDivs = array();
926 $this->DisplayPreferences='';
927
928 $this->patterns = array(); // Tiling patterns used for backgrounds
929 $this->pageBackgrounds = array();
930 $this->writingHTMLheader = false; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
931 $this->writingHTMLfooter = false; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
932 $this->gradients = array();
933
934 $this->kwt_Reference = array();
935 $this->kwt_BMoutlines = array();
936 $this->kwt_toc = array();
937
938 $this->tbrot_BMoutlines = array();
939 $this->tbrot_toc = array();
940
941 $this->col_BMoutlines = array();
942 $this->col_toc = array();
943 $this->graphs = array();
944
945 $this->pgsIns = array();
946 $this->PDFAXwarnings = array();
947 $this->inlineDisplayOff = false;
948 $this->lSpacingCSS = '';
949 $this->wSpacingCSS = '';
950 $this->fixedlSpacing = false;
951 $this->minwSpacing = 0;
952
953
954 $this->baselineC = 0.35; // Baseline for text
955 // mPDF 5.7.3 inline text-decoration parameters
956 $this->baselineSup = 0.5; // Sets default change in baseline for <sup> text as factor of preceeding fontsize
957 // 0.35 has been recommended; 0.5 matches applications like MS Word
958 $this->baselineSub = -0.2; // Sets default change in baseline for <sub> text as factor of preceeding fontsize
959 $this->baselineS = 0.3; // Sets default height for <strike> text as factor of fontsize
960 $this->baselineO = 1.1; // Sets default height for overline text as factor of fontsize
961
962 $this->noImageFile = str_replace("\\","/",dirname(__FILE__)) . '/includes/no_image.jpg';
963 $this->subPos = 0;
964 $this->normalLineheight = 1.3; // This should be overridden in config.php - but it is so important a default value is put here
965 // These are intended as configuration variables, and should be set in config.php - which will override these values;
966 // set here as failsafe as will cause an error if not defined
967 $this->incrementFPR1 = 10;
968 $this->incrementFPR2 = 10;
969 $this->incrementFPR3 = 10;
970 $this->incrementFPR4 = 10;
971
972 $this->fullImageHeight = false;
973 $this->floatbuffer = array();
974 $this->floatmargins = array();
975 $this->formobjects=array(); // array of Form Objects for WMF
976 $this->InlineProperties=array();
977 $this->InlineAnnots=array();
978 $this->InlineBDF=array(); // mPDF 6
979 $this->InlineBDFctr= 0; // mPDF 6
980 $this->tbrot_Annots=array();
981 $this->kwt_Annots=array();
982 $this->columnAnnots=array();
983 $this->pageDim=array();
984 $this->breakpoints = array(); // used in columnbuffer
985 $this->tableLevel=0;
986 $this->tbctr=array(); // counter for nested tables at each level
987 $this->page_box = array();
988 $this->show_marks = ''; // crop or cross marks
989 $this->kwt = false;
990 $this->kwt_height = 0;
991 $this->kwt_y0 = 0;
992 $this->kwt_x0 = 0;
993 $this->kwt_buffer = array();
994 $this->kwt_Links = array();
995 $this->kwt_moved = false;
996 $this->kwt_saved = false;
997 $this->PageNumSubstitutions = array();
998 $this->base_table_properties=array();
999 $this->borderstyles = array('inset','groove','outset','ridge','dotted','dashed','solid','double');
1000 $this->tbrot_align = 'C';
1001
1002 $this->pageHTMLheaders=array();
1003 $this->pageHTMLfooters=array();
1004 $this->HTMLheaderPageLinks = array();
1005 $this->HTMLheaderPageAnnots = array();
1006
1007 $this->HTMLheaderPageForms = array();
1008 $this->columnForms = array();
1009 $this->tbrotForms = array();
1010 $this->useRC128encryption = false;
1011 $this->uniqid = '';
1012
1013 $this->pageoutput = array();
1014
1015 $this->bufferoutput = false;
1016 $this->encrypted=false; //whether document is protected
1017 $this->BMoutlines=array();
1018 $this->ColActive=0; //Flag indicating that columns are on (the index is being processed)
1019 $this->Reference=array(); //Array containing the references
1020 $this->CurrCol=0; //Current column number
1021 $this->ColL = array(0); // Array of Left pos of columns - absolute - needs Margin correction for Odd-Even
1022 $this->ColR = array(0); // Array of Right pos of columns - absolute pos - needs Margin correction for Odd-Even
1023 $this->ChangeColumn = 0;
1024 $this->columnbuffer = array();
1025 $this->ColDetails = array(); // Keeps track of some column details
1026 $this->columnLinks = array(); // Cross references PageLinks
1027 $this->substitute = array(); // Array of substitution strings e.g. <ttz>112</ttz>
1028 $this->entsearch = array(); // Array of HTML entities (>ASCII 127) to substitute
1029 $this->entsubstitute = array(); // Array of substitution decimal unicode for the Hi entities
1030 $this->lastoptionaltag = '';
1031 $this->charset_in = '';
1032 $this->blk = array();
1033 $this->blklvl = 0;
1034 $this->tts = false;
1035 $this->ttz = false;
1036 $this->tta = false;
1037 $this->ispre=false;
1038
1039 $this->checkSIP = false;
1040 $this->checkSMP = false;
1041 $this->checkCJK = false;
1042
1043 $this->page_break_after_avoid = false;
1044 $this->margin_bottom_collapse = false;
1045 $this->tablethead = 0;
1046 $this->tabletfoot = 0;
1047 $this->table_border_attr_set = 0;
1048 $this->table_border_css_set = 0;
1049 $this->shrin_k = 1.0;
1050 $this->shrink_this_table_to_fit = 0;
1051 $this->MarginCorrection = 0;
1052
1053 $this->tabletheadjustfinished = false;
1054 $this->usingCoreFont = false;
1055 $this->charspacing=0;
1056
1057 $this->autoPageBreak = true;
1058
1059 require(_MPDF_PATH.'config.php'); // config data
1060
1061 $this->_setPageSize($format, $orientation);
1062 $this->DefOrientation=$orientation;
1063
1064 $this->margin_header=$mgh;
1065 $this->margin_footer=$mgf;
1066
1067 $bmargin=$mgb;
1068
1069 $this->DeflMargin = $mgl;
1070 $this->DefrMargin = $mgr;
1071
1072 $this->orig_tMargin = $mgt;
1073 $this->orig_bMargin = $bmargin;
1074 $this->orig_lMargin = $this->DeflMargin;
1075 $this->orig_rMargin = $this->DefrMargin;
1076 $this->orig_hMargin = $this->margin_header;
1077 $this->orig_fMargin = $this->margin_footer;
1078
1079 if ($this->setAutoTopMargin=='pad') { $mgt += $this->margin_header; }
1080 if ($this->setAutoBottomMargin=='pad') { $mgb += $this->margin_footer; }
1081 $this->SetMargins($this->DeflMargin,$this->DefrMargin,$mgt); // sets l r t margin
1082 //Automatic page break
1083 $this->SetAutoPageBreak($this->autoPageBreak,$bmargin); // sets $this->bMargin & PageBreakTrigger
1084
1085 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
1086
1087 //Interior cell margin (1 mm) ? not used
1088 $this->cMarginL = 1;
1089 $this->cMarginR = 1;
1090 //Line width (0.2 mm)
1091 $this->LineWidth=.567/_MPDFK;
1092
1093 //To make the function Footer() work - replaces {nb} with page number
1094 $this->AliasNbPages();
1095 $this->AliasNbPageGroups();
1096
1097 //$this->aliasNbPgHex = '{nbHEXmarker}'; // mPDF 6 deleted
1098 //$this->aliasNbPgGpHex = '{nbpgHEXmarker}'; // mPDF 6 deleted
1099
1100 //Enable all tags as default
1101 $this->DisableTags();
1102 //Full width display mode
1103 $this->SetDisplayMode(100); // fullwidth? 'fullpage'
1104 //Compression
1105 $this->SetCompression(true);
1106 //Set default display preferences
1107 $this->SetDisplayPreferences('');
1108
1109 // Font data
1110 require(_MPDF_PATH.'config_fonts.php');
1111 // Available fonts
1112 $this->available_unifonts = array();
1113 foreach ($this->fontdata AS $f => $fs) {
1114 if (isset($fs['R']) && $fs['R']) { $this->available_unifonts[] = $f; }
1115 if (isset($fs['B']) && $fs['B']) { $this->available_unifonts[] = $f.'B'; }
1116 if (isset($fs['I']) && $fs['I']) { $this->available_unifonts[] = $f.'I'; }
1117 if (isset($fs['BI']) && $fs['BI']) { $this->available_unifonts[] = $f.'BI'; }
1118 }
1119
1120 $this->default_available_fonts = $this->available_unifonts;
1121
1122 $optcore = false;
1123 $onlyCoreFonts = false;
1124 if (preg_match('/([\-+])aCJK/i',$mode, $m)) {
1125 $mode = preg_replace('/([\-+])aCJK/i','',$mode); // mPDF 6
1126 if ($m[1]=='+') { $this->useAdobeCJK = true; }
1127 else { $this->useAdobeCJK = false; }
1128 }
1129
1130 if (strlen($mode)==1) {
1131 if ($mode=='s') { $this->percentSubset = 100; $mode = ''; }
1132 else if ($mode=='c') { $onlyCoreFonts = true; $mode = ''; }
1133 }
1134 else if (substr($mode,-2)=='-s') {
1135 $this->percentSubset = 100;
1136 $mode = substr($mode,0,strlen($mode)-2);
1137 }
1138 else if (substr($mode,-2)=='-c') {
1139 $onlyCoreFonts = true;
1140 $mode = substr($mode,0,strlen($mode)-2);
1141 }
1142 else if (substr($mode,-2)=='-x') {
1143 $optcore = true;
1144 $mode = substr($mode,0,strlen($mode)-2);
1145 }
1146
1147 // Autodetect if mode is a language_country string (en-GB or en_GB or en)
1148 if ($mode && $mode != 'UTF-8') { // mPDF 6
1149 list ($coreSuitable,$mpdf_pdf_unifont) = GetLangOpts($mode, $this->useAdobeCJK, $this->fontdata);
1150 if ($coreSuitable && $optcore) { $onlyCoreFonts = true; }
1151 if ($mpdf_pdf_unifont) { // mPDF 6
1152 $default_font = $mpdf_pdf_unifont;
1153 }
1154 $this->currentLang = $mode;
1155 $this->default_lang = $mode;
1156 }
1157
1158 $this->onlyCoreFonts = $onlyCoreFonts;
1159
1160 if ($this->onlyCoreFonts) {
1161 $this->setMBencoding('windows-1252'); // sets $this->mb_enc
1162 }
1163 else {
1164 $this->setMBencoding('UTF-8'); // sets $this->mb_enc
1165 }
1166 @mb_regex_encoding('UTF-8'); // required only for mb_ereg... and mb_split functions
1167
1168
1169 // Adobe CJK fonts
1170 $this->available_CJK_fonts = array('gb','big5','sjis','uhc','gbB','big5B','sjisB','uhcB','gbI','big5I','sjisI','uhcI',
1171 'gbBI','big5BI','sjisBI','uhcBI');
1172
1173
1174 //Standard fonts
1175 $this->CoreFonts=array('ccourier'=>'Courier','ccourierB'=>'Courier-Bold','ccourierI'=>'Courier-Oblique','ccourierBI'=>'Courier-BoldOblique',
1176 'chelvetica'=>'Helvetica','chelveticaB'=>'Helvetica-Bold','chelveticaI'=>'Helvetica-Oblique','chelveticaBI'=>'Helvetica-BoldOblique',
1177 'ctimes'=>'Times-Roman','ctimesB'=>'Times-Bold','ctimesI'=>'Times-Italic','ctimesBI'=>'Times-BoldItalic',
1178 'csymbol'=>'Symbol','czapfdingbats'=>'ZapfDingbats');
1179 $this->fontlist=array("ctimes","ccourier","chelvetica","csymbol","czapfdingbats");
1180
1181 // Substitutions
1182 $this->setHiEntitySubstitutions();
1183
1184 if ($this->onlyCoreFonts) {
1185 $this->useSubstitutions = true;
1186 $this->SetSubstitutions();
1187 }
1188 else { $this->useSubstitutions = false; }
1189
1190 /*-- HTML-CSS --*/
1191
1192 if (!class_exists('cssmgr', false)) { include(_MPDF_PATH .'classes/cssmgr.php'); }
1193 $this->cssmgr = new cssmgr($this);
1194 // mPDF 6
1195 if (file_exists(_MPDF_PATH.'mpdf.css')) {
1196 $css = file_get_contents(_MPDF_PATH.'mpdf.css');
1197 $this->cssmgr->ReadCSS('<style> '.$css.' </style>');
1198 }
1199 /*-- END HTML-CSS --*/
1200
1201 if ($default_font=='') {
1202 if ($this->onlyCoreFonts) {
1203 if (in_array(strtolower($this->defaultCSS['BODY']['FONT-FAMILY']),$this->mono_fonts)) { $default_font = 'ccourier'; }
1204 else if (in_array(strtolower($this->defaultCSS['BODY']['FONT-FAMILY']),$this->sans_fonts)) { $default_font = 'chelvetica'; }
1205 else { $default_font = 'ctimes'; }
1206 }
1207 else { $default_font = $this->defaultCSS['BODY']['FONT-FAMILY']; }
1208 }
1209 if (!$default_font_size) {
1210 $mmsize = $this->ConvertSize($this->defaultCSS['BODY']['FONT-SIZE']);
1211 $default_font_size = $mmsize*(_MPDFK);
1212 }
1213
1214 if ($default_font) { $this->SetDefaultFont($default_font); }
1215 if ($default_font_size) { $this->SetDefaultFontSize($default_font_size); }
1216
1217 $this->SetLineHeight(); // lineheight is in mm
1218
1219 $this->SetFColor($this->ConvertColor(255));
1220 $this->HREF='';
1221 $this->oldy=-1;
1222 $this->B=0;
1223 $this->I=0;
1224
1225 // mPDF 6 Lists
1226 $this->listlvl=0;
1227 $this->listtype=array();
1228 $this->listitem=array();
1229 $this->listcounter=array();
1230
1231 $this->tdbegin=false;
1232 $this->table=array();
1233 $this->cell=array();
1234 $this->col=-1;
1235 $this->row=-1;
1236 $this->cellBorderBuffer = array();
1237
1238 $this->divbegin=false;
1239 // mPDF 6
1240 $this->cellTextAlign='';
1241 $this->cellLineHeight = '';
1242 $this->cellLineStackingStrategy = '';
1243 $this->cellLineStackingShift = '';
1244
1245 $this->divwidth=0;
1246 $this->divheight=0;
1247 $this->spanbgcolor=false;
1248 $this->spanborder=false;
1249 $this->spanborddet=array();
1250
1251 $this->blockjustfinished=false;
1252 $this->ignorefollowingspaces = true; //in order to eliminate exceeding left-side spaces
1253 $this->dash_on=false;
1254 $this->dotted_on=false;
1255 $this->textshadow='';
1256
1257 $this->currentfontfamily='';
1258 $this->currentfontsize='';
1259 $this->currentfontstyle='';
1260 $this->colorarray=''; // mPDF 6
1261 $this->spanbgcolorarray=''; // mPDF 6
1262 $this->textbuffer=array();
1263 $this->internallink=array();
1264 $this->basepath = "";
1265
1266 $this->SetBasePath('');
1267
1268 $this->textparam = array();
1269
1270 $this->specialcontent = '';
1271 $this->selectoption = array();
1272
1273 /*-- IMPORTS --*/
1274
1275 $this->tpls = array();
1276 $this->tpl = 0;
1277 $this->tplprefix = "/TPL";
1278 $this->res = array();
1279 if ($this->enableImports) {
1280 $this->SetImportUse();
1281 }
1282 /*-- END IMPORTS --*/
1283
1284 if ($this->progressBar) { $this->StartProgressBarOutput($this->progressBar) ; } // *PROGRESS-BAR*
1285 }
1286
1287
1288
1289 function _setPageSize($format, &$orientation) {
1290 //Page format
1291 if(is_string($format))
1292 {
1293 if ($format=='') { $format = 'A4'; }
1294 $pfo = 'P';
1295 if(preg_match('/([0-9a-zA-Z]*)-L/i',$format,$m)) { // e.g. A4-L = A4 landscape
1296 $format=$m[1];
1297 $pfo='L';
1298 }
1299 $format = $this->_getPageFormat($format);
1300 if (!$format) { $this->Error('Unknown page format: '.$format); }
1301 else { $orientation = $pfo; }
1302
1303 $this->fwPt=$format[0];
1304 $this->fhPt=$format[1];
1305 }
1306 else
1307 {
1308 if (!$format[0] || !$format[1]) { $this->Error('Invalid page format: '.$format[0].' '.$format[1]); }
1309 $this->fwPt=$format[0]*_MPDFK;
1310 $this->fhPt=$format[1]*_MPDFK;
1311 }
1312 $this->fw=$this->fwPt/_MPDFK;
1313 $this->fh=$this->fhPt/_MPDFK;
1314 //Page orientation
1315 $orientation=strtolower($orientation);
1316 if($orientation=='p' or $orientation=='portrait')
1317 {
1318 $orientation='P';
1319 $this->wPt=$this->fwPt;
1320 $this->hPt=$this->fhPt;
1321 }
1322 elseif($orientation=='l' or $orientation=='landscape')
1323 {
1324 $orientation='L';
1325 $this->wPt=$this->fhPt;
1326 $this->hPt=$this->fwPt;
1327 }
1328 else $this->Error('Incorrect orientation: '.$orientation);
1329 $this->CurOrientation=$orientation;
1330
1331 $this->w=$this->wPt/_MPDFK;
1332 $this->h=$this->hPt/_MPDFK;
1333 }
1334
1335 function _getPageFormat($format) {
1336 switch (strtoupper($format)) {
1337 case '4A0': {$format = array(4767.87,6740.79); break;}
1338 case '2A0': {$format = array(3370.39,4767.87); break;}
1339 case 'A0': {$format = array(2383.94,3370.39); break;}
1340 case 'A1': {$format = array(1683.78,2383.94); break;}
1341 case 'A2': {$format = array(1190.55,1683.78); break;}
1342 case 'A3': {$format = array(841.89,1190.55); break;}
1343 case 'A4': {$format = array(595.28,841.89); break;}
1344 case 'A5': {$format = array(419.53,595.28); break;}
1345 case 'A6': {$format = array(297.64,419.53); break;}
1346 case 'A7': {$format = array(209.76,297.64); break;}
1347 case 'A8': {$format = array(147.40,209.76); break;}
1348 case 'A9': {$format = array(104.88,147.40); break;}
1349 case 'A10': {$format = array(73.70,104.88); break;}
1350 case 'B0': {$format = array(2834.65,4008.19); break;}
1351 case 'B1': {$format = array(2004.09,2834.65); break;}
1352 case 'B2': {$format = array(1417.32,2004.09); break;}
1353 case 'B3': {$format = array(1000.63,1417.32); break;}
1354 case 'B4': {$format = array(708.66,1000.63); break;}
1355 case 'B5': {$format = array(498.90,708.66); break;}
1356 case 'B6': {$format = array(354.33,498.90); break;}
1357 case 'B7': {$format = array(249.45,354.33); break;}
1358 case 'B8': {$format = array(175.75,249.45); break;}
1359 case 'B9': {$format = array(124.72,175.75); break;}
1360 case 'B10': {$format = array(87.87,124.72); break;}
1361 case 'C0': {$format = array(2599.37,3676.54); break;}
1362 case 'C1': {$format = array(1836.85,2599.37); break;}
1363 case 'C2': {$format = array(1298.27,1836.85); break;}
1364 case 'C3': {$format = array(918.43,1298.27); break;}
1365 case 'C4': {$format = array(649.13,918.43); break;}
1366 case 'C5': {$format = array(459.21,649.13); break;}
1367 case 'C6': {$format = array(323.15,459.21); break;}
1368 case 'C7': {$format = array(229.61,323.15); break;}
1369 case 'C8': {$format = array(161.57,229.61); break;}
1370 case 'C9': {$format = array(113.39,161.57); break;}
1371 case 'C10': {$format = array(79.37,113.39); break;}
1372 case 'RA0': {$format = array(2437.80,3458.27); break;}
1373 case 'RA1': {$format = array(1729.13,2437.80); break;}
1374 case 'RA2': {$format = array(1218.90,1729.13); break;}
1375 case 'RA3': {$format = array(864.57,1218.90); break;}
1376 case 'RA4': {$format = array(609.45,864.57); break;}
1377 case 'SRA0': {$format = array(2551.18,3628.35); break;}
1378 case 'SRA1': {$format = array(1814.17,2551.18); break;}
1379 case 'SRA2': {$format = array(1275.59,1814.17); break;}
1380 case 'SRA3': {$format = array(907.09,1275.59); break;}
1381 case 'SRA4': {$format = array(637.80,907.09); break;}
1382 case 'LETTER': {$format = array(612.00,792.00); break;}
1383 case 'LEGAL': {$format = array(612.00,1008.00); break;}
1384 case 'LEDGER': {$format = array(279.00,432.00); break;}
1385 case 'TABLOID': {$format = array(279.00,432.00); break;}
1386 case 'EXECUTIVE': {$format = array(521.86,756.00); break;}
1387 case 'FOLIO': {$format = array(612.00,936.00); break;}
1388 case 'B': {$format=array(362.83,561.26 ); break;} // 'B' format paperback size 128x198mm
1389 case 'A': {$format=array(314.65,504.57 ); break;} // 'A' format paperback size 111x178mm
1390 case 'DEMY': {$format=array(382.68,612.28 ); break;} // 'Demy' format paperback size 135x216mm
1391 case 'ROYAL': {$format=array(433.70,663.30 ); break;} // 'Royal' format paperback size 153x234mm
1392 default: {$format = array(595.28,841.89); break;}
1393 }
1394 return $format;
1395 }
1396
1397
1398 /*-- PROGRESS-BAR --*/
1399 function StartProgressBarOutput($mode=1) {
1400 // must be relative path, or URI (not a file system path)
1401 if (!defined('_MPDF_URI')) {
1402 $this->progressBar = false;
1403 if ($this->debug) { $this->Error("You need to define _MPDF_URI to use the progress bar!"); }
1404 else return false;
1405 }
1406 $this->progressBar = $mode;
1407 if ($this->progbar_altHTML) {
1408 echo $this->progbar_altHTML;
1409 }
1410 else {
1411 echo '<html>
1412 <head>
1413 <title>mPDF File Progress</title>
1414 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1415 <link rel="stylesheet" type="text/css" href="'._MPDF_URI.'progbar.css" />
1416 </head>
1417 <body>
1418 <div class="main">
1419 <div class="heading">'.$this->progbar_heading.'</div>
1420 <div class="demo">
1421 ';
1422 if ($this->progressBar==2) { echo ' <table width="100%"><tr><td style="width: 50%;">
1423 <span class="barheading">Writing HTML code</span> <br/>
1424
1425 <div class="progressBar">
1426 <div id="element1" class="innerBar">&nbsp;</div>
1427 </div>
1428 <span class="code" id="box1"></span>
1429 </td><td style="width: 50%;">
1430 <span class="barheading">Autosizing elements</span> <br/>
1431 <div class="progressBar">
1432 <div id="element4" class="innerBar">&nbsp;</div>
1433 </div>
1434 <span class="code" id="box4"></span>
1435 <br/><br/>
1436 <span class="barheading">Writing Tables</span> <br/>
1437 <div class="progressBar">
1438 <div id="element7" class="innerBar">&nbsp;</div>
1439 </div>
1440 <span class="code" id="box7"></span>
1441 </td></tr>
1442 <tr><td><br /><br /></td><td></td></tr>
1443 <tr><td style="width: 50%;">
1444 '; }
1445 echo ' <span class="barheading">Writing PDF file</span> <br/>
1446 <div class="progressBar">
1447 <div id="element2" class="innerBar">&nbsp;</div>
1448 </div>
1449 <span class="code" id="box2"></span>
1450 ';
1451 if ($this->progressBar==2) { echo '
1452 </td><td style="width: 50%;">
1453 <span class="barheading">Memory usage</span> <br/>
1454 <div class="progressBar">
1455 <div id="element5" class="innerBar">&nbsp;</div>
1456 </div>
1457 <span id="box5">0</span> '.ini_get("memory_limit").'<br />
1458 <br/><br/>
1459 <span class="barheading">Memory usage (peak)</span> <br/>
1460 <div class="progressBar">
1461 <div id="element6" class="innerBar">&nbsp;</div>
1462 </div>
1463 <span id="box6">0</span> '.ini_get("memory_limit").'<br />
1464 </td></tr>
1465 </table>
1466 '; }
1467 echo ' <br/><br/>
1468 <span id="box3"></span>
1469
1470 </div>
1471 ';
1472 }
1473 ob_flush();
1474 flush();
1475 }
1476
1477 function UpdateProgressBar($el,$val,$txt='') {
1478 // $val should be a string - 5 = actual value, +15 = increment
1479
1480 if ($this->progressBar<2) {
1481 if ($el>3) { return; }
1482 else if ($el ==1) { $el = 2; }
1483 }
1484 echo '<script type="text/javascript">';
1485 if ($val) { echo ' document.getElementById(\'element'.$el.'\').style.width=\''.$val.'%\'; '; }
1486 if ($txt) { echo ' document.getElementById(\'box'.$el.'\').innerHTML=\''.$txt.'\'; '; }
1487 if ($this->progressBar==2) {
1488 $m = round(memory_get_usage(true)/1048576);
1489 $m2 = round(memory_get_peak_usage(true)/1048576);
1490 $mem = $m * 100 / (ini_get("memory_limit")+0);
1491 $mem2 = $m2 * 100 / (ini_get("memory_limit")+0);
1492 echo ' document.getElementById(\'element5\').style.width=\''.$mem.'%\'; ';
1493 echo ' document.getElementById(\'element6\').style.width=\''.$mem2.'%\'; ';
1494 echo ' document.getElementById(\'box5\').innerHTML=\''.$m.'MB / \'; ';
1495 echo ' document.getElementById(\'box6\').innerHTML=\''.$m2.'MB / \'; ';
1496 }
1497 echo '</script>'."\n";
1498 ob_flush();
1499 flush();
1500 }
1501 /*-- END PROGRESS-BAR --*/
1502
1503
1504
1505 function RestrictUnicodeFonts($res) {
1506 // $res = array of (Unicode) fonts to restrict to: e.g. norasi|norasiB - language specific
1507 if (count($res)) { // Leave full list of available fonts if passed blank array
1508 $this->available_unifonts = $res;
1509 }
1510 else { $this->available_unifonts = $this->default_available_fonts; }
1511 if (count($this->available_unifonts) == 0) { $this->available_unifonts[] = $this->default_available_fonts[0]; }
1512 $this->available_unifonts = array_values($this->available_unifonts);
1513 }
1514
1515
1516 function setMBencoding($enc) {
1517 if ($this->mb_enc != $enc) {
1518 $this->mb_enc = $enc;
1519 mb_internal_encoding($this->mb_enc);
1520 }
1521 }
1522
1523
1524 function SetMargins($left,$right,$top) {
1525 //Set left, top and right margins
1526 $this->lMargin=$left;
1527 $this->rMargin=$right;
1528 $this->tMargin=$top;
1529 }
1530
1531 function ResetMargins() {
1532 //ReSet left, top margins
1533 if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P' && $this->CurOrientation=='L') {
1534 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
1535 $this->tMargin=$this->orig_rMargin;
1536 $this->bMargin=$this->orig_lMargin;
1537 }
1538 else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS
1539 $this->tMargin=$this->orig_lMargin;
1540 $this->bMargin=$this->orig_rMargin;
1541 }
1542 $this->lMargin=$this->DeflMargin;
1543 $this->rMargin=$this->DefrMargin;
1544 $this->MarginCorrection = 0;
1545 $this->PageBreakTrigger=$this->h-$this->bMargin;
1546 }
1547 else if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
1548 $this->lMargin=$this->DefrMargin;
1549 $this->rMargin=$this->DeflMargin;
1550 $this->MarginCorrection = $this->DefrMargin-$this->DeflMargin;
1551
1552 }
1553 else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS
1554 $this->lMargin=$this->DeflMargin;
1555 $this->rMargin=$this->DefrMargin;
1556 if ($this->mirrorMargins) { $this->MarginCorrection = $this->DeflMargin-$this->DefrMargin; }
1557 }
1558 $this->x=$this->lMargin;
1559
1560 }
1561
1562 function SetLeftMargin($margin) {
1563 //Set left margin
1564 $this->lMargin=$margin;
1565 if($this->page>0 and $this->x<$margin) $this->x=$margin;
1566 }
1567
1568 function SetTopMargin($margin) {
1569 //Set top margin
1570 $this->tMargin=$margin;
1571 }
1572
1573 function SetRightMargin($margin) {
1574 //Set right margin
1575 $this->rMargin=$margin;
1576 }
1577
1578 function SetAutoPageBreak($auto,$margin=0) {
1579 //Set auto page break mode and triggering margin
1580 $this->autoPageBreak=$auto;
1581 $this->bMargin=$margin;
1582 $this->PageBreakTrigger=$this->h-$margin;
1583 }
1584
1585 function SetDisplayMode($zoom,$layout='continuous') {
1586 //Set display mode in viewer
1587 if($zoom=='fullpage' or $zoom=='fullwidth' or $zoom=='real' or $zoom=='default' or !is_string($zoom))
1588 $this->ZoomMode=$zoom;
1589 else
1590 $this->Error('Incorrect zoom display mode: '.$zoom);
1591 if($layout=='single' or $layout=='continuous' or $layout=='two' or $layout=='twoleft' or $layout=='tworight' or $layout=='default')
1592 $this->LayoutMode=$layout;
1593 else
1594 $this->Error('Incorrect layout display mode: '.$layout);
1595 }
1596
1597 function SetCompression($compress) {
1598 //Set page compression
1599 if(function_exists('gzcompress')) $this->compress=$compress;
1600 else $this->compress=false;
1601 }
1602
1603 function SetTitle($title) {
1604 //Title of document // Arrives as UTF-8
1605 $this->title = $title;
1606 }
1607
1608 function SetSubject($subject) {
1609 //Subject of document
1610 $this->subject= $subject;
1611 }
1612
1613 function SetAuthor($author) {
1614 //Author of document
1615 $this->author= $author;
1616 }
1617
1618 function SetKeywords($keywords) {
1619 //Keywords of document
1620 $this->keywords= $keywords;
1621 }
1622
1623 function SetCreator($creator) {
1624 //Creator of document
1625 $this->creator= $creator;
1626 }
1627
1628
1629 function SetAnchor2Bookmark($x) {
1630 $this->anchor2Bookmark = $x;
1631 }
1632
1633 function AliasNbPages($alias='{nb}') {
1634 //Define an alias for total number of pages
1635 $this->aliasNbPg=$alias;
1636 }
1637
1638 function AliasNbPageGroups($alias='{nbpg}') {
1639 //Define an alias for total number of pages in a group
1640 $this->aliasNbPgGp=$alias;
1641 }
1642
1643 function SetAlpha($alpha, $bm='Normal', $return=false, $mode='B') {
1644 // alpha: real value from 0 (transparent) to 1 (opaque)
1645 // bm: blend mode, one of the following:
1646 // Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn,
1647 // HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity
1648 // set alpha for stroking (CA) and non-stroking (ca) operations
1649 // mode determines F (fill) S (stroke) B (both)
1650 if (($this->PDFA || $this->PDFX) && $alpha!=1) {
1651 if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "Image opacity must be 100% (Opacity changed to 100%)"; }
1652 $alpha = 1;
1653 }
1654 $a = array('BM'=>'/'.$bm);
1655 if ($mode=='F' || $mode=='B') $a['ca'] = $alpha; // mPDF 5.7.2
1656 if ($mode=='S' || $mode=='B') $a['CA'] = $alpha; // mPDF 5.7.2
1657 $gs = $this->AddExtGState($a);
1658 if ($return) { return sprintf('/GS%d gs', $gs); }
1659 else { $this->_out(sprintf('/GS%d gs', $gs)); }
1660 }
1661
1662 function AddExtGState($parms) {
1663 $n = count($this->extgstates);
1664 // check if graphics state already exists
1665 for ($i=1; $i<=$n; $i++) {
1666 if (count($this->extgstates[$i]['parms']) == count($parms)) {
1667 $same = true;
1668 foreach($this->extgstates[$i]['parms'] AS $k=>$v) {
1669 if (!isset($parms[$k]) || $parms[$k] != $v) { $same = false; break; }
1670 }
1671 if ($same) { return $i; }
1672 }
1673 }
1674 $n++;
1675 $this->extgstates[$n]['parms'] = $parms;
1676 return $n;
1677 }
1678
1679 function SetVisibility($v) {
1680 if (($this->PDFA || $this->PDFX) && $this->visibility!='visible') { $this->PDFAXwarnings[] = "Cannot set visibility to anything other than full when using PDFA or PDFX"; return ''; }
1681 else if (!$this->PDFA && !$this->PDFX)
1682 $this->pdf_version='1.5';
1683 if($this->visibility!='visible') {
1684 $this->_out('EMC');
1685 $this->hasOC=intval($this->hasOC );
1686 }
1687 if($v=='printonly') {
1688 $this->_out('/OC /OC1 BDC');
1689 $this->hasOC=($this->hasOC | 1);
1690 }
1691 elseif($v=='screenonly') {
1692 $this->_out('/OC /OC2 BDC');
1693 $this->hasOC=($this->hasOC | 2);
1694 }
1695 elseif($v=='hidden') {
1696 $this->_out('/OC /OC3 BDC');
1697 $this->hasOC=($this->hasOC | 4);
1698 }
1699 elseif($v!='visible')
1700 $this->Error('Incorrect visibility: '.$v);
1701 $this->visibility=$v;
1702 }
1703
1704 function Error($msg) {
1705 //Fatal error
1706 header('Content-Type: text/html; charset=utf-8');
1707 die('<B>mPDF error: </B>'.$msg);
1708 }
1709
1710 function Open() {
1711 //Begin document
1712 if($this->state==0) {
1713 // Was is function _begindoc()
1714 // Start document
1715 $this->state=1;
1716 $this->_out('%PDF-'.$this->pdf_version);
1717 $this->_out('%'.chr(226).chr(227).chr(207).chr(211)); // 4 chars > 128 to show binary file
1718 }
1719 }
1720
1721 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1722 // DEPRACATED but included for backwards compatability
1723 // Depracated - can use AddPage for all
1724 function AddPages($a='',$b='', $c='', $d='', $e='',$f='',$g='',$h='',$i='',$j='',$k='',$l='',$m='',$n='',$o='',$p=0,$q=0,$r=0,$s=0,$t='',$u='') {
1725 $this->Error('function AddPages is depracated as of mPDF 6. Please use AddPage or HTML code methods instead.');
1726 }
1727
1728 function startPageNums() { $this->Error('function startPageNums is depracated as of mPDF 6.'); }
1729
1730 function setUnvalidatedText($a='', $b=-1) { $this->Error('function setUnvalidatedText is depracated as of mPDF 6. Please use SetWatermarkText instead.'); }
1731
1732 function SetAutoFont($a) { $this->Error('function SetAutoFont is depracated as of mPDF 6. Please use autoScriptToLang instead. See config.php'); }
1733
1734 function Reference($a) { $this->Error('function Reference is depracated as of mPDF 6. Please use IndexEntry instead.'); }
1735
1736 function ReferenceSee($a,$b) { $this->Error('function ReferenceSee is depracated as of mPDF 6. Please use IndexEntrySee instead.'); }
1737
1738 function CreateReference($a=1, $b='', $c='', $d=3, $e=1, $f='', $g=5, $h='',$i='', $j=false) { $this->Error('function CreateReference is depracated as of mPDF 6. Please use InsertIndex instead.'); }
1739
1740 function CreateIndex($a=1, $b='', $c='', $d=3, $e=1, $f='', $g=5, $h='',$i='', $j=false) { $this->Error('function CreateIndex is depracated as of mPDF 6. Please use InsertIndex instead.'); }
1741
1742 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1743
1744 function Close() {
1745 // Check old Aliases - now depracated mPDF 6
1746 if (isset($this->UnvalidatedText)) { $this->Error('$mpdf->UnvalidatedText is depracated as of mPDF 6. Please use $mpdf->watermarkText instead.'); }
1747 if (isset($this->TopicIsUnvalidated)) { $this->Error('$mpdf->TopicIsUnvalidated is depracated as of mPDF 6. Please use $mpdf->showWatermarkText instead.'); }
1748 if (isset($this->AliasNbPg)) { $this->Error('$mpdf->AliasNbPg is depracated as of mPDF 6. Please use $mpdf->aliasNbPg instead.'); }
1749 if (isset($this->AliasNbPgGp)) { $this->Error('$mpdf->AliasNbPgGp is depracated as of mPDF 6. Please use $mpdf->aliasNbPgGp instead.'); }
1750 if (isset($this->BiDirectional)) { $this->Error('$mpdf->BiDirectional is depracated as of mPDF 6. Please use $mpdf->biDirectional instead.'); }
1751 if (isset($this->Anchor2Bookmark)) { $this->Error('$mpdf->Anchor2Bookmark is depracated as of mPDF 6. Please use $mpdf->anchor2Bookmark instead.'); }
1752 if (isset($this->KeepColumns)) { $this->Error('$mpdf->KeepColumns is depracated as of mPDF 6. Please use $mpdf->keepColumns instead.'); }
1753 if (isset($this->useOddEven)) { $this->Error('$mpdf->useOddEven is depracated as of mPDF 6. Please use $mpdf->mirrorMargins instead.'); }
1754 if (isset($this->useSubstitutionsMB)) { $this->Error('$mpdf->useSubstitutionsMB is depracated as of mPDF 6. Please use $mpdf->useSubstitutions instead.'); }
1755 if (isset($this->useLang)) { $this->Error('$mpdf->useLang is depracated as of mPDF 6. Please use $mpdf->autoLangToFont instead.'); }
1756 if (isset($this->useAutoFont)) { $this->Error('$mpdf->useAutoFont is depracated. Please use $mpdf->autoScriptToLang instead.'); }
1757
1758 if ($this->progressBar) { $this->UpdateProgressBar(2,'2','Closing last page'); } // *PROGRESS-BAR*
1759 //Terminate document
1760 if($this->state==3) return;
1761 if($this->page==0) $this->AddPage($this->CurOrientation);
1762 if (count($this->cellBorderBuffer)) { $this->printcellbuffer(); } // *TABLES*
1763 if ($this->tablebuffer) { $this->printtablebuffer(); } // *TABLES*
1764 /*-- COLUMNS --*/
1765
1766 if ($this->ColActive) {
1767 $this->SetColumns(0);
1768 $this->ColActive = 0;
1769 if (count($this->columnbuffer)) { $this->printcolumnbuffer(); }
1770 }
1771 /*-- END COLUMNS --*/
1772
1773 // BODY Backgrounds
1774 $s = '';
1775
1776 $s .= $this->PrintBodyBackgrounds();
1777
1778 $s .= $this->PrintPageBackgrounds();
1779 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.$this->uniqstr.')/', "\n".$s."\n".'\\1', $this->pages[$this->page]);
1780 $this->pageBackgrounds = array();
1781
1782 if($this->visibility!='visible')
1783 $this->SetVisibility('visible');
1784 $this->EndLayer();
1785
1786 if (!$this->tocontents || !$this->tocontents->TOCmark) { //Page footer
1787 $this->InFooter=true;
1788 $this->Footer();
1789 $this->InFooter=false;
1790 }
1791 if ($this->tocontents && ($this->tocontents->TOCmark || count($this->tocontents->m_TOC))) { $this->tocontents->insertTOC(); } // *TOC*
1792
1793 //Close page
1794 $this->_endpage();
1795
1796 //Close document
1797 $this->_enddoc();
1798 }
1799
1800 /*-- BACKGROUNDS --*/
1801 function _resizeBackgroundImage($imw, $imh, $cw, $ch, $resize=0, $repx, $repy, $pba=array(), $size=array()) {
1802 // pba is background positioning area (from CSS background-origin) may not always be set [x,y,w,h]
1803 // size is from CSS3 background-size - takes precendence over old resize
1804 // $w - absolute length or % or auto or cover | contain
1805 // $h - absolute length or % or auto or cover | contain
1806 if (isset($pba['w'])) $cw = $pba['w'];
1807 if (isset($pba['h'])) $ch = $pba['h'];
1808
1809 $cw = $cw*_MPDFK;
1810 $ch = $ch*_MPDFK;
1811 if (empty($size) && !$resize) { return array($imw, $imh, $repx, $repy); }
1812
1813 if (isset($size['w']) && $size['w']) {
1814 if ($size['w']=='contain') {
1815 // 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.
1816 // Same as resize==3
1817 $h = $imh * $cw/$imw;
1818 $w = $cw;
1819 if ($h > $ch) {
1820 $w = $w * $ch/$h;
1821 $h = $ch;
1822 }
1823 }
1824 else if ($size['w']=='cover') {
1825 // 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.
1826 $h = $imh * $cw/$imw;
1827 $w = $cw;
1828 if ($h < $ch) {
1829 $w = $w * $h/$ch;
1830 $h = $ch;
1831 }
1832 }
1833 else {
1834 if (stristr($size['w'] ,'%')) {
1835 $size['w'] += 0;
1836 $size['w'] /= 100;
1837 $size['w'] = ($cw * $size['w']);
1838 }
1839 if (stristr($size['h'] ,'%')) {
1840 $size['h'] += 0;
1841 $size['h'] /= 100;
1842 $size['h'] = ($ch * $size['h']);
1843 }
1844 if ($size['w']=='auto' && $size['h']=='auto') {
1845 $w = $imw;
1846 $h = $imh;
1847 }
1848 else if ($size['w']=='auto' && $size['h']!='auto') {
1849 $w = $imw * $size['h']/$imh;
1850 $h = $size['h'];
1851 }
1852 else if ($size['w']!='auto' && $size['h']=='auto') {
1853 $h = $imh * $size['w']/$imw;
1854 $w = $size['w'];
1855 }
1856 else {
1857 $w = $size['w'];
1858 $h = $size['h'];
1859 }
1860 }
1861 return array($w, $h, $repx, $repy);
1862 }
1863 else if ($resize==1 && $imw > $cw) {
1864 $h = $imh * $cw/$imw;
1865 return array($cw, $h, $repx, $repy);
1866 }
1867 else if ($resize==2 && $imh > $ch) {
1868 $w = $imw * $ch/$imh;
1869 return array($w, $ch, $repx, $repy);
1870 }
1871 else if ($resize==3) {
1872 $w = $imw;
1873 $h = $imh;
1874 if ($w > $cw) {
1875 $h = $h * $cw/$w;
1876 $w = $cw;
1877 }
1878 if ($h > $ch) {
1879 $w = $w * $ch/$h;
1880 $h = $ch;
1881 }
1882 return array($w, $h, $repx, $repy);
1883 }
1884 else if ($resize==4) {
1885 $h = $imh * $cw/$imw;
1886 return array($cw, $h, $repx, $repy);
1887 }
1888 else if ($resize==5) {
1889 $w = $imw * $ch/$imh;
1890 return array($w, $ch, $repx, $repy);
1891 }
1892 else if ($resize==6) {
1893 return array($cw, $ch, $repx, $repy);
1894 }
1895 return array($imw, $imh, $repx, $repy);
1896 }
1897
1898
1899 function SetBackground(&$properties, &$maxwidth) {
1900 if (isset($properties['BACKGROUND-ORIGIN']) && ($properties['BACKGROUND-ORIGIN']=='border-box' || $properties['BACKGROUND-ORIGIN']== 'content-box')) { $origin = $properties['BACKGROUND-ORIGIN']; }
1901 else { $origin = 'padding-box'; }
1902 if (isset($properties['BACKGROUND-SIZE'])) {
1903 if (stristr($properties['BACKGROUND-SIZE'] ,'contain') ) { $bsw = $bsh = 'contain'; }
1904 else if (stristr($properties['BACKGROUND-SIZE'] ,'cover') ) { $bsw = $bsh = 'cover'; }
1905 else {
1906 $bsw = $bsh = 'auto';
1907 $sz = preg_split('/\s+/',trim($properties['BACKGROUND-SIZE']));
1908 if (count($sz)==2) { $bsw = $sz[0]; $bsh = $sz[1]; }
1909 else { $bsw = $sz[0]; }
1910 if (!stristr($bsw ,'%') && !stristr($bsw ,'auto') ) { $bsw = $this->ConvertSize($bsw ,$maxwidth,$this->FontSize); }
1911 if (!stristr($bsh ,'%') && !stristr($bsh ,'auto') ) { $bsh = $this->ConvertSize($bsh ,$maxwidth,$this->FontSize); }
1912 }
1913 $size = array('w'=>$bsw, 'h'=>$bsh);
1914 }
1915 else { $size = false; } // mPDF 6
1916 if (preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/',$properties['BACKGROUND-IMAGE'])) {
1917 return array('gradient'=>$properties['BACKGROUND-IMAGE'], 'origin'=>$origin, 'size'=>$size );
1918 }
1919 else {
1920 $file = $properties['BACKGROUND-IMAGE'];
1921 $sizesarray = $this->Image($file,0,0,0,0,'','',false, false, false, false, true);
1922 if (isset($sizesarray['IMAGE_ID'])) {
1923 $image_id = $sizesarray['IMAGE_ID'];
1924 $orig_w = $sizesarray['WIDTH']*_MPDFK; // in user units i.e. mm
1925 $orig_h = $sizesarray['HEIGHT']*_MPDFK; // (using $this->img_dpi)
1926 if (isset($properties['BACKGROUND-IMAGE-RESOLUTION'])) {
1927 if (preg_match('/from-image/i', $properties['BACKGROUND-IMAGE-RESOLUTION']) && isset($sizesarray['set-dpi']) && $sizesarray['set-dpi']>0) {
1928 $orig_w *= $this->img_dpi / $sizesarray['set-dpi'];
1929 $orig_h *= $this->img_dpi / $sizesarray['set-dpi'];
1930 }
1931 else if (preg_match('/(\d+)dpi/i', $properties['BACKGROUND-IMAGE-RESOLUTION'], $m)) {
1932 $dpi = $m[1];
1933 if ($dpi > 0) {
1934 $orig_w *= $this->img_dpi / $dpi;
1935 $orig_h *= $this->img_dpi / $dpi;
1936 }
1937 }
1938 }
1939 $x_repeat = true;
1940 $y_repeat = true;
1941 if (isset($properties['BACKGROUND-REPEAT'])) {
1942 if ($properties['BACKGROUND-REPEAT']=='no-repeat' || $properties['BACKGROUND-REPEAT']=='repeat-x') { $y_repeat = false; }
1943 if ($properties['BACKGROUND-REPEAT']=='no-repeat' || $properties['BACKGROUND-REPEAT']=='repeat-y') { $x_repeat = false; }
1944 }
1945 $x_pos = 0;
1946 $y_pos = 0;
1947 if (isset($properties['BACKGROUND-POSITION'])) {
1948 $ppos = preg_split('/\s+/',$properties['BACKGROUND-POSITION']);
1949 $x_pos = $ppos[0];
1950 $y_pos = $ppos[1];
1951 if (!stristr($x_pos ,'%') ) { $x_pos = $this->ConvertSize($x_pos ,$maxwidth,$this->FontSize); }
1952 if (!stristr($y_pos ,'%') ) { $y_pos = $this->ConvertSize($y_pos ,$maxwidth,$this->FontSize); }
1953 }
1954 if (isset($properties['BACKGROUND-IMAGE-RESIZE'])) { $resize = $properties['BACKGROUND-IMAGE-RESIZE']; }
1955 else { $resize = 0; }
1956 if (isset($properties['BACKGROUND-IMAGE-OPACITY'])) { $opacity = $properties['BACKGROUND-IMAGE-OPACITY']; }
1957 else { $opacity = 1; }
1958 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 );
1959 }
1960 }
1961 return false;
1962 }
1963 /*-- END BACKGROUNDS --*/
1964
1965 function PrintBodyBackgrounds() {
1966 $s = '';
1967 $clx = 0;
1968 $cly = 0;
1969 $clw = $this->w;
1970 $clh = $this->h;
1971 // If using bleed and trim margins in paged media
1972 if ($this->pageDim[$this->page]['outer_width_LR'] || $this->pageDim[$this->page]['outer_width_TB']) {
1973 $clx = $this->pageDim[$this->page]['outer_width_LR'] - $this->pageDim[$this->page]['bleedMargin'];
1974 $cly = $this->pageDim[$this->page]['outer_width_TB'] - $this->pageDim[$this->page]['bleedMargin'];
1975 $clw = $this->w - 2*$clx;
1976 $clh = $this->h - 2*$cly;
1977 }
1978
1979 if ($this->bodyBackgroundColor) {
1980 $s .= 'q ' .$this->SetFColor($this->bodyBackgroundColor, true)."\n";
1981 if ($this->bodyBackgroundColor{0}==5) { // RGBa
1982 $s .= $this->SetAlpha(ord($this->bodyBackgroundColor{4})/100, 'Normal', true, 'F')."\n";
1983 }
1984 else if ($this->bodyBackgroundColor{0}==6) { // CMYKa
1985 $s .= $this->SetAlpha(ord($this->bodyBackgroundColor{5})/100, 'Normal', true, 'F')."\n";
1986 }
1987 $s .= sprintf('%.3F %.3F %.3F %.3F re f Q', ($clx*_MPDFK), ($cly*_MPDFK),$clw*_MPDFK,$clh*_MPDFK)."\n";
1988 }
1989
1990 /*-- BACKGROUNDS --*/
1991 if ($this->bodyBackgroundGradient) {
1992 $g = $this->grad->parseBackgroundGradient($this->bodyBackgroundGradient);
1993 if ($g) {
1994 $s .= $this->grad->Gradient($clx, $cly, $clw, $clh, (isset($g['gradtype']) ? $g['gradtype'] : null), $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true);
1995 }
1996 }
1997 if ($this->bodyBackgroundImage) {
1998 if (isset($this->bodyBackgroundImage['gradient']) && $this->bodyBackgroundImage['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $this->bodyBackgroundImage['gradient'])) {
1999 $g = $this->grad->parseMozGradient( $this->bodyBackgroundImage['gradient']);
2000 if ($g) {
2001 $s .= $this->grad->Gradient($clx, $cly, $clw, $clh, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true);
2002 }
2003 }
2004 else if ($this->bodyBackgroundImage['image_id']) { // Background pattern
2005 $n = count($this->patterns)+1;
2006 // If using resize, uses TrimBox (not including the bleed)
2007 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']);
2008
2009 $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']);
2010 if (($this->bodyBackgroundImage['opacity']>0 || $this->bodyBackgroundImage['opacity']==='0') && $this->bodyBackgroundImage['opacity']<1) { $opac = $this->SetAlpha($this->bodyBackgroundImage['opacity'],'Normal',true); }
2011 else { $opac = ''; }
2012 $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";
2013 }
2014 }
2015 /*-- END BACKGROUNDS --*/
2016 return $s;
2017 }
2018
2019 function _setClippingPath($clx, $cly, $clw, $clh) {
2020 $s = ' q 0 w '; // Line width=0
2021 $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
2022 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
2023 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
2024 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
2025 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
2026 $s .= ' W n '; // Ends path no-op & Sets the clipping path
2027 return $s;
2028 }
2029
2030
2031 function PrintPageBackgrounds($adjustmenty=0) {
2032 $s = '';
2033
2034 ksort($this->pageBackgrounds);
2035 foreach($this->pageBackgrounds AS $bl=>$pbs) {
2036 foreach ($pbs AS $pb) {
2037 if ((!isset($pb['image_id']) && !isset($pb['gradient'])) || isset($pb['shadowonly'])) { // Background colour or boxshadow
2038 if($pb['z-index']>0) {
2039 $this->current_layer = $pb['z-index'];
2040 $s .= "\n".'/OCBZ-index /ZI'.$pb['z-index'].' BDC'."\n";
2041 }
2042
2043 if($pb['visibility']!='visible') {
2044 if($pb['visibility']=='printonly')
2045 $s .= '/OC /OC1 BDC'."\n";
2046 else if($pb['visibility']=='screenonly')
2047 $s .= '/OC /OC2 BDC'."\n";
2048 else if($pb['visibility']=='hidden')
2049 $s .= '/OC /OC3 BDC'."\n";
2050 }
2051 // Box shadow
2052 if (isset($pb['shadow']) && $pb['shadow']) { $s .= $pb['shadow']."\n"; }
2053 if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2054 $s .= 'q '.$this->SetFColor($pb['col'], true)."\n";
2055 if ($pb['col']{0}==5) { // RGBa
2056 $s .= $this->SetAlpha(ord($pb['col']{4})/100, 'Normal', true, 'F')."\n";
2057 }
2058 else if ($pb['col']{0}==6) { // CMYKa
2059 $s .= $this->SetAlpha(ord($pb['col']{5})/100, 'Normal', true, 'F')."\n";
2060 }
2061 $s .= sprintf('%.3F %.3F %.3F %.3F re f Q',$pb['x']*_MPDFK,($this->h-$pb['y'])*_MPDFK,$pb['w']*_MPDFK,-$pb['h']*_MPDFK)."\n";
2062 if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2063 if($pb['visibility']!='visible')
2064 $s .= 'EMC'."\n";
2065
2066 if($pb['z-index']>0) {
2067 $s .= "\n".'EMCBZ-index'."\n";
2068 $this->current_layer = 0;
2069 }
2070 }
2071 }
2072 /*-- BACKGROUNDS --*/
2073 foreach ($pbs AS $pb) {
2074 if ((isset($pb['gradient']) && $pb['gradient']) || (isset($pb['image_id']) && $pb['image_id'])) {
2075 if($pb['z-index']>0) {
2076 $this->current_layer = $pb['z-index'];
2077 $s .= "\n".'/OCGZ-index /ZI'.$pb['z-index'].' BDC'."\n";
2078 }
2079 if($pb['visibility']!='visible') {
2080 if($pb['visibility']=='printonly')
2081 $s .= '/OC /OC1 BDC'."\n";
2082 else if($pb['visibility']=='screenonly')
2083 $s .= '/OC /OC2 BDC'."\n";
2084 else if($pb['visibility']=='hidden')
2085 $s .= '/OC /OC3 BDC'."\n";
2086 }
2087 }
2088 if (isset($pb['gradient']) && $pb['gradient']) {
2089 if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2090 $s .= $this->grad->Gradient($pb['x'], $pb['y'], $pb['w'], $pb['h'], $pb['gradtype'], $pb['stops'], $pb['colorspace'], $pb['coords'], $pb['extend'], true);
2091 if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2092 }
2093 else if (isset($pb['image_id']) && $pb['image_id']) { // Background Image
2094 $pb['y'] -= $adjustmenty;
2095 $pb['h'] += $adjustmenty;
2096 $n = count($this->patterns)+1;
2097 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']);
2098 $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']);
2099 $x = $pb['x']*_MPDFK;
2100 $y = ($this->h - $pb['y'])*_MPDFK;
2101 $w = $pb['w']*_MPDFK;
2102 $h = -$pb['h']*_MPDFK;
2103 if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2104 if ($this->writingHTMLfooter || $this->writingHTMLheader) { // Write each (tiles) image rather than use as a pattern
2105 $iw = $pb['orig_w']/_MPDFK;
2106 $ih = $pb['orig_h']/_MPDFK;
2107
2108 $w = $pb['w'];
2109 $h = $pb['h'];
2110 $x0 = $pb['x'];
2111 $y0 = $pb['y'];
2112
2113 if (isset($pb['bpa']) && $pb['bpa']) {
2114 $w = $pb['bpa']['w'];
2115 $h = $pb['bpa']['h'];
2116 $x0 = $pb['bpa']['x'];
2117 $y0 = $pb['bpa']['y'];
2118 }
2119
2120 if (isset($pb['size']['w']) && $pb['size']['w']) {
2121 $size = $pb['size'];
2122
2123 if ($size['w']=='contain') {
2124 // 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.
2125 // Same as resize==3
2126 $ih = $ih * $pb['bpa']['w']/$iw;
2127 $iw = $pb['bpa']['w'];
2128 if ($ih > $pb['bpa']['h']) {
2129 $iw = $iw * $pb['bpa']['h']/$ih;
2130 $ih = $pb['bpa']['h'];
2131 }
2132 }
2133 else if ($size['w']=='cover') {
2134 // 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.
2135 $ih = $ih * $pb['bpa']['w']/$iw;
2136 $iw = $pb['bpa']['w'];
2137 if ($ih < $pb['bpa']['h']) {
2138 $iw = $iw * $ih/$pb['bpa']['h'];
2139 $ih = $pb['bpa']['h'];
2140 }
2141 }
2142 else {
2143 if (stristr($size['w'] ,'%')) {
2144 $size['w'] += 0;
2145 $size['w'] /= 100;
2146 $size['w'] = ($pb['bpa']['w'] * $size['w']);
2147 }
2148 if (stristr($size['h'] ,'%')) {
2149 $size['h'] += 0;
2150 $size['h'] /= 100;
2151 $size['h'] = ($pb['bpa']['h'] * $size['h']);
2152 }
2153 if ($size['w']=='auto' && $size['h']=='auto') {
2154 $iw = $iw;
2155 $ih = $ih;
2156 }
2157 else if ($size['w']=='auto' && $size['h']!='auto') {
2158 $iw = $iw * $size['h']/$ih;
2159 $ih = $size['h'];
2160 }
2161 else if ($size['w']!='auto' && $size['h']=='auto') {
2162 $ih = $ih * $size['w']/$iw;
2163 $iw = $size['w'];
2164 }
2165 else {
2166 $iw = $size['w'];
2167 $ih = $size['h'];
2168 }
2169 }
2170 }
2171
2172 // Number to repeat
2173 if ($pb['x_repeat']) { $nx = ceil($pb['w']/$iw)+1; }
2174 else { $nx = 1; }
2175 if ($pb['y_repeat']) { $ny = ceil($pb['h']/$ih)+1; }
2176 else { $ny = 1; }
2177
2178 $x_pos = $pb['x_pos'];
2179 if (stristr($x_pos ,'%') ) {
2180 $x_pos += 0;
2181 $x_pos /= 100;
2182 $x_pos = ($pb['bpa']['w'] * $x_pos) - ($iw * $x_pos);
2183 }
2184 $y_pos = $pb['y_pos'];
2185 if (stristr($y_pos ,'%') ) {
2186 $y_pos += 0;
2187 $y_pos /= 100;
2188 $y_pos = ($pb['bpa']['h'] * $y_pos) - ($ih * $y_pos);
2189 }
2190 if ($nx>1) {
2191 while($x_pos>($pb['x']-$pb['bpa']['x'])) { $x_pos -= $iw; }
2192 }
2193 if ($ny>1) {
2194 while($y_pos>($pb['y']-$pb['bpa']['y'])) { $y_pos -= $ih; }
2195 }
2196 for($xi=0;$xi<$nx;$xi++) {
2197 for($yi=0;$yi<$ny;$yi++) {
2198 $x = $x0 + $x_pos + ($iw*$xi);
2199 $y = $y0 + $y_pos + ($ih*$yi);
2200 if ($pb['opacity']>0 && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
2201 else { $opac = ''; }
2202 $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";
2203 }
2204 }
2205 }
2206 else {
2207 if (($pb['opacity']>0 || $pb['opacity']==='0') && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
2208 else { $opac = ''; }
2209 $s .= sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $x, $y, $w, $h) ."\n";
2210 }
2211 if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2212 }
2213 if ((isset($pb['gradient']) && $pb['gradient']) || (isset($pb['image_id']) && $pb['image_id'])) {
2214 if($pb['visibility']!='visible')
2215 $s .= 'EMC'."\n";
2216
2217 if($pb['z-index']>0) {
2218 $s .= "\n".'EMCGZ-index'."\n";
2219 $this->current_layer = 0;
2220 }
2221 }
2222
2223 }
2224 /*-- END BACKGROUNDS --*/
2225 }
2226 return $s;
2227 }
2228
2229 function PrintTableBackgrounds($adjustmenty=0) {
2230 $s = '';
2231 /*-- BACKGROUNDS --*/
2232 ksort($this->tableBackgrounds);
2233 foreach($this->tableBackgrounds AS $bl=>$pbs) {
2234 foreach ($pbs AS $pb) {
2235 if ((!isset($pb['gradient']) || !$pb['gradient']) && (!isset($pb['image_id']) || !$pb['image_id'])) {
2236 $s .= 'q '.$this->SetFColor($pb['col'], true)."\n";
2237 if ($pb['col']{0}==5) { // RGBa
2238 $s .= $this->SetAlpha(ord($pb['col']{4})/100, 'Normal', true, 'F')."\n";
2239 }
2240 else if ($pb['col']{0}==6) { // CMYKa
2241 $s .= $this->SetAlpha(ord($pb['col']{5})/100, 'Normal', true, 'F')."\n";
2242 }
2243 $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";
2244 }
2245 if (isset($pb['gradient']) && $pb['gradient']) {
2246 if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2247 $s .= $this->grad->Gradient($pb['x'], $pb['y'], $pb['w'], $pb['h'], $pb['gradtype'], $pb['stops'], $pb['colorspace'], $pb['coords'], $pb['extend'], true);
2248 if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2249 }
2250 if (isset($pb['image_id']) && $pb['image_id']) { // Background pattern
2251 $pb['y'] -= $adjustmenty;
2252 $pb['h'] += $adjustmenty;
2253 $n = count($this->patterns)+1;
2254 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']);
2255 $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']);
2256 $x = $pb['x']*_MPDFK;
2257 $y = ($this->h - $pb['y'])*_MPDFK;
2258 $w = $pb['w']*_MPDFK;
2259 $h = -$pb['h']*_MPDFK;
2260
2261 // mPDF 5.7.3
2262 if (($this->writingHTMLfooter || $this->writingHTMLheader) && (!isset($pb['clippath']) || $pb['clippath']=='') ) {
2263 // Set clipping path
2264 $pb['clippath'] = sprintf(' q 0 w %.3F %.3F m %.3F %.3F l %.3F %.3F l %.3F %.3F l %.3F %.3F l W n ', $x, $y, $x, $y+$h, $x+$w, $y+$h, $x+$w, $y, $x, $y);
2265 }
2266
2267 if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2268
2269 // mPDF 5.7.3
2270 if ($this->writingHTMLfooter || $this->writingHTMLheader) { // Write each (tiles) image rather than use as a pattern
2271 $iw = $pb['orig_w']/_MPDFK;
2272 $ih = $pb['orig_h']/_MPDFK;
2273
2274 $w = $pb['w'];
2275 $h = $pb['h'];
2276 $x0 = $pb['x'];
2277 $y0 = $pb['y'];
2278
2279 if (isset($pb['bpa']) && $pb['bpa']) {
2280 $w = $pb['bpa']['w'];
2281 $h = $pb['bpa']['h'];
2282 $x0 = $pb['bpa']['x'];
2283 $y0 = $pb['bpa']['y'];
2284 }
2285 // At present 'bpa' (background page area) is not set for tablebackgrounds - only pagebackgrounds
2286 // For now, just set it as:
2287 else {
2288 $pb['bpa'] = array('x'=>$x0, 'y'=>$y0, 'w'=>$w, 'h'=>$h);
2289 }
2290
2291 if (isset($pb['size']['w']) && $pb['size']['w']) {
2292 $size = $pb['size'];
2293
2294 if ($size['w']=='contain') {
2295 // 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.
2296 // Same as resize==3
2297 $ih = $ih * $pb['bpa']['w']/$iw;
2298 $iw = $pb['bpa']['w'];
2299 if ($ih > $pb['bpa']['h']) {
2300 $iw = $iw * $pb['bpa']['h']/$ih;
2301 $ih = $pb['bpa']['h'];
2302 }
2303 }
2304 else if ($size['w']=='cover') {
2305 // 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.
2306 $ih = $ih * $pb['bpa']['w']/$iw;
2307 $iw = $pb['bpa']['w'];
2308 if ($ih < $pb['bpa']['h']) {
2309 $iw = $iw * $ih/$pb['bpa']['h'];
2310 $ih = $pb['bpa']['h'];
2311 }
2312 }
2313 else {
2314 if (stristr($size['w'] ,'%')) {
2315 $size['w'] += 0;
2316 $size['w'] /= 100;
2317 $size['w'] = ($pb['bpa']['w'] * $size['w']);
2318 }
2319 if (stristr($size['h'] ,'%')) {
2320 $size['h'] += 0;
2321 $size['h'] /= 100;
2322 $size['h'] = ($pb['bpa']['h'] * $size['h']);
2323 }
2324 if ($size['w']=='auto' && $size['h']=='auto') {
2325 $iw = $iw;
2326 $ih = $ih;
2327 }
2328 else if ($size['w']=='auto' && $size['h']!='auto') {
2329 $iw = $iw * $size['h']/$ih;
2330 $ih = $size['h'];
2331 }
2332 else if ($size['w']!='auto' && $size['h']=='auto') {
2333 $ih = $ih * $size['w']/$iw;
2334 $iw = $size['w'];
2335 }
2336 else {
2337 $iw = $size['w'];
2338 $ih = $size['h'];
2339 }
2340 }
2341 }
2342
2343 // Number to repeat
2344 if (isset($pb['x_repeat']) && $pb['x_repeat']) { $nx = ceil($pb['w']/$iw)+1; }
2345 else { $nx = 1; }
2346 if (isset($pb['y_repeat']) && $pb['y_repeat']) { $ny = ceil($pb['h']/$ih)+1; }
2347 else { $ny = 1; }
2348
2349 $x_pos = $pb['x_pos'];
2350 if (stristr($x_pos ,'%') ) {
2351 $x_pos += 0;
2352 $x_pos /= 100;
2353 $x_pos = ($pb['bpa']['w'] * $x_pos) - ($iw * $x_pos);
2354 }
2355 $y_pos = $pb['y_pos'];
2356 if (stristr($y_pos ,'%') ) {
2357 $y_pos += 0;
2358 $y_pos /= 100;
2359 $y_pos = ($pb['bpa']['h'] * $y_pos) - ($ih * $y_pos);
2360 }
2361 if ($nx>1) {
2362 while($x_pos>($pb['x']-$pb['bpa']['x'])) { $x_pos -= $iw; }
2363 }
2364 if ($ny>1) {
2365 while($y_pos>($pb['y']-$pb['bpa']['y'])) { $y_pos -= $ih; }
2366 }
2367 for($xi=0;$xi<$nx;$xi++) {
2368 for($yi=0;$yi<$ny;$yi++) {
2369 $x = $x0 + $x_pos + ($iw*$xi);
2370 $y = $y0 + $y_pos + ($ih*$yi);
2371 if ($pb['opacity']>0 && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
2372 else { $opac = ''; }
2373 $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";
2374 }
2375 }
2376 }
2377 else {
2378 if (($pb['opacity']>0 || $pb['opacity']==='0') && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
2379 else { $opac = ''; }
2380 $s .= sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $x, $y, $w, $h) ."\n";
2381 }
2382
2383 if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2384 }
2385 }
2386 }
2387 /*-- END BACKGROUNDS --*/
2388 return $s;
2389 }
2390
2391 function BeginLayer($id) {
2392 if($this->current_layer>0) $this->EndLayer();
2393 if ($id < 1) { return false; }
2394 if (!isset($this->layers[$id])) {
2395 $this->layers[$id] = array('name'=>'Layer '.($id) );
2396 if (($this->PDFA || $this->PDFX)) { $this->PDFAXwarnings[] = "Cannot use layers when using PDFA or PDFX"; return ''; }
2397 else if (!$this->PDFA && !$this->PDFX) { $this->pdf_version='1.5'; }
2398 }
2399 $this->current_layer = $id;
2400 $this->_out('/OCZ-index /ZI'.$id.' BDC');
2401
2402 $this->pageoutput[$this->page] = array();
2403 }
2404
2405 function EndLayer() {
2406 if($this->current_layer>0) {
2407 $this->_out('EMCZ-index');
2408 $this->current_layer = 0;
2409 }
2410 }
2411
2412
2413 function AddPageByArray($a) {
2414 if (!is_array($a)) { $a = array(); }
2415 $orientation = (isset($a['orientation']) ? $a['orientation'] : '');
2416 $condition = (isset($a['condition']) ? $a['condition'] : (isset($a['type']) ? $a['type'] : ''));
2417 $resetpagenum = (isset($a['resetpagenum']) ? $a['resetpagenum'] : '');
2418 $pagenumstyle = (isset($a['pagenumstyle']) ? $a['pagenumstyle'] : '');
2419 $suppress = (isset($a['suppress']) ? $a['suppress'] : '');
2420 $mgl = (isset($a['mgl']) ? $a['mgl'] : (isset($a['margin-left']) ? $a['margin-left'] : ''));
2421 $mgr = (isset($a['mgr']) ? $a['mgr'] : (isset($a['margin-right']) ? $a['margin-right'] : ''));
2422 $mgt = (isset($a['mgt']) ? $a['mgt'] : (isset($a['margin-top']) ? $a['margin-top'] : ''));
2423 $mgb = (isset($a['mgb']) ? $a['mgb'] : (isset($a['margin-bottom']) ? $a['margin-bottom'] : ''));
2424 $mgh = (isset($a['mgh']) ? $a['mgh'] : (isset($a['margin-header']) ? $a['margin-header'] : ''));
2425 $mgf = (isset($a['mgf']) ? $a['mgf'] : (isset($a['margin-footer']) ? $a['margin-footer'] : ''));
2426 $ohname = (isset($a['ohname']) ? $a['ohname'] : (isset($a['odd-header-name']) ? $a['odd-header-name'] : ''));
2427 $ehname = (isset($a['ehname']) ? $a['ehname'] : (isset($a['even-header-name']) ? $a['even-header-name'] : ''));
2428 $ofname = (isset($a['ofname']) ? $a['ofname'] : (isset($a['odd-footer-name']) ? $a['odd-footer-name'] : ''));
2429 $efname = (isset($a['efname']) ? $a['efname'] : (isset($a['even-footer-name']) ? $a['even-footer-name'] : ''));
2430 $ohvalue = (isset($a['ohvalue']) ? $a['ohvalue'] : (isset($a['odd-header-value']) ? $a['odd-header-value'] : 0));
2431 $ehvalue = (isset($a['ehvalue']) ? $a['ehvalue'] : (isset($a['even-header-value']) ? $a['even-header-value'] : 0));
2432 $ofvalue = (isset($a['ofvalue']) ? $a['ofvalue'] : (isset($a['odd-footer-value']) ? $a['odd-footer-value'] : 0));
2433 $efvalue = (isset($a['efvalue']) ? $a['efvalue'] : (isset($a['even-footer-value']) ? $a['even-footer-value'] : 0));
2434 $pagesel = (isset($a['pagesel']) ? $a['pagesel'] : (isset($a['pageselector']) ? $a['pageselector'] : ''));
2435 $newformat = (isset($a['newformat']) ? $a['newformat'] : (isset($a['sheet-size']) ? $a['sheet-size'] : ''));
2436
2437 $this->AddPage($orientation,$condition,$resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue,$pagesel,$newformat);
2438
2439 }
2440
2441 // mPDF 6 pagebreaktype
2442 function _preForcedPagebreak($pagebreaktype) {
2443 if ($pagebreaktype == 'cloneall') {
2444 // Close any open block tags
2445 $arr=array();
2446 $ai=0;
2447 for ($b=$this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag'],$arr,$ai); }
2448 if ($this->blklvl==0 && !empty($this->textbuffer)) { //Output previously buffered content
2449 $this->printbuffer($this->textbuffer, 1);
2450 $this->textbuffer=array();
2451 }
2452 }
2453 else if ($pagebreaktype == 'clonebycss') {
2454 // Close open block tags whilst box-decoration-break==clone
2455 $arr=array();
2456 $ai=0;
2457 for ($b=$this->blklvl;$b>0;$b--) {
2458 if (isset($this->blk[$b]['box_decoration_break']) && $this->blk[$b]['box_decoration_break']=='clone') { $this->CloseTag($this->blk[$b]['tag'],$arr,$ai); }
2459 else {
2460 if ($b==$this->blklvl && !empty($this->textbuffer)) { //Output previously buffered content
2461 $this->printbuffer($this->textbuffer, 1);
2462 $this->textbuffer=array();
2463 }
2464 break;
2465 }
2466 }
2467 }
2468 else if (!empty($this->textbuffer)) { //Output previously buffered content
2469 $this->printbuffer($this->textbuffer, 1);
2470 $this->textbuffer=array();
2471 }
2472 }
2473
2474 // mPDF 6 pagebreaktype
2475 function _postForcedPagebreak($pagebreaktype, $startpage, $save_blk, $save_blklvl) {
2476 if ($pagebreaktype == 'cloneall') {
2477 $this->blk = array();
2478 $this->blk[0] = $save_blk[0];
2479 // Re-open block tags
2480 $this->blklvl = 0;
2481 $arr=array();
2482 $i=0;
2483 for ($b=1; $b<=$save_blklvl;$b++) {
2484 $this->OpenTag($save_blk[$b]['tag'],$save_blk[$b]['attr'],$arr,$i);
2485 }
2486 }
2487 else if ($pagebreaktype == 'clonebycss') {
2488 $this->blk = array();
2489 $this->blk[0] = $save_blk[0];
2490 // Don't re-open tags for lowest level elements - so need to do some adjustments
2491 for ($b=1; $b<=$this->blklvl;$b++) {
2492 $this->blk[$b] = $save_blk[$b];
2493 $this->blk[$b]['startpage']=0;
2494 $this->blk[$b]['y0']=$this->y; // ?? $this->tMargin
2495 if (($this->page - $startpage) % 2) {
2496 if (isset($this->blk[$b]['x0'])) { $this->blk[$b]['x0'] += $this->MarginCorrection; }
2497 else { $this->blk[$b]['x0'] = $this->MarginCorrection; }
2498 }
2499 //for Float DIV
2500 $this->blk[$b]['marginCorrected'][$this->page] = true;
2501 }
2502
2503 // Re-open block tags for any that have box_decoration_break==clone
2504 $arr=array();
2505 $i=0;
2506 for ($b=$this->blklvl+1; $b<=$save_blklvl;$b++) {
2507 if ($b<$this->blklvl) { $this->lastblocklevelchange = -1; }
2508 $this->OpenTag($save_blk[$b]['tag'],$save_blk[$b]['attr'],$arr,$i);
2509 }
2510 if ($this->blk[$this->blklvl]['box_decoration_break']!='clone') { $this->lastblocklevelchange = -1; }
2511 }
2512 else { $this->lastblocklevelchange = -1; }
2513 }
2514
2515 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='') {
2516
2517 /*-- CSS-FLOAT --*/
2518 // Float DIV
2519 // Cannot do with columns on, or if any change in page orientation/margins etc.
2520 // If next page already exists - i.e background /headers and footers already written
2521 if ($this->state > 0 && $this->page < count($this->pages)) {
2522 $bak_cml = $this->cMarginL;
2523 $bak_cmr = $this->cMarginR;
2524 $bak_dw = $this->divwidth;
2525 // Paint Div Border if necessary
2526 if ($this->blklvl > 0) {
2527 $save_tr = $this->table_rotate; // *TABLES*
2528 $this->table_rotate = 0; // *TABLES*
2529 if ($this->y == $this->blk[$this->blklvl]['y0']) { $this->blk[$this->blklvl]['startpage']++; }
2530 if (($this->y > $this->blk[$this->blklvl]['y0']) || $this->flowingBlockAttr['is_table'] ) { $toplvl = $this->blklvl; }
2531 else { $toplvl = $this->blklvl-1; }
2532 $sy = $this->y;
2533 for ($bl=1;$bl<=$toplvl;$bl++) {
2534 $this->PaintDivBB('pagebottom',0,$bl);
2535 }
2536 $this->y = $sy;
2537 $this->table_rotate = $save_tr; // *TABLES*
2538 }
2539 $s = $this->PrintPageBackgrounds();
2540
2541 // Writes after the marker so not overwritten later by page background etc.
2542 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.$this->uniqstr.')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
2543 $this->pageBackgrounds = array();
2544 $family=$this->FontFamily;
2545 $style=$this->FontStyle;
2546 $size=$this->FontSizePt;
2547 $lw=$this->LineWidth;
2548 $dc=$this->DrawColor;
2549 $fc=$this->FillColor;
2550 $tc=$this->TextColor;
2551 $cf=$this->ColorFlag;
2552
2553 $this->printfloatbuffer();
2554
2555 //Move to next page
2556 $this->page++;
2557 $this->ResetMargins();
2558 $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
2559 $this->x=$this->lMargin;
2560 $this->y=$this->tMargin;
2561 $this->FontFamily='';
2562 $this->_out('2 J');
2563 $this->LineWidth=$lw;
2564 $this->_out(sprintf('%.3F w',$lw*_MPDFK));
2565 if($family) $this->SetFont($family,$style,$size,true,true);
2566 $this->DrawColor=$dc;
2567 if($dc!=$this->defDrawColor) $this->_out($dc);
2568 $this->FillColor=$fc;
2569 if($fc!=$this->defFillColor) $this->_out($fc);
2570 $this->TextColor=$tc;
2571 $this->ColorFlag=$cf;
2572 for($bl=1;$bl<=$this->blklvl;$bl++) {
2573 $this->blk[$bl]['y0'] = $this->y;
2574 // Don't correct more than once for background DIV containing a Float
2575 if (!isset($this->blk[$bl]['marginCorrected'][$this->page])) { $this->blk[$bl]['x0'] += $this->MarginCorrection; }
2576 $this->blk[$bl]['marginCorrected'][$this->page] = true;
2577 }
2578 $this->cMarginL = $bak_cml;
2579 $this->cMarginR = $bak_cmr;
2580 $this->divwidth = $bak_dw;
2581 return '';
2582 }
2583 /*-- END CSS-FLOAT --*/
2584
2585 //Start a new page
2586 if($this->state==0) $this->Open();
2587
2588 $bak_cml = $this->cMarginL;
2589 $bak_cmr = $this->cMarginR;
2590 $bak_dw = $this->divwidth;
2591
2592
2593 $bak_lh = $this->lineheight;
2594
2595 $orientation = substr(strtoupper($orientation),0,1);
2596 $condition = strtoupper($condition);
2597
2598
2599 if ($condition == 'E') { // only adds new page if needed to create an Even page
2600 if (!$this->mirrorMargins || ($this->page)%2==0) { return false; }
2601 }
2602 else if ($condition == 'O') { // only adds new page if needed to create an Odd page
2603 if (!$this->mirrorMargins || ($this->page)%2==1) { return false; }
2604 }
2605 else if ($condition == 'NEXT-EVEN') { // always adds at least one new page to create an Even page
2606 if (!$this->mirrorMargins) { $condition = ''; }
2607 else {
2608 if ($pagesel) { $pbch = $pagesel; $pagesel = ''; } // *CSS-PAGE*
2609 else { $pbch = false; } // *CSS-PAGE*
2610 $this->AddPage($this->CurOrientation,'O');
2611 $this->extrapagebreak = true; // mPDF 6 pagebreaktype
2612 if ($pbch ) { $pagesel = $pbch; } // *CSS-PAGE*
2613 $condition = '';
2614 }
2615 }
2616 else if ($condition == 'NEXT-ODD') { // always adds at least one new page to create an Odd page
2617 if (!$this->mirrorMargins) { $condition = ''; }
2618 else {
2619 if ($pagesel) { $pbch = $pagesel; $pagesel = ''; } // *CSS-PAGE*
2620 else { $pbch = false; } // *CSS-PAGE*
2621 $this->AddPage($this->CurOrientation,'E');
2622 $this->extrapagebreak = true; // mPDF 6 pagebreaktype
2623 if ($pbch ) { $pagesel = $pbch; } // *CSS-PAGE*
2624 $condition = '';
2625 }
2626 }
2627
2628
2629 if ($resetpagenum || $pagenumstyle || $suppress) {
2630 $this->PageNumSubstitutions[] = array('from'=>($this->page+1), 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=>$suppress);
2631 }
2632
2633
2634 $save_tr = $this->table_rotate; // *TABLES*
2635 $this->table_rotate = 0; // *TABLES*
2636 $save_kwt = $this->kwt;
2637 $this->kwt = 0;
2638 $save_layer = $this->current_layer;
2639 $save_vis = $this->visibility;
2640
2641 if($this->visibility!='visible')
2642 $this->SetVisibility('visible');
2643 $this->EndLayer();
2644
2645 // Paint Div Border if necessary
2646 //PAINTS BACKGROUND COLOUR OR BORDERS for DIV - DISABLED FOR COLUMNS (cf. AcceptPageBreak) AT PRESENT in ->PaintDivBB
2647 if (!$this->ColActive && $this->blklvl > 0) {
2648 if (isset($this->blk[$this->blklvl]['y0']) && $this->y == $this->blk[$this->blklvl]['y0'] && !$this->extrapagebreak ) { // mPDF 6 pagebreaktype
2649 if (isset($this->blk[$this->blklvl]['startpage'])) { $this->blk[$this->blklvl]['startpage']++; }
2650 else { $this->blk[$this->blklvl]['startpage'] = 1; }
2651 }
2652 if ((isset($this->blk[$this->blklvl]['y0']) && $this->y > $this->blk[$this->blklvl]['y0']) || $this->flowingBlockAttr['is_table'] || $this->extrapagebreak ) { $toplvl = $this->blklvl; } // mPDF 6 pagebreaktype
2653 else { $toplvl = $this->blklvl-1; }
2654 $sy = $this->y;
2655 for ($bl=1;$bl<=$toplvl;$bl++) {
2656
2657 if (isset($this->blk[$bl]['z-index']) && $this->blk[$bl]['z-index']>0) {
2658 $this->BeginLayer($this->blk[$bl]['z-index']);
2659 }
2660 if (isset($this->blk[$bl]['visibility']) && $this->blk[$bl]['visibility'] && $this->blk[$bl]['visibility']!='visible') {
2661 $this->SetVisibility($this->blk[$bl]['visibility']);
2662 }
2663 $this->PaintDivBB('pagebottom',0,$bl);
2664 }
2665 $this->y = $sy;
2666 // RESET block y0 and x0 - see below
2667 }
2668 $this->extrapagebreak = false; // mPDF 6 pagebreaktype
2669
2670 if($this->visibility!='visible')
2671 $this->SetVisibility('visible');
2672 $this->EndLayer();
2673
2674 // BODY Backgrounds
2675 if ($this->page > 0) {
2676 $s = '';
2677 $s .= $this->PrintBodyBackgrounds();
2678
2679 $s .= $this->PrintPageBackgrounds();
2680 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.$this->uniqstr.')/', "\n".$s."\n".'\\1', $this->pages[$this->page]);
2681 $this->pageBackgrounds = array();
2682 }
2683
2684 $save_kt = $this->keep_block_together;
2685 $this->keep_block_together = 0;
2686
2687 $save_cols = false;
2688 /*-- COLUMNS --*/
2689 if ($this->ColActive) {
2690 $save_cols = true;
2691 $save_nbcol = $this->NbCol; // other values of gap and vAlign will not change by setting Columns off
2692 $this->SetColumns(0);
2693 }
2694 /*-- END COLUMNS --*/
2695
2696
2697 $family=$this->FontFamily;
2698 $style=$this->FontStyle;
2699 $size=$this->FontSizePt;
2700 $this->ColumnAdjust = true; // enables column height adjustment for the page
2701 $lw=$this->LineWidth;
2702 $dc=$this->DrawColor;
2703 $fc=$this->FillColor;
2704 $tc=$this->TextColor;
2705 $cf=$this->ColorFlag;
2706 if($this->page>0)
2707 {
2708 //Page footer
2709 $this->InFooter=true;
2710
2711 $this->Reset();
2712 $this->pageoutput[$this->page] = array();
2713
2714 $this->Footer();
2715 //Close page
2716 $this->_endpage();
2717 }
2718
2719
2720 //Start new page
2721 $this->_beginpage($orientation,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat);
2722 if ($this->docTemplate) {
2723 $pagecount = $this->SetSourceFile($this->docTemplate);
2724 if (($this->page - $this->docTemplateStart) > $pagecount) {
2725 if ($this->docTemplateContinue) {
2726 $tplIdx = $this->ImportPage($pagecount);
2727 $this->UseTemplate($tplIdx);
2728 }
2729 }
2730 else {
2731 $tplIdx = $this->ImportPage(($this->page - $this->docTemplateStart));
2732 $this->UseTemplate($tplIdx);
2733 }
2734 }
2735 if ($this->pageTemplate) {
2736 $this->UseTemplate($this->pageTemplate);
2737 }
2738
2739 // Tiling Patterns
2740 $this->_out('___PAGE___START'.$this->uniqstr);
2741 $this->_out('___BACKGROUND___PATTERNS'.$this->uniqstr);
2742 $this->_out('___HEADER___MARKER'.$this->uniqstr);
2743 $this->pageBackgrounds = array();
2744
2745 //Set line cap style to square
2746 $this->SetLineCap(2);
2747 //Set line width
2748 $this->LineWidth=$lw;
2749 $this->_out(sprintf('%.3F w',$lw*_MPDFK));
2750 //Set font
2751 if($family) $this->SetFont($family,$style,$size,true,true); // forces write
2752 //Set colors
2753 $this->DrawColor=$dc;
2754 if($dc!=$this->defDrawColor) $this->_out($dc);
2755 $this->FillColor=$fc;
2756 if($fc!=$this->defFillColor) $this->_out($fc);
2757 $this->TextColor=$tc;
2758 $this->ColorFlag=$cf;
2759
2760 //Page header
2761 $this->Header();
2762
2763 //Restore line width
2764 if($this->LineWidth!=$lw)
2765 {
2766 $this->LineWidth=$lw;
2767 $this->_out(sprintf('%.3F w',$lw*_MPDFK));
2768 }
2769 //Restore font
2770 if($family) $this->SetFont($family,$style,$size,true,true); // forces write
2771 //Restore colors
2772 if($this->DrawColor!=$dc)
2773 {
2774 $this->DrawColor=$dc;
2775 $this->_out($dc);
2776 }
2777 if($this->FillColor!=$fc)
2778 {
2779 $this->FillColor=$fc;
2780 $this->_out($fc);
2781 }
2782 $this->TextColor=$tc;
2783 $this->ColorFlag=$cf;
2784 $this->InFooter=false;
2785
2786 if ($save_layer>0)
2787 $this->BeginLayer($save_layer);
2788
2789 if($save_vis!='visible')
2790 $this->SetVisibility($save_vis);
2791
2792 /*-- COLUMNS --*/
2793 if ($save_cols) {
2794 // Restore columns
2795 $this->SetColumns($save_nbcol,$this->colvAlign,$this->ColGap);
2796 }
2797 if ($this->ColActive) { $this->SetCol(0); }
2798 /*-- END COLUMNS --*/
2799
2800
2801 //RESET BLOCK BORDER TOP
2802 if (!$this->ColActive) {
2803 for($bl=1;$bl<=$this->blklvl;$bl++) {
2804 $this->blk[$bl]['y0'] = $this->y;
2805 if (isset($this->blk[$bl]['x0'])) { $this->blk[$bl]['x0'] += $this->MarginCorrection; }
2806 else { $this->blk[$bl]['x0'] = $this->MarginCorrection; }
2807 // Added mPDF 3.0 Float DIV
2808 $this->blk[$bl]['marginCorrected'][$this->page] = true;
2809 }
2810 }
2811
2812
2813 $this->table_rotate = $save_tr; // *TABLES*
2814 $this->kwt = $save_kwt;
2815
2816 $this->keep_block_together = $save_kt ;
2817
2818 $this->cMarginL = $bak_cml;
2819 $this->cMarginR = $bak_cmr;
2820 $this->divwidth = $bak_dw;
2821
2822 $this->lineheight = $bak_lh;
2823 }
2824
2825
2826 function PageNo() {
2827 //Get current page number
2828 return $this->page;
2829 }
2830
2831 function AddSpotColorsFromFile($file) {
2832 $colors = @file($file) or die("Cannot load spot colors file - ".$file);
2833 foreach($colors AS $sc) {
2834 list($name, $c, $m, $y, $k) = preg_split("/\t/",$sc);
2835 $c = intval($c);
2836 $m = intval($m);
2837 $y = intval($y);
2838 $k = intval($k);
2839 $this->AddSpotColor($name, $c, $m, $y, $k);
2840 }
2841 }
2842
2843 function AddSpotColor($name, $c, $m, $y, $k) {
2844 $name = strtoupper(trim($name));
2845 if(!isset($this->spotColors[$name])) {
2846 $i=count($this->spotColors)+1;
2847 $this->spotColors[$name]=array('i'=>$i,'c'=>$c,'m'=>$m,'y'=>$y,'k'=>$k);
2848 $this->spotColorIDs[$i]=$name;
2849 }
2850 }
2851
2852 function SetColor($col, $type='') {
2853 $out = '';
2854 if (!$col) { return ''; } // mPDF 6
2855 if ($col{0}==3 || $col{0}==5) { // RGB / RGBa
2856 $out = sprintf('%.3F %.3F %.3F rg',ord($col{1})/255,ord($col{2})/255,ord($col{3})/255);
2857 }
2858 else if ($col{0}==1) { // GRAYSCALE
2859 $out = sprintf('%.3F g',ord($col{1})/255);
2860 }
2861 else if ($col{0}==2) { // SPOT COLOR
2862 $out = sprintf('/CS%d cs %.3F scn',ord($col{1}),ord($col{2})/100);
2863 }
2864 else if ($col{0}==4 || $col{0}==6) { // CMYK / CMYKa
2865 $out = sprintf('%.3F %.3F %.3F %.3F k', ord($col{1})/100, ord($col{2})/100, ord($col{3})/100, ord($col{4})/100);
2866 }
2867 if ($type=='Draw') { $out = strtoupper($out); } // e.g. rg => RG
2868 else if ($type=='CodeOnly') { $out = preg_replace('/\s(rg|g|k)/','',$out); }
2869 return $out;
2870 }
2871
2872
2873 function SetDColor($col, $return=false) {
2874 $out = $this->SetColor($col, 'Draw');
2875 if ($return) { return $out; }
2876 if ($out=='') { return ''; }
2877 $this->DrawColor = $out;
2878 if($this->page>0 && ((isset($this->pageoutput[$this->page]['DrawColor']) && $this->pageoutput[$this->page]['DrawColor'] != $this->DrawColor) || !isset($this->pageoutput[$this->page]['DrawColor']))) { $this->_out($this->DrawColor); }
2879 $this->pageoutput[$this->page]['DrawColor'] = $this->DrawColor;
2880 }
2881
2882 function SetFColor($col, $return=false) {
2883 $out = $this->SetColor($col, 'Fill');
2884 if ($return) { return $out; }
2885 if ($out=='') { return ''; }
2886 $this->FillColor = $out;
2887 $this->ColorFlag = ($out != $this->TextColor);
2888 if($this->page>0 && ((isset($this->pageoutput[$this->page]['FillColor']) && $this->pageoutput[$this->page]['FillColor'] != $this->FillColor) || !isset($this->pageoutput[$this->page]['FillColor']))) { $this->_out($this->FillColor); }
2889 $this->pageoutput[$this->page]['FillColor'] = $this->FillColor;
2890 }
2891
2892 function SetTColor($col, $return=false) {
2893 $out = $this->SetColor($col, 'Text');
2894 if ($return) { return $out; }
2895 if ($out=='') { return ''; }
2896 $this->TextColor = $out;
2897 $this->ColorFlag = ($this->FillColor != $out);
2898 }
2899
2900
2901 function SetDrawColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
2902 //Set color for all stroking operations
2903 $col = array();
2904 if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
2905 else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
2906 else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
2907 $out = $this->SetDColor($col, $return);
2908 return $out;
2909 }
2910
2911 function SetFillColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
2912 //Set color for all filling operations
2913 $col = array();
2914 if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
2915 else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
2916 else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
2917 $out = $this->SetFColor($col, $return);
2918 return $out;
2919 }
2920
2921 function SetTextColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
2922 //Set color for text
2923 $col = array();
2924 if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
2925 else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
2926 else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
2927 $out = $this->SetTColor($col, $return);
2928 return $out;
2929 }
2930
2931
2932 function _getCharWidth(&$cw, $u, $isdef=true) {
2933 $w = 0;
2934 if ($u==0) { $w = false; }
2935 else if (isset($cw[$u*2+1])) { $w = (ord($cw[$u*2]) << 8) + ord($cw[$u*2+1]); }
2936 if ($w == 65535) { return 0; }
2937 else if ($w) { return $w; }
2938 else if ($isdef) { return false; }
2939 else { return 0; }
2940 }
2941
2942 function _charDefined(&$cw, $u) {
2943 $w = 0;
2944 if ($u==0) { return false; }
2945 if (isset($cw[$u*2+1])) { $w = (ord($cw[$u*2]) << 8) + ord($cw[$u*2+1]); }
2946 if ($w) { return true; }
2947 else { return false; }
2948 }
2949
2950 function GetCharWidthCore($c) {
2951 //Get width of a single character in the current Core font
2952 $c = (string)$c;
2953 $w = 0;
2954 // Soft Hyphens chr(173)
2955 if ($c == chr(173) && $this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
2956 return 0;
2957 }
2958 else if (($this->textvar & FC_SMALLCAPS) && isset($this->upperCase[ord($c)])) { // mPDF 5.7.1
2959 $charw = $this->CurrentFont['cw'][chr($this->upperCase[ord($c)])];
2960 if ($charw!==false) {
2961 $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
2962 $w+=$charw;
2963 }
2964 }
2965 else if (isset($this->CurrentFont['cw'][$c])) {
2966 $w += $this->CurrentFont['cw'][$c];
2967 }
2968 else if (isset($this->CurrentFont['cw'][ord($c)])) {
2969 $w += $this->CurrentFont['cw'][ord($c)];
2970 }
2971 $w *= ($this->FontSize/ 1000);
2972 if ($this->minwSpacing || $this->fixedlSpacing) {
2973 if ($c==' ') $nb_spaces = 1;
2974 else $nb_spaces = 0;
2975 $w += $this->fixedlSpacing + ($nb_spaces * $this->minwSpacing);
2976 }
2977 return ($w);
2978 }
2979
2980 function GetCharWidthNonCore($c, $addSubset=true) {
2981 //Get width of a single character in the current Non-Core font
2982 $c = (string)$c;
2983 $w = 0;
2984 $unicode = $this->UTF8StringToArray($c, $addSubset);
2985 $char = $unicode[0];
2986 /*-- CJK-FONTS --*/
2987 if ($this->CurrentFont['type'] == 'Type0') { // CJK Adobe fonts
2988 if ($char == 173) { return 0; } // Soft Hyphens
2989 elseif (isset($this->CurrentFont['cw'][$char])) { $w+=$this->CurrentFont['cw'][$char]; }
2990 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
2991 else { $w += 500; }
2992 }
2993 else {
2994 /*-- END CJK-FONTS --*/
2995 if ($char == 173) { return 0; } // Soft Hyphens
2996 else if (($this->textvar & FC_SMALLCAPS) && isset($this->upperCase[$char])) { // mPDF 5.7.1
2997 $charw = $this->_getCharWidth($this->CurrentFont['cw'],$this->upperCase[$char]);
2998 if ($charw!==false) {
2999 $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
3000 $w+=$charw;
3001 }
3002 elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
3003 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
3004 else { $w += 500; }
3005 }
3006 else {
3007 $charw = $this->_getCharWidth($this->CurrentFont['cw'],$char);
3008 if ($charw!==false) { $w+=$charw; }
3009 elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
3010 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
3011 else { $w += 500; }
3012 }
3013 } // *CJK-FONTS*
3014 $w *= ($this->FontSize/ 1000);
3015 if ($this->minwSpacing || $this->fixedlSpacing) {
3016 if ($c==' ') $nb_spaces = 1;
3017 else $nb_spaces = 0;
3018 $w += $this->fixedlSpacing + ($nb_spaces * $this->minwSpacing);
3019 }
3020 return ($w);
3021 }
3022
3023
3024 function GetCharWidth($c, $addSubset=true) {
3025 if (!$this->usingCoreFont) {
3026 return $this->GetCharWidthNonCore($c, $addSubset);
3027 }
3028 else {
3029 return $this->GetCharWidthCore($c);
3030 }
3031 }
3032
3033 function GetStringWidth($s, $addSubset=true, $OTLdata=false, $textvar=0, $includeKashida=false) { // mPDF 5.7.1
3034 //Get width of a string in the current font
3035 $s = (string)$s;
3036 $cw = &$this->CurrentFont['cw'];
3037 $w = 0;
3038 $kerning = 0;
3039 $lastchar = 0;
3040 $nb_carac = 0;
3041 $nb_spaces = 0;
3042 $kashida = 0;
3043 // mPDF ITERATION
3044 if ($this->iterationCounter) $s = preg_replace('/{iteration ([a-zA-Z0-9_]+)}/', '\\1', $s);
3045 if (!$this->usingCoreFont) {
3046 $discards = substr_count($s,"\xc2\xad"); // mPDF 6 soft hyphens [U+00AD]
3047 $unicode = $this->UTF8StringToArray($s, $addSubset);
3048 if ($this->minwSpacing || $this->fixedlSpacing) {
3049 $nb_spaces = mb_substr_count($s,' ', $this->mb_enc);
3050 $nb_carac = count($unicode) - $discards ; // mPDF 6
3051 // mPDF 5.7.1
3052 // Use GPOS OTL
3053 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
3054 if (isset($OTLdata['group']) && $OTLdata['group']) {
3055 $nb_carac -= substr_count($OTLdata['group'], 'M');
3056 }
3057 }
3058 }
3059 /*-- CJK-FONTS --*/
3060 if ($this->CurrentFont['type'] == 'Type0') { // CJK Adobe fonts
3061 foreach($unicode as $char) {
3062 if ($char == 0x00AD) { continue; } // mPDF 6 soft hyphens [U+00AD]
3063 if (isset($cw[$char])) { $w+=$cw[$char]; }
3064 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
3065 else { $w += 500; }
3066 }
3067 }
3068 else {
3069 /*-- END CJK-FONTS --*/
3070 foreach($unicode as $i=>$char) {
3071 if ($char == 0x00AD) { continue; } // mPDF 6 soft hyphens [U+00AD]
3072 if (($textvar & FC_SMALLCAPS) && isset($this->upperCase[$char])) {
3073 $charw = $this->_getCharWidth($cw,$this->upperCase[$char]);
3074 if ($charw!==false) {
3075 $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
3076 $w+=$charw;
3077 }
3078 elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
3079 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
3080 else { $w += 500; }
3081 }
3082 else {
3083 $charw = $this->_getCharWidth($cw,$char);
3084 if ($charw!==false) { $w+=$charw; }
3085 elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
3086 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
3087 else { $w += 500; }
3088 // mPDF 5.7.1
3089 // Use GPOS OTL
3090 // ...GetStringWidth...
3091 if (isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0xFF) && !empty($OTLdata)) {
3092 if (isset($OTLdata['GPOSinfo'][$i]['wDir']) && $OTLdata['GPOSinfo'][$i]['wDir']=='RTL') {
3093 if (isset($OTLdata['GPOSinfo'][$i]['XAdvanceR']) && $OTLdata['GPOSinfo'][$i]['XAdvanceR']) {
3094 $w += $OTLdata['GPOSinfo'][$i]['XAdvanceR']* 1000/$this->CurrentFont['unitsPerEm'];
3095 }
3096 }
3097 else {
3098 if (isset($OTLdata['GPOSinfo'][$i]['XAdvanceL']) && $OTLdata['GPOSinfo'][$i]['XAdvanceL']) {
3099 $w += $OTLdata['GPOSinfo'][$i]['XAdvanceL']* 1000/$this->CurrentFont['unitsPerEm'];
3100 }
3101 }
3102 // Kashida from GPOS
3103 // Kashida is set as an absolute length value (already set as a proportion based on useKashida %)
3104 if ($includeKashida && isset($OTLdata['GPOSinfo'][$i]['kashida_space']) && $OTLdata['GPOSinfo'][$i]['kashida_space']) {
3105 $kashida += $OTLdata['GPOSinfo'][$i]['kashida_space'];
3106 }
3107 }
3108 if (($textvar & FC_KERNING) && $lastchar) {
3109 if (isset($this->CurrentFont['kerninfo'][$lastchar][$char])) {
3110 $kerning += $this->CurrentFont['kerninfo'][$lastchar][$char];
3111 }
3112 }
3113 $lastchar = $char;
3114 }
3115 }
3116 } // *CJK-FONTS*
3117
3118 }
3119 else {
3120 if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
3121 $s = str_replace(chr(173),'',$s );
3122 }
3123 $nb_carac = $l = strlen($s);
3124 if ($this->minwSpacing || $this->fixedlSpacing) {
3125 $nb_spaces = substr_count($s,' ');
3126 }
3127 for($i=0; $i<$l; $i++) {
3128 if (($textvar & FC_SMALLCAPS) && isset($this->upperCase[ord($s[$i])])) { // mPDF 5.7.1
3129 $charw = $cw[chr($this->upperCase[ord($s[$i])])];
3130 if ($charw!==false) {
3131 $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
3132 $w+=$charw;
3133 }
3134 }
3135 else if (isset($cw[$s[$i]])) {
3136 $w += $cw[$s[$i]];
3137 }
3138 else if (isset($cw[ord($s[$i])])) {
3139 $w += $cw[ord($s[$i])];
3140 }
3141 if (($textvar & FC_KERNING) && $i>0) { // mPDF 5.7.1
3142 if (isset($this->CurrentFont['kerninfo'][$s[($i-1)]][$s[$i]])) {
3143 $kerning += $this->CurrentFont['kerninfo'][$s[($i-1)]][$s[$i]];
3144 }
3145 }
3146 }
3147 }
3148 unset($cw);
3149 if ($textvar & FC_KERNING) { $w += $kerning; } // mPDF 5.7.1
3150 $w *= ($this->FontSize/ 1000);
3151 $w += (($nb_carac + $nb_spaces) * $this->fixedlSpacing) + ($nb_spaces * $this->minwSpacing);
3152 $w += $kashida / _MPDFK;
3153
3154 return ($w);
3155 }
3156
3157
3158 function SetLineWidth($width) {
3159 //Set line width
3160 $this->LineWidth=$width;
3161 $lwout = (sprintf('%.3F w',$width*_MPDFK));
3162 if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineWidth']) && $this->pageoutput[$this->page]['LineWidth'] != $lwout) || !isset($this->pageoutput[$this->page]['LineWidth']))) {
3163 $this->_out($lwout);
3164 }
3165 $this->pageoutput[$this->page]['LineWidth'] = $lwout;
3166 }
3167
3168 function Line($x1,$y1,$x2,$y2) {
3169 //Draw a line
3170 $this->_out(sprintf('%.3F %.3F m %.3F %.3F l S',$x1*_MPDFK,($this->h-$y1)*_MPDFK,$x2*_MPDFK,($this->h-$y2)*_MPDFK));
3171 }
3172
3173 function Arrow($x1,$y1,$x2,$y2,$headsize=3,$fill='B',$angle=25) {
3174 //F == fill //S == stroke //B == stroke and fill
3175 // angle = splay of arrowhead - 1 - 89 degrees
3176 if($fill=='F') $fill='f';
3177 elseif($fill=='FD' or $fill=='DF' or $fill=='B') $fill='B';
3178 else $fill='S';
3179 $a = atan2(($y2-$y1),($x2-$x1));
3180 $b = $a + deg2rad($angle);
3181 $c = $a - deg2rad($angle);
3182 $x3 = $x2 - ($headsize* cos($b));
3183 $y3 = $this->h-($y2 - ($headsize* sin($b)));
3184 $x4 = $x2 - ($headsize* cos($c));
3185 $y4 = $this->h-($y2 - ($headsize* sin($c)));
3186
3187 $x5 = $x3-($x3-$x4)/2; // mid point of base of arrowhead - to join arrow line to
3188 $y5 = $y3-($y3-$y4)/2;
3189
3190 $s = '';
3191 $s.=sprintf('%.3F %.3F m %.3F %.3F l S',$x1*_MPDFK,($this->h-$y1)*_MPDFK,$x5*_MPDFK,$y5*_MPDFK);
3192 $this->_out($s);
3193
3194 $s = '';
3195 $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);
3196 $s.=$fill;
3197 $this->_out($s);
3198 }
3199
3200
3201 function Rect($x,$y,$w,$h,$style='') {
3202 //Draw a rectangle
3203 if($style=='F') $op='f';
3204 elseif($style=='FD' or $style=='DF') $op='B';
3205 else $op='S';
3206 $this->_out(sprintf('%.3F %.3F %.3F %.3F re %s',$x*_MPDFK,($this->h-$y)*_MPDFK,$w*_MPDFK,-$h*_MPDFK,$op));
3207 }
3208
3209 function AddFont($family,$style='') {
3210 if(empty($family)) { return; }
3211 $family = strtolower($family);
3212 $style=strtoupper($style);
3213 $style=str_replace('U','',$style);
3214 if($style=='IB') $style='BI';
3215 $fontkey = $family.$style;
3216 // check if the font has been already added
3217 if(isset($this->fonts[$fontkey])) {
3218 return;
3219 }
3220
3221 /*-- CJK-FONTS --*/
3222 if (in_array($family,$this->available_CJK_fonts)) {
3223 if (empty($this->Big5_widths)) { require(_MPDF_PATH . 'includes/CJKdata.php'); }
3224 $this->AddCJKFont($family); // don't need to add style
3225 return;
3226 }
3227 /*-- END CJK-FONTS --*/
3228
3229 if ($this->usingCoreFont) { die("mPDF Error - problem with Font management"); }
3230
3231 $stylekey = $style;
3232 if (!$style) { $stylekey = 'R'; }
3233
3234 if (!isset($this->fontdata[$family][$stylekey]) || !$this->fontdata[$family][$stylekey]) {
3235 die('mPDF Error - Font is not supported - '.$family.' '.$style);
3236 }
3237
3238 $name = '';
3239 $originalsize = 0;
3240 $sip = false;
3241 $smp = false;
3242 $useOTL = 0; // mPDF 5.7.1
3243 $fontmetrics = ''; // mPDF 6
3244 $haskerninfo = false;
3245 $haskernGPOS = false;
3246 $hassmallcapsGSUB = false;
3247 $BMPselected = false;
3248 $GSUBScriptLang = array();
3249 $GSUBFeatures = array();
3250 $GSUBLookups = array();
3251 $GPOSScriptLang = array();
3252 $GPOSFeatures = array();
3253 $GPOSLookups = array();
3254 if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.mtx.php')) { include(_MPDF_TTFONTDATAPATH.$fontkey.'.mtx.php'); }
3255
3256 $ttffile = '';
3257 if (defined('_MPDF_SYSTEM_TTFONTS')) {
3258 $ttffile = _MPDF_SYSTEM_TTFONTS.$this->fontdata[$family][$stylekey];
3259 if (!file_exists($ttffile)) { $ttffile = ''; }
3260 }
3261 if (!$ttffile) {
3262 $ttffile = _MPDF_TTFONTPATH.$this->fontdata[$family][$stylekey];
3263 if (!file_exists($ttffile)) { die("mPDF Error - cannot find TTF TrueType font file - ".$ttffile); }
3264 }
3265 $ttfstat = stat($ttffile);
3266
3267 if (isset($this->fontdata[$family]['TTCfontID'][$stylekey])) { $TTCfontID = $this->fontdata[$family]['TTCfontID'][$stylekey]; }
3268 else { $TTCfontID = 0; }
3269
3270 $BMPonly = false;
3271 if (in_array($family,$this->BMPonly)) { $BMPonly = true; }
3272 $regenerate = false;
3273 if ($BMPonly && !$BMPselected) { $regenerate = true; }
3274 else if (!$BMPonly && $BMPselected) { $regenerate = true; }
3275 // mPDF 5.7.1
3276 if (isset($this->fontdata[$family]['useOTL']) && $this->fontdata[$family]['useOTL'] && $useOTL!=$this->fontdata[$family]['useOTL']) {
3277 $regenerate = true;
3278 $useOTL = $this->fontdata[$family]['useOTL'];
3279 }
3280 else if ((!isset($this->fontdata[$family]['useOTL']) || !$this->fontdata[$family]['useOTL']) && $useOTL) {
3281 $regenerate = true;
3282 $useOTL = 0;
3283 }
3284 if (_FONT_DESCRIPTOR != $fontmetrics) { $regenerate = true; } // mPDF 6
3285 if (!isset($name) || $originalsize != $ttfstat['size'] || $regenerate) {
3286 if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
3287 $ttf = new TTFontFile();
3288 $ttf->getMetrics($ttffile, $fontkey, $TTCfontID, $this->debugfonts, $BMPonly, $useOTL); // mPDF 5.7.1
3289 $cw = $ttf->charWidths;
3290 $kerninfo = $ttf->kerninfo;
3291 if ($kerninfo) $haskerninfo = true;
3292 $haskernGPOS = $ttf->haskernGPOS;
3293 $hassmallcapsGSUB = $ttf->hassmallcapsGSUB;
3294 $name = preg_replace('/[ ()]/','',$ttf->fullName);
3295 $sip = $ttf->sipset;
3296 $smp = $ttf->smpset;
3297 // mPDF 6
3298 $GSUBScriptLang = $ttf->GSUBScriptLang;
3299 $GSUBFeatures = $ttf->GSUBFeatures;
3300 $GSUBLookups = $ttf->GSUBLookups;
3301 $rtlPUAstr = $ttf->rtlPUAstr;
3302 $GPOSScriptLang = $ttf->GPOSScriptLang;
3303 $GPOSFeatures = $ttf->GPOSFeatures;
3304 $GPOSLookups = $ttf->GPOSLookups;
3305 $glyphIDtoUni = $ttf->glyphIDtoUni;
3306
3307
3308 $desc= array(
3309 'CapHeight'=>round($ttf->capHeight),
3310 'XHeight'=>round($ttf->xHeight),
3311 'FontBBox'=>'['.round($ttf->bbox[0])." ".round($ttf->bbox[1])." ".round($ttf->bbox[2])." ".round($ttf->bbox[3]).']', /* FontBBox from head table */
3312
3313 /* 'MaxWidth' => round($ttf->advanceWidthMax), // AdvanceWidthMax from hhea table NB ArialUnicode MS = 31990 ! */
3314 'Flags'=>$ttf->flags,
3315 'Ascent'=>round($ttf->ascent),
3316 'Descent'=>round($ttf->descent),
3317 'Leading' => round($ttf->lineGap),
3318 'ItalicAngle'=>$ttf->italicAngle,
3319 'StemV'=>round($ttf->stemV),
3320 'MissingWidth'=>round($ttf->defaultWidth)
3321 );
3322 $panose = '';
3323 if (count($ttf->panose)) {
3324 $panoseArray = array_merge(array($ttf->sFamilyClass, $ttf->sFamilySubClass), $ttf->panose);
3325 foreach($panoseArray as $value)
3326 $panose .= ' '.dechex($value);
3327 }
3328 $unitsPerEm = round($ttf->unitsPerEm);
3329 $up = round($ttf->underlinePosition);
3330 $ut = round($ttf->underlineThickness);
3331 $strp = round($ttf->strikeoutPosition); // mPDF 6
3332 $strs = round($ttf->strikeoutSize); // mPDF 6
3333 $originalsize = $ttfstat['size']+0;
3334 $type = 'TTF';
3335 //Generate metrics .php file
3336 $s='<?php'."\n";
3337 $s.='$name=\''.$name."';\n";
3338 $s.='$type=\''.$type."';\n";
3339 $s.='$desc='.var_export($desc,true).";\n";
3340 $s.='$unitsPerEm='.$unitsPerEm.";\n";
3341 $s.='$up='.$up.";\n";
3342 $s.='$ut='.$ut.";\n";
3343 $s.='$strp='.$strp.";\n"; // mPDF 6
3344 $s.='$strs='.$strs.";\n"; // mPDF 6
3345 $s.='$ttffile=\''.$ttffile."';\n";
3346 $s.='$TTCfontID=\''.$TTCfontID."';\n";
3347 $s.='$originalsize='.$originalsize.";\n";
3348 if ($sip) $s.='$sip=true;'."\n";
3349 else $s.='$sip=false;'."\n";
3350 if ($smp) $s.='$smp=true;'."\n";
3351 else $s.='$smp=false;'."\n";
3352 if ($BMPonly) $s.='$BMPselected=true;'."\n";
3353 else $s.='$BMPselected=false;'."\n";
3354 $s.='$fontkey=\''.$fontkey."';\n";
3355 $s.='$panose=\''.$panose."';\n";
3356 if ($haskerninfo) $s.='$haskerninfo=true;'."\n";
3357 else $s.='$haskerninfo=false;'."\n";
3358 if ($haskernGPOS) $s.='$haskernGPOS=true;'."\n";
3359 else $s.='$haskernGPOS=false;'."\n";
3360 if ($hassmallcapsGSUB) $s.='$hassmallcapsGSUB=true;'."\n";
3361 else $s.='$hassmallcapsGSUB=false;'."\n";
3362 $s.='$fontmetrics=\''._FONT_DESCRIPTOR."';\n"; // mPDF 6
3363
3364 $s.='// TypoAscender/TypoDescender/TypoLineGap = '.round($ttf->typoAscender).', '.round($ttf->typoDescender).', '.round($ttf->typoLineGap)."\n";
3365 $s.='// usWinAscent/usWinDescent = '.round($ttf->usWinAscent).', '.round(-$ttf->usWinDescent)."\n";
3366 $s.='// hhea Ascent/Descent/LineGap = '.round($ttf->hheaascent).', '.round($ttf->hheadescent).', '.round($ttf->hhealineGap)."\n";
3367
3368 // mPDF 5.7.1
3369 if (isset($this->fontdata[$family]['useOTL'])) {
3370 $s.='$useOTL='.$this->fontdata[$family]['useOTL'].';'."\n";
3371 }
3372 else $s.='$useOTL=0x0000;'."\n";
3373 if ($rtlPUAstr) {
3374 $s.='$rtlPUAstr=\''.$rtlPUAstr."';\n";
3375 }
3376 else $s.='$rtlPUAstr=\'\';'."\n";
3377 if (count($GSUBScriptLang)) {
3378 $s.='$GSUBScriptLang='.var_export($GSUBScriptLang,true).";\n";
3379 }
3380 if (count($GSUBFeatures)) {
3381 $s.='$GSUBFeatures='.var_export($GSUBFeatures,true).";\n";
3382 }
3383 if (count($GSUBLookups)) {
3384 $s.='$GSUBLookups='.var_export($GSUBLookups,true).";\n";
3385 }
3386 if (count($GPOSScriptLang)) {
3387 $s.='$GPOSScriptLang='.var_export($GPOSScriptLang,true).";\n";
3388 }
3389 if (count($GPOSFeatures)) {
3390 $s.='$GPOSFeatures='.var_export($GPOSFeatures,true).";\n";
3391 }
3392 if (count($GPOSLookups)) {
3393 $s.='$GPOSLookups='.var_export($GPOSLookups,true).";\n";
3394 }
3395 if ($kerninfo) {
3396 $s.='$kerninfo='.var_export($kerninfo,true).";\n";
3397 }
3398 $s.="?>";
3399 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
3400 $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.mtx.php',"w");
3401 fwrite($fh,$s,strlen($s));
3402 fclose($fh);
3403 $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.cw.dat',"wb");
3404 fwrite($fh,$cw,strlen($cw));
3405 fclose($fh);
3406 // mPDF 5.7.1
3407 $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.gid.dat',"wb");
3408 fwrite($fh,$glyphIDtoUni,strlen($glyphIDtoUni));
3409 fclose($fh);
3410 if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.cgm')) unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cgm');
3411 if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.z')) unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.z');
3412 if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.cw127.php')) unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cw127.php');
3413 if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.cw')) unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cw');
3414 }
3415 else if ($this->debugfonts) { $this->Error('Cannot write to the font caching directory - '._MPDF_TTFONTDATAPATH); }
3416 unset($ttf);
3417 }
3418 else {
3419 $cw = '';
3420 $glyphIDtoUni = '';
3421 if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.cw.dat')) $cw = file_get_contents(_MPDF_TTFONTDATAPATH.$fontkey.'.cw.dat');
3422 if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.gid.dat')) $glyphIDtoUni = file_get_contents(_MPDF_TTFONTDATAPATH.$fontkey.'.gid.dat');
3423 }
3424
3425 /*-- OTL --*/
3426 // mPDF 5.7.1
3427 // Use OTL OpenType Table Layout - GSUB
3428 if (isset($this->fontdata[$family]['useOTL']) && ($this->fontdata[$family]['useOTL'])) {
3429 if (!class_exists('otl', false)) { include(_MPDF_PATH.'classes/otl.php'); }
3430 if (empty($this->otl)) { $this->otl = new otl($this); }
3431 }
3432 /*-- END OTL --*/
3433
3434 if (isset($this->fontdata[$family]['sip-ext']) && $this->fontdata[$family]['sip-ext']) { $sipext = $this->fontdata[$family]['sip-ext']; }
3435 else { $sipext = ''; }
3436
3437 // Override with values from config_font.php
3438 if (isset($this->fontdata[$family]['Ascent']) && $this->fontdata[$family]['Ascent']) {
3439 $desc['Ascent'] = $this->fontdata[$family]['Ascent'];
3440 }
3441 if (isset($this->fontdata[$family]['Descent']) && $this->fontdata[$family]['Descent']) {
3442 $desc['Descent'] = $this->fontdata[$family]['Descent'];
3443 }
3444 if (isset($this->fontdata[$family]['Leading']) && $this->fontdata[$family]['Leading']) {
3445 $desc['Leading'] = $this->fontdata[$family]['Leading'];
3446 }
3447
3448
3449
3450 $i = count($this->fonts)+$this->extraFontSubsets+1;
3451 if ($sip || $smp) {
3452 $this->fonts[$fontkey] = array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'panose'=>$panose, 'unitsPerEm'=>$unitsPerEm, 'up'=>$up, 'ut'=>$ut, 'strs'=>$strs, 'strp'=>$strp, 'cw'=>$cw, 'ttffile'=>$ttffile, 'fontkey'=>$fontkey, 'subsets'=>array(0=>range(0,127)), 'subsetfontids'=>array($i), 'used'=>false, 'sip'=>$sip, 'sipext'=>$sipext, 'smp'=>$smp, 'TTCfontID' => $TTCfontID, 'useOTL' => (isset($this->fontdata[$family]['useOTL']) ? $this->fontdata[$family]['useOTL'] : false), 'useKashida' => (isset($this->fontdata[$family]['useKashida']) ? $this->fontdata[$family]['useKashida'] : false), 'GSUBScriptLang'=>$GSUBScriptLang, 'GSUBFeatures'=>$GSUBFeatures, 'GSUBLookups'=>$GSUBLookups, 'GPOSScriptLang'=>$GPOSScriptLang, 'GPOSFeatures'=>$GPOSFeatures, 'GPOSLookups'=>$GPOSLookups, 'rtlPUAstr'=>$rtlPUAstr, 'glyphIDtoUni'=>$glyphIDtoUni, 'haskerninfo'=>$haskerninfo, 'haskernGPOS'=>$haskernGPOS, 'hassmallcapsGSUB'=>$hassmallcapsGSUB); // mPDF 5.7.1 // mPDF 6
3453 }
3454 else {
3455 $ss = array();
3456 for ($s=32; $s<128; $s++) { $ss[$s] = $s; }
3457 $this->fonts[$fontkey] = array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'panose'=>$panose, 'unitsPerEm'=>$unitsPerEm, 'up'=>$up, 'ut'=>$ut, 'strs'=>$strs, 'strp'=>$strp, 'cw'=>$cw, 'ttffile'=>$ttffile, 'fontkey'=>$fontkey, 'subset'=>$ss, 'used'=>false, 'sip'=>$sip, 'sipext'=>$sipext, 'smp'=>$smp, 'TTCfontID' => $TTCfontID, 'useOTL' => (isset($this->fontdata[$family]['useOTL']) ? $this->fontdata[$family]['useOTL'] : false), 'useKashida' => (isset($this->fontdata[$family]['useKashida']) ? $this->fontdata[$family]['useKashida'] : false), 'GSUBScriptLang'=>$GSUBScriptLang, 'GSUBFeatures'=>$GSUBFeatures, 'GSUBLookups'=>$GSUBLookups, 'GPOSScriptLang'=>$GPOSScriptLang, 'GPOSFeatures'=>$GPOSFeatures, 'GPOSLookups'=>$GPOSLookups, 'rtlPUAstr'=>$rtlPUAstr, 'glyphIDtoUni'=>$glyphIDtoUni, 'haskerninfo'=>$haskerninfo, 'haskernGPOS'=>$haskernGPOS, 'hassmallcapsGSUB'=>$hassmallcapsGSUB); // mPDF 5.7.1 // mPDF 6
3458 }
3459 if ($haskerninfo) { $this->fonts[$fontkey]['kerninfo'] = $kerninfo; }
3460 $this->FontFiles[$fontkey]=array('length1'=>$originalsize, 'type'=>"TTF", 'ttffile'=>$ttffile, 'sip'=>$sip, 'smp'=>$smp);
3461 unset($cw);
3462 }
3463
3464
3465
3466 function SetFont($family,$style='',$size=0, $write=true, $forcewrite=false) {
3467 $family=strtolower($family);
3468 if (!$this->onlyCoreFonts) {
3469 if ($family == 'sans' || $family == 'sans-serif') { $family = $this->sans_fonts[0]; }
3470 if ($family == 'serif') { $family = $this->serif_fonts[0]; }
3471 if ($family == 'mono' || $family == 'monospace') { $family = $this->mono_fonts[0]; }
3472 }
3473 if (isset($this->fonttrans[$family]) && $this->fonttrans[$family]) { $family = $this->fonttrans[$family]; }
3474 if($family=='') {
3475 if ($this->FontFamily) { $family=$this->FontFamily; }
3476 else if ($this->default_font) { $family=$this->default_font; }
3477 else { $this->Error("No font or default font set!"); }
3478 }
3479 $this->ReqFontStyle = $style; // required or requested style - used later for artificial bold/italic
3480
3481 if (($family == 'csymbol') || ($family == 'czapfdingbats') || ($family == 'ctimes') || ($family == 'ccourier') || ($family == 'chelvetica')) {
3482 if ($this->PDFA || $this->PDFX) {
3483 if ($family == 'csymbol' || $family == 'czapfdingbats') {
3484 $this->Error("Symbol and Zapfdingbats cannot be embedded in mPDF (required for PDFA1-b or PDFX/1-a).");
3485 }
3486 if ($family == 'ctimes' || $family == 'ccourier' || $family == 'chelvetica') {
3487 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.)"; }
3488 if ($family == 'chelvetica') { $family = 'sans'; }
3489 if ($family == 'ctimes') { $family = 'serif'; }
3490 if ($family == 'ccourier') { $family = 'mono'; }
3491 }
3492 $this->usingCoreFont = false;
3493 }
3494 else { $this->usingCoreFont = true; }
3495 if($family=='csymbol' || $family=='czapfdingbats') { $style=''; }
3496 }
3497 else { $this->usingCoreFont = false; }
3498
3499 // mPDF 5.7.1
3500 if ($style) {
3501 $style=strtoupper($style);
3502 if ($style=='IB') $style='BI';
3503 }
3504 if ($size==0) $size=$this->FontSizePt;
3505
3506 $fontkey=$family.$style;
3507
3508 $stylekey = $style;
3509 if (!$stylekey) { $stylekey = "R"; }
3510
3511 if (!$this->onlyCoreFonts && !$this->usingCoreFont) {
3512 if(!isset($this->fonts[$fontkey]) || count($this->default_available_fonts) != count($this->available_unifonts) ) { // not already added
3513 /*-- CJK-FONTS --*/
3514 // CJK fonts
3515 if (in_array($fontkey,$this->available_CJK_fonts)) {
3516 if(!isset($this->fonts[$fontkey])) { // already added
3517 if (empty($this->Big5_widths)) { require(_MPDF_PATH . 'includes/CJKdata.php'); }
3518 $this->AddCJKFont($family); // don't need to add style
3519 }
3520 }
3521 // Test to see if requested font/style is available - or substitute
3522 else
3523 /*-- END CJK-FONTS --*/
3524 if (!in_array($fontkey,$this->available_unifonts)) {
3525 // If font[nostyle] exists - set it
3526 if (in_array($family,$this->available_unifonts)) {
3527 $style = '';
3528 }
3529
3530 // Else if only one font available - set it (assumes if only one font available it will not have a style)
3531 else if (count($this->available_unifonts) == 1) {
3532 $family = $this->available_unifonts[0];
3533 $style = '';
3534 }
3535
3536 else {
3537 $found = 0;
3538 // else substitute font of similar type
3539 if (in_array($family,$this->sans_fonts)) {
3540 $i = array_intersect($this->sans_fonts,$this->available_unifonts);
3541 if (count($i)) {
3542 $i = array_values($i);
3543 // with requested style if possible
3544 if (!in_array(($i[0].$style),$this->available_unifonts)) {
3545 $style = '';
3546 }
3547 $family = $i[0];
3548 $found = 1;
3549 }
3550 }
3551 else if (in_array($family,$this->serif_fonts)) {
3552 $i = array_intersect($this->serif_fonts,$this->available_unifonts);
3553 if (count($i)) {
3554 $i = array_values($i);
3555 // with requested style if possible
3556 if (!in_array(($i[0].$style),$this->available_unifonts)) {
3557 $style = '';
3558 }
3559 $family = $i[0];
3560 $found = 1;
3561 }
3562 }
3563 else if (in_array($family,$this->mono_fonts)) {
3564 $i = array_intersect($this->mono_fonts,$this->available_unifonts);
3565 if (count($i)) {
3566 $i = array_values($i);
3567 // with requested style if possible
3568 if (!in_array(($i[0].$style),$this->available_unifonts)) {
3569 $style = '';
3570 }
3571 $family = $i[0];
3572 $found = 1;
3573 }
3574 }
3575
3576 if (!$found) {
3577 // set first available font
3578 $fs = $this->available_unifonts[0];
3579 preg_match('/^([a-z_0-9\-]+)([BI]{0,2})$/',$fs,$fas); // Allow "-"
3580 // with requested style if possible
3581 $ws = $fas[1].$style;
3582 if (in_array($ws,$this->available_unifonts)) {
3583 $family = $fas[1]; // leave $style as is
3584 }
3585 else if (in_array($fas[1],$this->available_unifonts)) {
3586 // or without style
3587 $family = $fas[1];
3588 $style = '';
3589 }
3590 else {
3591 // or with the style specified
3592 $family = $fas[1];
3593 $style = $fas[2];
3594 }
3595 }
3596 }
3597 $fontkey = $family.$style;
3598 }
3599 }
3600 // try to add font (if not already added)
3601 $this->AddFont($family, $style);
3602
3603 //Test if font is already selected
3604 if($this->FontFamily == $family && $this->FontFamily == $this->currentfontfamily && $this->FontStyle == $style && $this->FontStyle == $this->currentfontstyle && $this->FontSizePt == $size && $this->FontSizePt == $this->currentfontsize && !$forcewrite) {
3605 return $family;
3606 }
3607
3608 $fontkey = $family.$style;
3609
3610 //Select it
3611 $this->FontFamily = $family;
3612 $this->FontStyle = $style;
3613 $this->FontSizePt = $size;
3614 $this->FontSize = $size / _MPDFK;
3615 $this->CurrentFont = &$this->fonts[$fontkey];
3616 if ($write) {
3617 $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
3618 if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) { $this->_out($fontout); }
3619 $this->pageoutput[$this->page]['Font'] = $fontout;
3620 }
3621
3622
3623
3624 // Added - currentfont (lowercase) used in HTML2PDF
3625 $this->currentfontfamily=$family;
3626 $this->currentfontsize=$size;
3627 $this->currentfontstyle=$style;
3628 $this->setMBencoding('UTF-8');
3629 }
3630
3631 else { // if using core fonts
3632
3633
3634 if ($this->PDFA || $this->PDFX) {
3635 $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.');
3636 }
3637 $this->setMBencoding('windows-1252');
3638
3639 //Test if font is already selected
3640 if(($this->FontFamily == $family) AND ($this->FontStyle == $style) AND ($this->FontSizePt == $size) && !$forcewrite) {
3641 return $family;
3642 }
3643
3644 if (!isset($this->CoreFonts[$fontkey])) {
3645 if (in_array($family,$this->serif_fonts)) { $family = 'ctimes'; }
3646 else if (in_array($family,$this->mono_fonts)) { $family = 'ccourier'; }
3647 else { $family = 'chelvetica'; }
3648 $this->usingCoreFont = true;
3649 $fontkey = $family.$style;
3650 }
3651
3652 if(!isset($this->fonts[$fontkey])) {
3653 // STANDARD CORE FONTS
3654 if (isset($this->CoreFonts[$fontkey])) {
3655 //Load metric file
3656 $file=$family;
3657 if($family=='ctimes' || $family=='chelvetica' || $family=='ccourier') { $file.=strtolower($style); }
3658 $file.='.php';
3659 include(_MPDF_PATH.'font/'.$file);
3660 if(!isset($cw)) { $this->Error('Could not include font metric file'); }
3661 $i=count($this->fonts)+$this->extraFontSubsets+1;
3662 $this->fonts[$fontkey]=array('i'=>$i,'type'=>'core','name'=>$this->CoreFonts[$fontkey],'desc'=>$desc,'up'=>$up,'ut'=>$ut,'cw'=>$cw);
3663 if ($this->useKerning && isset($kerninfo)) { $this->fonts[$fontkey]['kerninfo'] = $kerninfo; }
3664 }
3665 else {
3666 die('mPDF error - Font not defined');
3667 }
3668 }
3669 //Test if font is already selected
3670 if(($this->FontFamily == $family) AND ($this->FontStyle == $style) AND ($this->FontSizePt == $size) && !$forcewrite) {
3671 return $family;
3672 }
3673 //Select it
3674 $this->FontFamily=$family;
3675 $this->FontStyle=$style;
3676 $this->FontSizePt=$size;
3677 $this->FontSize=$size/_MPDFK;
3678 $this->CurrentFont=&$this->fonts[$fontkey];
3679 if ($write) {
3680 $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
3681 if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) { $this->_out($fontout); }
3682 $this->pageoutput[$this->page]['Font'] = $fontout;
3683 }
3684 // Added - currentfont (lowercase) used in HTML2PDF
3685 $this->currentfontfamily=$family;
3686 $this->currentfontsize=$size;
3687 $this->currentfontstyle=$style;
3688
3689 }
3690
3691 return $family;
3692 }
3693
3694 function SetFontSize($size,$write=true) {
3695 //Set font size in points
3696 if($this->FontSizePt==$size) return;
3697 $this->FontSizePt=$size;
3698 $this->FontSize=$size/_MPDFK;
3699 $this->currentfontsize=$size;
3700 if ($write) {
3701 $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
3702 // Edited mPDF 3.0
3703 if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) { $this->_out($fontout); }
3704 $this->pageoutput[$this->page]['Font'] = $fontout;
3705 }
3706 }
3707
3708 function AddLink() {
3709 //Create a new internal link
3710 $n=count($this->links)+1;
3711 $this->links[$n]=array(0,0);
3712 return $n;
3713 }
3714
3715 function SetLink($link,$y=0,$page=-1) {
3716 //Set destination of internal link
3717 if($y==-1) $y=$this->y;
3718 if($page==-1) $page=$this->page;
3719 $this->links[$link]=array($page,$y);
3720 }
3721
3722 function Link($x,$y,$w,$h,$link) {
3723 $l = array($x*_MPDFK,$this->hPt-$y*_MPDFK,$w*_MPDFK,$h*_MPDFK,$link);
3724 if ($this->keep_block_together) { // don't write yet
3725 return;
3726 }
3727 else if ($this->table_rotate) { // *TABLES*
3728 $this->tbrot_Links[$this->page][]= $l; // *TABLES*
3729 return; // *TABLES*
3730 } // *TABLES*
3731 else if ($this->kwt) {
3732 $this->kwt_Links[$this->page][]= $l;
3733 return;
3734 }
3735
3736 if ($this->writingHTMLheader || $this->writingHTMLfooter) {
3737 $this->HTMLheaderPageLinks[]= $l;
3738 return;
3739 }
3740 //Put a link on the page
3741 $this->PageLinks[$this->page][]= $l;
3742 // Save cross-reference to Column buffer
3743 $ref = count($this->PageLinks[$this->page])-1; // *COLUMNS*
3744 $this->columnLinks[$this->CurrCol][INTVAL($this->x)][INTVAL($this->y)] = $ref; // *COLUMNS*
3745
3746 }
3747
3748 function Text($x,$y,$txt,$OTLdata=array(), $textvar=0, $aixextra='',$coordsys='',$return=false) {
3749 // Output (or return) a string
3750 // Called (internally) by Watermark() & _tableWrite() [rotated cells] & TableHeaderFooter() & WriteText()
3751 // Called also from classes/svg.php
3752 // Expects Font to be set
3753 // Expects input to be mb_encoded if necessary and RTL reversed & OTL processed
3754
3755 // ARTIFICIAL BOLD AND ITALIC
3756 $s = 'q ';
3757 if ($this->falseBoldWeight && strpos($this->ReqFontStyle,"B") !== false && strpos($this->FontStyle,"B") === false) {
3758 $s .= '2 Tr 1 J 1 j ';
3759 $s .= sprintf('%.3F w ',($this->FontSize/130)*_MPDFK*$this->falseBoldWeight);
3760 $tc = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3761 if($this->FillColor!=$tc) { $s .= $tc.' '; } // stroke (outline) = same colour as text(fill)
3762 }
3763 if (strpos($this->ReqFontStyle,"I") !== false && strpos($this->FontStyle,"I") === false) {
3764 $aix = '1 0 0.261799 1 %.3F %.3F Tm';
3765 }
3766 else { $aix = '%.3F %.3F Td'; }
3767
3768 $aix = $aixextra.$aix;
3769
3770 if($this->ColorFlag) $s.=$this->TextColor.' ';
3771
3772 $this->CurrentFont['used']= true;
3773
3774 if ($this->usingCoreFont) {
3775 $txt2 = str_replace(chr(160),chr(32),$txt);
3776 }
3777 else {
3778 $txt2 = str_replace(chr(194).chr(160),chr(32),$txt);
3779 }
3780
3781 $px = $x;
3782 $py = $y;
3783 if ($coordsys != 'SVG') {
3784 $px = $x*_MPDFK;
3785 $py = ($this->h-$y)*_MPDFK;
3786 }
3787
3788
3789 /* *************** SIMILAR TO Cell() ************************ */
3790
3791 // IF corefonts AND NOT SmCaps AND NOT Kerning
3792 // Just output text
3793 if ($this->usingCoreFont && !($textvar & FC_SMALLCAPS) && !($textvar & FC_KERNING)) {
3794 $txt2=$this->_escape($txt2);
3795 $s .=sprintf('BT '.$aix.' (%s) Tj ET',$px,$py,$txt2);
3796 }
3797
3798
3799 // IF NOT corefonts [AND NO wordspacing] AND NOT SIP/SMP AND NOT SmCaps AND NOT Kerning AND NOT OTL
3800 // Just output text
3801 else if (!$this->usingCoreFont && !($textvar & FC_SMALLCAPS) && !($textvar & FC_KERNING) && !(isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0xFF) && !empty($OTLdata['GPOSinfo']))) {
3802 // IF SIP/SMP
3803 if ($this->CurrentFont['sip'] || $this->CurrentFont['smp']) {
3804 $txt2 = $this->UTF8toSubset($txt2);
3805 $s .=sprintf('BT '.$aix.' %s Tj ET',$px,$py,$txt2);
3806 }
3807 // NOT SIP/SMP
3808 else {
3809 $txt2 = $this->UTF8ToUTF16BE($txt2, false);
3810 $txt2=$this->_escape($txt2);
3811 $s .=sprintf('BT '.$aix.' (%s) Tj ET',$px,$py,$txt2);
3812 }
3813 }
3814
3815 // IF NOT corefonts [AND IS wordspacing] AND NOT SIP AND NOT SmCaps AND NOT Kerning AND NOT OTL
3816 // Not required here (cf. Cell() )
3817
3818 // ELSE (IF SmCaps || Kerning || OTL) [corefonts or not corefonts; SIP or SMP or BMP]
3819 else {
3820 $s .= $this->applyGPOSpdf($txt2, $aix, $px,$py, $OTLdata, $textvar );
3821 }
3822 /* *************** END ************************ */
3823
3824 $s .= ' ';
3825
3826 if(($textvar & FD_UNDERLINE) && $txt!='') { // mPDF 5.7.1
3827 $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3828 if($this->FillColor!=$c) { $s.= ' '.$c.' '; }
3829 if (isset($this->CurrentFont['up']) && $this->CurrentFont['up']) { $up=$this->CurrentFont['up']; }
3830 else { $up = -100; }
3831 $adjusty = (-$up/1000* $this->FontSize);
3832 if (isset($this->CurrentFont['ut']) && $this->CurrentFont['ut']) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
3833 else { $ut = 60/1000* $this->FontSize; }
3834 $olw = $this->LineWidth;
3835 $s.=' '.(sprintf(' %.3F w',$ut*_MPDFK));
3836 $s.=' '.$this->_dounderline($x,$y + $adjusty,$txt,$OTLdata,$textvar);
3837 $s.=' '.(sprintf(' %.3F w',$olw*_MPDFK));
3838 if($this->FillColor!=$c) { $s.= ' '.$this->FillColor.' '; }
3839 }
3840 // STRIKETHROUGH
3841 if(($textvar & FD_LINETHROUGH) && $txt!='') { // mPDF 5.7.1
3842 $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3843 if($this->FillColor!=$c) { $s.= ' '.$c.' '; }
3844 //Superscript and Subscript Y coordinate adjustment (now for striked-through texts)
3845 if (isset($this->CurrentFont['desc']['CapHeight']) && $this->CurrentFont['desc']['CapHeight']) { $ch=$this->CurrentFont['desc']['CapHeight']; }
3846 else { $ch = 700; }
3847 $adjusty = (-$ch/1000* $this->FontSize) * 0.35;
3848 if (isset($this->CurrentFont['ut']) && $this->CurrentFont['ut']) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
3849 else { $ut = 60/1000* $this->FontSize; }
3850 $olw = $this->LineWidth;
3851 $s.=' '.(sprintf(' %.3F w',$ut*_MPDFK));
3852 $s.=' '.$this->_dounderline($x,$y+$adjusty,$txt,$OTLdata,$textvar);
3853 $s.=' '.(sprintf(' %.3F w',$olw*_MPDFK));
3854 if($this->FillColor!=$c) { $s.= ' '.$this->FillColor.' '; }
3855 }
3856 $s .= 'Q';
3857
3858 if ($return) { return $s." \n"; }
3859 $this->_out($s);
3860 }
3861
3862 /*-- DIRECTW --*/
3863 function WriteText($x,$y,$txt) {
3864 // Output a string using Text() but does encoding and text reversing of RTL
3865 $txt = $this->purify_utf8_text($txt);
3866 if ($this->text_input_as_HTML) {
3867 $txt = $this->all_entities_to_utf8($txt);
3868 }
3869 if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
3870
3871 // DIRECTIONALITY
3872 if (preg_match("/([".$this->pregRTLchars."])/u", $txt)) { $this->biDirectional = true; } // *OTL*
3873
3874 $textvar = 0;
3875 $save_OTLtags = $this->OTLtags;
3876 $this->OTLtags = array();
3877 if ($this->useKerning) {
3878 if ($this->CurrentFont['haskernGPOS']) { $this->OTLtags['Plus'] .= ' kern'; }
3879 else { $textvar = ($textvar | FC_KERNING); }
3880 }
3881
3882 /*-- OTL --*/
3883 // Use OTL OpenType Table Layout - GSUB & GPOS
3884 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
3885 $txt = $this->otl->applyOTL($txt, $this->CurrentFont['useOTL']);
3886 $OTLdata = $this->otl->OTLdata;
3887 }
3888 /*-- END OTL --*/
3889 $this->OTLtags = $save_OTLtags ;
3890
3891 $this->magic_reverse_dir($txt, $this->directionality, $OTLdata);
3892
3893 $this->Text($x,$y,$txt,$OTLdata, $textvar);
3894 }
3895
3896 function WriteCell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='', $currentx=0) {
3897 //Output a cell using Cell() but does encoding and text reversing of RTL
3898 $txt = $this->purify_utf8_text($txt);
3899 if ($this->text_input_as_HTML) {
3900 $txt = $this->all_entities_to_utf8($txt);
3901 }
3902 if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
3903 // DIRECTIONALITY
3904 if (preg_match("/([".$this->pregRTLchars."])/u", $txt)) { $this->biDirectional = true; } // *OTL*
3905
3906 $textvar = 0;
3907 $save_OTLtags = $this->OTLtags;
3908 $this->OTLtags = array();
3909 if ($this->useKerning) {
3910 if ($this->CurrentFont['haskernGPOS']) { $this->OTLtags['Plus'] .= ' kern'; }
3911 else { $textvar = ($textvar | FC_KERNING); }
3912 }
3913
3914 /*-- OTL --*/
3915 // Use OTL OpenType Table Layout - GSUB & GPOS
3916 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
3917 $txt = $this->otl->applyOTL($txt, $this->CurrentFont['useOTL']);
3918 $OTLdata = $this->otl->OTLdata;
3919 }
3920 /*-- END OTL --*/
3921 $this->OTLtags = $save_OTLtags ;
3922
3923 $this->magic_reverse_dir($txt, $this->directionality, $OTLdata);
3924
3925 $this->Cell($w,$h,$txt,$border,$ln,$align,$fill,$link, $currentx,0,0,'M', 0, false, $OTLdata, $textvar );
3926 }
3927 /*-- END DIRECTW --*/
3928
3929
3930 function ResetSpacing() {
3931 if ($this->ws != 0) { $this->_out('BT 0 Tw ET'); }
3932 $this->ws=0;
3933 if ($this->charspacing != 0) { $this->_out('BT 0 Tc ET'); }
3934 $this->charspacing=0;
3935 }
3936
3937
3938 function SetSpacing($cs,$ws) {
3939 if (intval($cs*1000)==0) { $cs = 0; }
3940 if ($cs) { $this->_out(sprintf('BT %.3F Tc ET',$cs)); }
3941 else if ($this->charspacing != 0) { $this->_out('BT 0 Tc ET'); }
3942 $this->charspacing=$cs;
3943 if (intval($ws*1000)==0) { $ws = 0; }
3944 if ($ws) { $this->_out(sprintf('BT %.3F Tw ET',$ws)); }
3945 else if ($this->ws != 0) { $this->_out('BT 0 Tw ET'); }
3946 $this->ws=$ws;
3947 }
3948
3949 // WORD SPACING
3950 function GetJspacing($nc,$ns,$w,$inclCursive,&$cOTLdata) {
3951 $kashida_present = false;
3952 $kashida_space = 0;
3953 if ($w >0 && $inclCursive && isset($this->CurrentFont['useKashida']) && $this->CurrentFont['useKashida'] && !empty($cOTLdata)) {
3954 for($c=0;$c<count($cOTLdata);$c++) {
3955 for($i=0;$i<strlen($cOTLdata[$c]['group']);$i++) {
3956 if (isset($cOTLdata[$c]['GPOSinfo'][$i]['kashida']) && $cOTLdata[$c]['GPOSinfo'][$i]['kashida']>0) {
3957 $kashida_present = true;
3958 break 2;
3959 }
3960 }
3961 }
3962 }
3963
3964 if ($kashida_present) {
3965 $k_ctr = 0; // Number of kashida points
3966 $k_total = 0; // Total of kashida values (priority)
3967 // Reset word
3968 $max_kashida_in_word = 0;
3969 $last_kashida_in_word = -1;
3970
3971 for($c=0;$c<count($cOTLdata);$c++) {
3972 for($i=0;$i<strlen($cOTLdata[$c]['group']);$i++) {
3973
3974 if ($cOTLdata[$c]['group']{$i}=='S') {
3975 // Save from last word
3976 if ($max_kashida_in_word) {
3977 $k_ctr++;
3978 $k_total = $max_kashida_in_word;
3979 }
3980 // Reset word
3981 $max_kashida_in_word = 0;
3982 $last_kashida_in_word = -1;
3983 }
3984
3985 if (isset($cOTLdata[$c]['GPOSinfo'][$i]['kashida']) && $cOTLdata[$c]['GPOSinfo'][$i]['kashida']>0) {
3986 if ($max_kashida_in_word) {
3987 if ($cOTLdata[$c]['GPOSinfo'][$i]['kashida'] > $max_kashida_in_word) {
3988 $max_kashida_in_word = $cOTLdata[$c]['GPOSinfo'][$i]['kashida'];
3989 $cOTLdata[$c]['GPOSinfo'][$last_kashida_in_word]['kashida'] = 0;
3990 $last_kashida_in_word = $i;
3991 }
3992 else {
3993 $cOTLdata[$c]['GPOSinfo'][$i]['kashida'] = 0;
3994 }
3995 }
3996 else {
3997 $max_kashida_in_word = $cOTLdata[$c]['GPOSinfo'][$i]['kashida'];
3998 $last_kashida_in_word = $i;
3999 }
4000 }
4001 }
4002 }
4003 // Save from last word
4004 if ($max_kashida_in_word) {
4005 $k_ctr++;
4006 $k_total = $max_kashida_in_word;
4007 }
4008
4009 // Number of kashida points = $k_ctr
4010 // $useKashida is a % value from CurrentFont/config_fonts.php
4011 // % ratio divided between word-spacing and kashida-spacing
4012 $kashida_space_ratio = intval($this->CurrentFont['useKashida']) / 100;
4013
4014
4015 $kashida_space = $w * $kashida_space_ratio;
4016
4017 $tatw = $this->_getCharWidth($this->CurrentFont['cw'], 0x0640);
4018 // Only use kashida if each allocated kashida width is > 0.01 x width of a tatweel
4019 // Otherwise fontstretch is too small and errors
4020 // If not just leave to adjust word-spacing
4021 if ($tatw && (($kashida_space/$k_ctr) / $tatw) > 0.01) {
4022 for($c=0;$c<count($cOTLdata);$c++) {
4023 for($i=0;$i<strlen($cOTLdata[$c]['group']);$i++) {
4024 if (isset($cOTLdata[$c]['GPOSinfo'][$i]['kashida']) && $cOTLdata[$c]['GPOSinfo'][$i]['kashida']>0) {
4025 // At this point kashida is a number representing priority (higher number - higher priority)
4026 // We are now going to set it as an actual length
4027 // This shares it equally amongst words:
4028 $cOTLdata[$c]['GPOSinfo'][$i]['kashida_space'] = (1 / $k_ctr) * $kashida_space;
4029 }
4030 }
4031 }
4032 $w -= $kashida_space;
4033 }
4034 }
4035
4036 $ws = 0;
4037 $charspacing = 0;
4038 $ww = $this->jSWord;
4039 $ncx = $nc-1;
4040 if ($nc == 0) { return array(0,0,0); }
4041 // Only word spacing allowed / possible
4042 else if ($this->fixedlSpacing !== false || $inclCursive) {
4043 if ($ns) { $ws = $w / $ns; }
4044 }
4045 else if ($nc==1) { $charspacing = $w; }
4046 else if (!$ns) {
4047 $charspacing = $w / ($ncx );
4048 if (($this->jSmaxChar > 0) && ($charspacing > $this->jSmaxChar)) {
4049 $charspacing = $this->jSmaxChar;
4050 }
4051 }
4052 else if ($ns == ($ncx )) {
4053 $charspacing = $w / $ns;
4054 }
4055 else {
4056 if ($this->usingCoreFont) {
4057 $cs = ($w * (1 - $this->jSWord)) / ($ncx );
4058 if (($this->jSmaxChar > 0) && ($cs > $this->jSmaxChar)) {
4059 $cs = $this->jSmaxChar;
4060 $ww = 1 - (($cs * ($ncx ))/$w);
4061 }
4062 $charspacing = $cs;
4063 $ws = ($w * ($ww) ) / $ns;
4064 }
4065 else {
4066 $cs = ($w * (1 - $this->jSWord)) / ($ncx -$ns);
4067 if (($this->jSmaxChar > 0) && ($cs > $this->jSmaxChar)) {
4068 $cs = $this->jSmaxChar;
4069 $ww = 1 - (($cs * ($ncx -$ns))/$w);
4070 }
4071 $charspacing = $cs;
4072 $ws = (($w * ($ww) ) / $ns) - $charspacing;
4073 }
4074 }
4075 return array($charspacing,$ws,$kashida_space);
4076 }
4077
4078 function Cell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='', $currentx=0, $lcpaddingL=0, $lcpaddingR=0, $valign='M', $spanfill=0, $exactWidth=false, $OTLdata=false, $textvar=0, $lineBox=false) { // mPDF 5.7.1
4079
4080 //Output a cell
4081 // Expects input to be mb_encoded if necessary and RTL reversed
4082 // NON_BREAKING SPACE
4083 if ($this->usingCoreFont) {
4084 $txt = str_replace(chr(160),chr(32),$txt);
4085 }
4086 else {
4087 $txt = str_replace(chr(194).chr(160),chr(32),$txt);
4088 }
4089
4090 $oldcolumn = $this->CurrCol;
4091 // Automatic page break
4092 // Allows PAGE-BREAK-AFTER = avoid to work
4093 if (isset($this->blk[$this->blklvl])) { $bottom = $this->blk[$this->blklvl]['padding_bottom']+$this->blk[$this->blklvl]['margin_bottom']; }
4094 else { $bottom = 0; }
4095 if (!$this->tableLevel && (($this->y+$this->divheight>$this->PageBreakTrigger) || ($this->y+$h>$this->PageBreakTrigger) ||
4096 ($this->y+($h*2)+$bottom>$this->PageBreakTrigger && $this->blk[$this->blklvl]['page_break_after_avoid'])) and !$this->InFooter and $this->AcceptPageBreak()) { // mPDF 5.7.2
4097 $x=$this->x;//Current X position
4098
4099
4100 // WORD SPACING
4101 $ws=$this->ws;//Word Spacing
4102 $charspacing=$this->charspacing;//Character Spacing
4103 $this->ResetSpacing();
4104
4105 $this->AddPage($this->CurOrientation);
4106 // Added to correct for OddEven Margins
4107 $x += $this->MarginCorrection;
4108 if ($currentx) {
4109 $currentx += $this->MarginCorrection;
4110 }
4111 $this->x=$x;
4112 // WORD SPACING
4113 $this->SetSpacing($charspacing,$ws);
4114 }
4115
4116 // Test: to put line through centre of cell: $this->Line($this->x,$this->y+($h/2),$this->x+50,$this->y+($h/2));
4117 // Test: to put border around cell as it is specified: $border='LRTB';
4118
4119
4120 /*-- COLUMNS --*/
4121 // COLS
4122 // COLUMN CHANGE
4123 if ($this->CurrCol != $oldcolumn) {
4124 if ($currentx) {
4125 $currentx += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
4126 }
4127 $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
4128 }
4129
4130 // COLUMNS Update/overwrite the lowest bottom of printing y value for a column
4131 if ($this->ColActive) {
4132 if ($h) { $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y+$h; }
4133 else { $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y+$this->divheight; }
4134 }
4135 /*-- END COLUMNS --*/
4136
4137
4138 if($w==0) $w = $this->w-$this->rMargin-$this->x;
4139 $s='';
4140 if($fill==1 && $this->FillColor) {
4141 if((isset($this->pageoutput[$this->page]['FillColor']) && $this->pageoutput[$this->page]['FillColor'] != $this->FillColor) || !isset($this->pageoutput[$this->page]['FillColor'])) { $s .= $this->FillColor.' '; }
4142 $this->pageoutput[$this->page]['FillColor'] = $this->FillColor;
4143 }
4144
4145
4146 if ($lineBox && isset($lineBox['boxtop']) && $txt) { // i.e. always from WriteFlowingBlock/finishFlowingBlock (but not objects -
4147 // which only have $lineBox['top'] set)
4148 $boxtop = $this->y + $lineBox['boxtop'];
4149 $boxbottom = $this->y + $lineBox['boxbottom'];
4150 $glyphYorigin = $lineBox['glyphYorigin'];
4151 $baseline_shift = $lineBox['baseline-shift'];
4152 $bord_boxtop = $bg_boxtop = $boxtop = $boxtop - $baseline_shift;
4153 $bord_boxbottom = $bg_boxbottom = $boxbottom = $boxbottom - $baseline_shift;
4154 $bord_boxheight = $bg_boxheight = $boxheight = $boxbottom - $boxtop;
4155
4156 // If inline element BACKGROUND has bounding box set by parent element:
4157 if (isset($lineBox['background-boxtop'])) {
4158 $bg_boxtop = $this->y + $lineBox['background-boxtop'] - $lineBox['background-baseline-shift'];
4159 $bg_boxbottom = $this->y + $lineBox['background-boxbottom'] - $lineBox['background-baseline-shift'];
4160 $bg_boxheight = $bg_boxbottom - $bg_boxtop;
4161 }
4162 // If inline element BORDER has bounding box set by parent element:
4163 if (isset($lineBox['border-boxtop'])) {
4164 $bord_boxtop = $this->y + $lineBox['border-boxtop'] - $lineBox['border-baseline-shift'];
4165 $bord_boxbottom = $this->y + $lineBox['border-boxbottom'] - $lineBox['border-baseline-shift'];
4166 $bord_boxheight = $bord_boxbottom - $bord_boxtop;
4167 }
4168
4169
4170 }
4171 else {
4172 $boxtop = $this->y;
4173 $boxheight = $h;
4174 $boxbottom = $this->y+$h;
4175 $baseline_shift = 0;
4176 if($txt!='') {
4177 // FONT SIZE - this determines the baseline caculation
4178 $bfs = $this->FontSize;
4179 //Calculate baseline Superscript and Subscript Y coordinate adjustment
4180 $bfx = $this->baselineC;
4181 $baseline = $bfx*$bfs;
4182
4183 if($textvar & FA_SUPERSCRIPT) { $baseline_shift = $this->textparam['text-baseline']; } // mPDF 5.7.1 // mPDF 6
4184 else if($textvar & FA_SUBSCRIPT) { $baseline_shift = $this->textparam['text-baseline']; } // mPDF 5.7.1 // mPDF 6
4185 else if($this->bullet) { $baseline += ($bfx-0.7)*$this->FontSize; }
4186
4187 // Vertical align (for Images)
4188 if ($valign == 'T') { $va = (0.5 * $bfs * $this->normalLineheight); }
4189 else if ($valign == 'B') { $va = $h-(0.5 * $bfs * $this->normalLineheight); }
4190 else { $va = 0.5*$h; } // Middle
4191
4192 // ONLY SET THESE IF WANT TO CONFINE BORDER +/- FILL TO FIT FONTSIZE - NOT FULL CELL AS IS ORIGINAL FUNCTION
4193 // spanfill or spanborder are set in FlowingBlock functions
4194 if ($spanfill || !empty($this->spanborddet) || $link!='') {
4195 $exth = 0.2; // Add to fontsize to increase height of background / link / border
4196 $boxtop = $this->y+$baseline+$va-($this->FontSize*(1+$exth/2)*(0.5+$bfx));
4197 $boxheight = $this->FontSize * (1+$exth);
4198 $boxbottom = $boxtop + $boxheight;
4199 }
4200 $glyphYorigin = $baseline + $va;
4201 }
4202 $boxtop -= $baseline_shift;
4203 $boxbottom -= $baseline_shift;
4204 $bord_boxtop = $bg_boxtop = $boxtop;
4205 $bord_boxbottom = $bg_boxbottom = $boxbottom;
4206 $bord_boxheight = $bg_boxheight = $boxheight = $boxbottom - $boxtop;
4207 }
4208
4209
4210 $bbw = $tbw = $lbw = $rbw = 0; // Border widths
4211 if (!empty($this->spanborddet)) {
4212 if (!isset($this->spanborddet['B'])) { $this->spanborddet['B'] = array('s' => 0, 'style' => '', 'w' => 0); }
4213 if (!isset($this->spanborddet['T'])) { $this->spanborddet['T'] = array('s' => 0, 'style' => '', 'w' => 0); }
4214 if (!isset($this->spanborddet['L'])) { $this->spanborddet['L'] = array('s' => 0, 'style' => '', 'w' => 0); }
4215 if (!isset($this->spanborddet['R'])) { $this->spanborddet['R'] = array('s' => 0, 'style' => '', 'w' => 0); }
4216 $bbw = $this->spanborddet['B']['w'];
4217 $tbw = $this->spanborddet['T']['w'];
4218 $lbw = $this->spanborddet['L']['w'];
4219 $rbw = $this->spanborddet['R']['w'];
4220 }
4221 if($fill==1 || $border==1 || !empty($this->spanborddet)) {
4222 if (!empty($this->spanborddet)) {
4223 if ($fill==1) {
4224 $s.=sprintf('%.3F %.3F %.3F %.3F re f ',($this->x-$lbw)*_MPDFK,($this->h-$bg_boxtop+$tbw)*_MPDFK,($w+$lbw+$rbw)*_MPDFK,(-$bg_boxheight-$tbw-$bbw)*_MPDFK);
4225 }
4226 $s.= ' q ';
4227 $dashon = 3;
4228 $dashoff = 3.5;
4229 $dot = 2.5;
4230 if($tbw) {
4231 $short = 0;
4232 if ($this->spanborddet['T']['style'] == 'dashed') {
4233 $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$tbw*$dashon*_MPDFK,$tbw*$dashoff*_MPDFK);
4234 }
4235 else if ($this->spanborddet['T']['style'] == 'dotted') {
4236 $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$tbw*$dot*_MPDFK,-$tbw/2*_MPDFK);
4237 $short = $tbw/2;
4238 }
4239 else {
4240 $s.=' 0 j 0 J [] 0 d ';
4241 }
4242 if ($this->spanborddet['T']['style'] != 'dotted') {
4243 $s .= 'q ';
4244 $s .= sprintf('%.3F %.3F m ',($this->x-$lbw)*_MPDFK, ($this->h-$bord_boxtop+$tbw)*_MPDFK);
4245 $s .= sprintf('%.3F %.3F l ',($this->x+$w+$rbw)*_MPDFK, ($this->h-$bord_boxtop+$tbw)*_MPDFK);
4246 $s .= sprintf('%.3F %.3F l ',($this->x+$w)*_MPDFK, ($this->h-$bord_boxtop)*_MPDFK);
4247 $s .= sprintf('%.3F %.3F l ',($this->x)*_MPDFK, ($this->h-$bord_boxtop)*_MPDFK);
4248 $s .= ' h W n '; // Ends path no-op & Sets the clipping path
4249
4250 }
4251 $c = $this->SetDColor($this->spanborddet['T']['c'],true);
4252 if ($this->spanborddet['T']['style'] == 'double') {
4253 $s.=sprintf(' %s %.3F w ',$c,$tbw/3*_MPDFK);
4254 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$bord_boxtop+$tbw*5/6)*_MPDFK,($this->x+$w+$rbw)*_MPDFK,($this->h-$bord_boxtop+$tbw*5/6)*_MPDFK);
4255 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$bord_boxtop+$tbw/6)*_MPDFK,($this->x+$w+$rbw)*_MPDFK,($this->h-$bord_boxtop+$tbw/6)*_MPDFK);
4256 }
4257 else if ($this->spanborddet['T']['style'] == 'dotted') {
4258 $s.=sprintf(' %s %.3F w ',$c,$tbw*_MPDFK);
4259 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$bord_boxtop+$tbw/2)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$bord_boxtop+$tbw/2)*_MPDFK);
4260 }
4261 else {
4262 $s.=sprintf(' %s %.3F w ',$c,$tbw*_MPDFK);
4263 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$bord_boxtop+$tbw/2)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$bord_boxtop+$tbw/2)*_MPDFK);
4264 }
4265 if ($this->spanborddet['T']['style'] != 'dotted') {
4266 $s .= ' Q ';
4267 }
4268 }
4269 if($bbw) {
4270 $short = 0;
4271 if ($this->spanborddet['B']['style'] == 'dashed') {
4272 $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$bbw*$dashon*_MPDFK,$bbw*$dashoff*_MPDFK);
4273 }
4274 else if ($this->spanborddet['B']['style'] == 'dotted') {
4275 $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$bbw*$dot*_MPDFK,-$bbw/2*_MPDFK);
4276 $short = $bbw/2;
4277 }
4278 else {
4279 $s.=' 0 j 0 J [] 0 d ';
4280 }
4281 if ($this->spanborddet['B']['style'] != 'dotted') {
4282 $s .= 'q ';
4283 $s .= sprintf('%.3F %.3F m ',($this->x-$lbw)*_MPDFK, ($this->h-$bord_boxbottom-$bbw)*_MPDFK);
4284 $s .= sprintf('%.3F %.3F l ',($this->x+$w+$rbw)*_MPDFK, ($this->h-$bord_boxbottom-$bbw)*_MPDFK);
4285 $s .= sprintf('%.3F %.3F l ',($this->x+$w)*_MPDFK, ($this->h-$bord_boxbottom)*_MPDFK);
4286 $s .= sprintf('%.3F %.3F l ',($this->x)*_MPDFK, ($this->h-$bord_boxbottom)*_MPDFK);
4287 $s .= ' h W n '; // Ends path no-op & Sets the clipping path
4288 }
4289 $c = $this->SetDColor($this->spanborddet['B']['c'],true);
4290 if ($this->spanborddet['B']['style'] == 'double') {
4291 $s.=sprintf(' %s %.3F w ',$c,$bbw/3*_MPDFK);
4292 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$bord_boxbottom-$bbw/6)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$bord_boxbottom-$bbw/6)*_MPDFK);
4293 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$bord_boxbottom-$bbw*5/6)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$bord_boxbottom-$bbw*5/6)*_MPDFK);
4294 }
4295 else if ($this->spanborddet['B']['style'] == 'dotted') {
4296 $s.=sprintf(' %s %.3F w ',$c,$bbw*_MPDFK);
4297 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$bord_boxbottom-$bbw/2)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$bord_boxbottom-$bbw/2)*_MPDFK);
4298 }
4299 else {
4300 $s.=sprintf(' %s %.3F w ',$c,$bbw*_MPDFK);
4301 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$bord_boxbottom-$bbw/2)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$bord_boxbottom-$bbw/2)*_MPDFK);
4302 }
4303 if ($this->spanborddet['B']['style'] != 'dotted') {
4304 $s .= ' Q ';
4305 }
4306 }
4307 if($lbw) {
4308 $short = 0;
4309 if ($this->spanborddet['L']['style'] == 'dashed') {
4310 $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$lbw*$dashon*_MPDFK,$lbw*$dashoff*_MPDFK);
4311 }
4312 else if ($this->spanborddet['L']['style'] == 'dotted') {
4313 $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$lbw*$dot*_MPDFK,-$lbw/2*_MPDFK);
4314 $short = $lbw/2;
4315 }
4316 else {
4317 $s.=' 0 j 0 J [] 0 d ';
4318 }
4319 if ($this->spanborddet['L']['style'] != 'dotted') {
4320 $s .= 'q ';
4321 $s .= sprintf('%.3F %.3F m ',($this->x-$lbw)*_MPDFK, ($this->h-$bord_boxbottom-$bbw)*_MPDFK);
4322 $s .= sprintf('%.3F %.3F l ',($this->x)*_MPDFK, ($this->h-$bord_boxbottom)*_MPDFK);
4323 $s .= sprintf('%.3F %.3F l ',($this->x)*_MPDFK, ($this->h-$bord_boxtop)*_MPDFK);
4324 $s .= sprintf('%.3F %.3F l ',($this->x-$lbw)*_MPDFK, ($this->h-$bord_boxtop+$tbw)*_MPDFK);
4325 $s .= ' h W n '; // Ends path no-op & Sets the clipping path
4326 }
4327 $c = $this->SetDColor($this->spanborddet['L']['c'],true);
4328 if ($this->spanborddet['L']['style'] == 'double') {
4329 $s.=sprintf(' %s %.3F w ',$c,$lbw/3*_MPDFK);
4330 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw/6)*_MPDFK,($this->h-$bord_boxtop+$tbw)*_MPDFK,($this->x-$lbw/6)*_MPDFK,($this->h-$bord_boxbottom-$bbw+$short)*_MPDFK);
4331 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw*5/6)*_MPDFK,($this->h-$bord_boxtop+$tbw)*_MPDFK,($this->x-$lbw*5/6)*_MPDFK,($this->h-$bord_boxbottom-$bbw+$short)*_MPDFK);
4332 }
4333 else if ($this->spanborddet['L']['style'] == 'dotted') {
4334 $s.=sprintf(' %s %.3F w ',$c,$lbw*_MPDFK);
4335 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw/2)*_MPDFK,($this->h-$bord_boxtop+$tbw)*_MPDFK,($this->x-$lbw/2)*_MPDFK,($this->h-$bord_boxbottom-$bbw+$short)*_MPDFK);
4336 }
4337 else {
4338 $s.=sprintf(' %s %.3F w ',$c,$lbw*_MPDFK);
4339 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw/2)*_MPDFK,($this->h-$bord_boxtop+$tbw)*_MPDFK,($this->x-$lbw/2)*_MPDFK,($this->h-$bord_boxbottom-$bbw+$short)*_MPDFK);
4340 }
4341 if ($this->spanborddet['L']['style'] != 'dotted') {
4342 $s .= ' Q ';
4343 }
4344 }
4345 if($rbw) {
4346 $short = 0;
4347 if ($this->spanborddet['R']['style'] == 'dashed') {
4348 $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$rbw*$dashon*_MPDFK,$rbw*$dashoff*_MPDFK);
4349 }
4350 else if ($this->spanborddet['R']['style'] == 'dotted') {
4351 $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$rbw*$dot*_MPDFK,-$rbw/2*_MPDFK);
4352 $short = $rbw/2;
4353 }
4354 else {
4355 $s.=' 0 j 0 J [] 0 d ';
4356 }
4357 if ($this->spanborddet['R']['style'] != 'dotted') {
4358 $s .= 'q ';
4359 $s .= sprintf('%.3F %.3F m ',($this->x+$w+$rbw)*_MPDFK, ($this->h-$bord_boxbottom-$bbw)*_MPDFK);
4360 $s .= sprintf('%.3F %.3F l ',($this->x+$w)*_MPDFK, ($this->h-$bord_boxbottom)*_MPDFK);
4361 $s .= sprintf('%.3F %.3F l ',($this->x+$w)*_MPDFK, ($this->h-$bord_boxtop)*_MPDFK);
4362 $s .= sprintf('%.3F %.3F l ',($this->x+$w+$rbw)*_MPDFK, ($this->h-$bord_boxtop+$tbw)*_MPDFK);
4363 $s .= ' h W n '; // Ends path no-op & Sets the clipping path
4364 }
4365 $c = $this->SetDColor($this->spanborddet['R']['c'],true);
4366 if ($this->spanborddet['R']['style'] == 'double') {
4367 $s.=sprintf(' %s %.3F w ',$c,$rbw/3*_MPDFK);
4368 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw/6)*_MPDFK,($this->h-$bord_boxtop+$tbw)*_MPDFK,($this->x+$w+$rbw/6)*_MPDFK,($this->h-$bord_boxbottom-$bbw+$short)*_MPDFK);
4369 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw*5/6)*_MPDFK,($this->h-$bord_boxtop+$tbw)*_MPDFK,($this->x+$w+$rbw*5/6)*_MPDFK,($this->h-$bord_boxbottom-$bbw+$short)*_MPDFK);
4370 }
4371 else if ($this->spanborddet['R']['style'] == 'dotted') {
4372 $s.=sprintf(' %s %.3F w ',$c,$rbw*_MPDFK);
4373 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw/2)*_MPDFK,($this->h-$bord_boxtop+$tbw)*_MPDFK,($this->x+$w+$rbw/2)*_MPDFK,($this->h-$bord_boxbottom-$bbw+$short)*_MPDFK);
4374 }
4375 else {
4376 $s.=sprintf(' %s %.3F w ',$c,$rbw*_MPDFK);
4377 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw/2)*_MPDFK,($this->h-$bord_boxtop+$tbw)*_MPDFK,($this->x+$w+$rbw/2)*_MPDFK,($this->h-$bord_boxbottom-$bbw+$short)*_MPDFK);
4378 }
4379 if ($this->spanborddet['R']['style'] != 'dotted') {
4380 $s .= ' Q ';
4381 }
4382 }
4383 $s.= ' Q ';
4384 }
4385 else { // If "border", does not come from WriteFlowingBlock or FinishFlowingBlock
4386 if ($fill==1) $op=($border==1) ? 'B' : 'f';
4387 else $op='S';
4388 $s.=sprintf('%.3F %.3F %.3F %.3F re %s ',$this->x*_MPDFK,($this->h-$bg_boxtop)*_MPDFK,$w*_MPDFK,-$bg_boxheight*_MPDFK,$op);
4389 }
4390 }
4391
4392 if(is_string($border)) { // If "border", does not come from WriteFlowingBlock or FinishFlowingBlock
4393 $x=$this->x;
4394 $y=$this->y;
4395 if(is_int(strpos($border,'L')))
4396 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-$bord_boxtop)*_MPDFK,$x*_MPDFK,($this->h-($bord_boxbottom))*_MPDFK);
4397 if(is_int(strpos($border,'T')))
4398 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-$bord_boxtop)*_MPDFK,($x+$w)*_MPDFK,($this->h-$bord_boxtop)*_MPDFK);
4399 if(is_int(strpos($border,'R')))
4400 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($x+$w)*_MPDFK,($this->h-$bord_boxtop)*_MPDFK,($x+$w)*_MPDFK,($this->h-($bord_boxbottom))*_MPDFK);
4401 if(is_int(strpos($border,'B')))
4402 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-($bord_boxbottom))*_MPDFK,($x+$w)*_MPDFK,($this->h-($bord_boxbottom))*_MPDFK);
4403 }
4404
4405 if($txt!='') {
4406
4407
4408 if ($exactWidth)
4409 $stringWidth = $w;
4410 else
4411 $stringWidth = $this->GetStringWidth($txt, true, $OTLdata, $textvar) + ( $this->charspacing * mb_strlen( $txt, $this->mb_enc )/_MPDFK )
4412 + ( $this->ws * mb_substr_count( $txt, ' ', $this->mb_enc ) / _MPDFK );
4413
4414 // Set x OFFSET FOR PRINTING
4415 if($align=='R') {
4416 $dx=$w-$this->cMarginR - $stringWidth - $lcpaddingR;
4417 }
4418 elseif($align=='C') {
4419 $dx=(($w - $stringWidth )/2);
4420 }
4421 elseif($align=='L' or $align=='J') $dx=$this->cMarginL + $lcpaddingL;
4422 else $dx = 0;
4423
4424 if($this->ColorFlag) $s .='q '.$this->TextColor.' ';
4425
4426 // OUTLINE
4427 if(isset($this->textparam['outline-s'] ) && $this->textparam['outline-s'] && !($textvar & FC_SMALLCAPS)) { // mPDF 5.7.1
4428 $s .=' '.sprintf('%.3F w',$this->LineWidth*_MPDFK).' ';
4429 $s .=" $this->DrawColor ";
4430 $s .=" 2 Tr ";
4431 }
4432 else if ($this->falseBoldWeight && strpos($this->ReqFontStyle,"B") !== false && strpos($this->FontStyle,"B") === false && !($textvar & FC_SMALLCAPS)) { // can't use together with OUTLINE or Small Caps // mPDF 5.7.1 ??? why not with SmallCaps ???
4433 $s .= ' 2 Tr 1 J 1 j ';
4434 $s .= ' '.sprintf('%.3F w',($this->FontSize/130)*_MPDFK*$this->falseBoldWeight).' ';
4435 $tc = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
4436 if($this->FillColor!=$tc) { $s .= ' '.$tc.' '; } // stroke (outline) = same colour as text(fill)
4437 }
4438 else { $s .=" 0 Tr "; }
4439
4440 if (strpos($this->ReqFontStyle,"I") !== false && strpos($this->FontStyle,"I") === false) { // Artificial italic
4441 $aix = '1 0 0.261799 1 %.3F %.3F Tm ';
4442 }
4443 else { $aix = '%.3F %.3F Td '; }
4444
4445 $px = ($this->x+$dx)*_MPDFK;
4446 $py = ($this->h-($this->y+$glyphYorigin-$baseline_shift))*_MPDFK;
4447
4448 // THE TEXT
4449 $txt2= $txt;
4450 $sub = '';
4451 $this->CurrentFont['used']= true;
4452
4453 /* *************** SIMILAR TO Text() ************************ */
4454
4455 // IF corefonts AND NOT SmCaps AND NOT Kerning
4456 // Just output text; charspacing and wordspacing already set by charspacing (Tc) and ws (Tw)
4457 if ($this->usingCoreFont && !($textvar & FC_SMALLCAPS) && !($textvar & FC_KERNING)) {
4458 $txt2=$this->_escape($txt2);
4459 $sub .=sprintf('BT '.$aix.' (%s) Tj ET',$px,$py,$txt2);
4460 }
4461
4462
4463 // IF NOT corefonts AND NO wordspacing AND NOT SIP/SMP AND NOT SmCaps AND NOT Kerning AND NOT OTL
4464 // Just output text
4465 else if (!$this->usingCoreFont && !$this->ws && !($textvar & FC_SMALLCAPS) && !($textvar & FC_KERNING) && !(isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0xFF) && !empty($OTLdata['GPOSinfo']))) {
4466 // IF SIP/SMP
4467 if ((isset($this->CurrentFont['sip']) && $this->CurrentFont['sip']) || (isset($this->CurrentFont['smp']) && $this->CurrentFont['smp'])) {
4468 $txt2 = $this->UTF8toSubset($txt2);
4469 $sub .=sprintf('BT '.$aix.' %s Tj ET',$px,$py,$txt2);
4470 }
4471 // NOT SIP/SMP
4472 else {
4473 $txt2 = $this->UTF8ToUTF16BE($txt2, false);
4474 $txt2=$this->_escape($txt2);
4475 $sub .=sprintf('BT '.$aix.' (%s) Tj ET',$px,$py,$txt2);
4476 }
4477 }
4478
4479
4480 // IF NOT corefonts AND IS wordspacing AND NOT SIP AND NOT SmCaps AND NOT Kerning AND NOT OTL
4481 // Output text word by word with an adjustment to the intercharacter spacing for SPACEs to form word spacing
4482 // IF multibyte - Tw has no effect - need to do word spacing using an adjustment before each space
4483 else if (!$this->usingCoreFont && $this->ws && !((isset($this->CurrentFont['sip']) && $this->CurrentFont['sip']) || (isset($this->CurrentFont['smp']) && $this->CurrentFont['smp'])) && !($textvar & FC_SMALLCAPS) && !($textvar & FC_KERNING) && !(isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0xFF) && (!empty($OTLdata['GPOSinfo']) || (strpos($OTLdata['group'],'M')!==false && $this->charspacing)) )) {
4484 $space = " ";
4485 $space= $this->UTF8ToUTF16BE($space, false);
4486 $space=$this->_escape($space);
4487 $sub .=sprintf('BT '.$aix.' %.3F Tc [',$px,$py, $this->charspacing);
4488 $t = explode(' ',$txt2);
4489 $numt = count($t);
4490 for($i=0;$i<$numt;$i++) {
4491 $tx = $t[$i];
4492 $tx = $this->UTF8ToUTF16BE($tx , false);
4493 $tx = $this->_escape($tx);
4494 $sub .=sprintf('(%s) ',$tx);
4495 if (($i+1)<$numt) {
4496 $adj = -($this->ws)*1000/$this->FontSizePt;
4497 $sub .=sprintf('%d(%s) ',$adj,$space);
4498 }
4499 }
4500 $sub .='] TJ ';
4501 $sub .=' ET';
4502 }
4503
4504
4505 // ELSE (IF SmCaps || Kerning || OTL) [corefonts or not corefonts; SIP or SMP or BMP]
4506 else {
4507 $sub = $this->applyGPOSpdf($txt, $aix, $px,$py, $OTLdata, $textvar );
4508 }
4509
4510 /* *************** END SIMILAR TO Text() ************************ */
4511
4512 if ($this->shrin_k > 1) { $shrin_k = $this->shrin_k; }
4513 else { $shrin_k = 1; }
4514 // UNDERLINE
4515 if($textvar & FD_UNDERLINE) { // mPDF 5.7.1 // mPDF 6
4516 // mPDF 5.7.3 inline text-decoration parameters
4517 $c = $this->textparam['u-decoration']['color'];
4518 if($this->FillColor!=$c) { $sub .= ' '.$c.' '; }
4519 // mPDF 5.7.3 inline text-decoration parameters
4520 $decorationfontkey = $this->textparam['u-decoration']['fontkey'];
4521 $decorationfontsize = $this->textparam['u-decoration']['fontsize'] / $shrin_k;
4522 if (isset($this->fonts[$decorationfontkey]['ut']) && $this->fonts[$decorationfontkey]['ut']) { $ut=$this->fonts[$decorationfontkey]['ut']/1000* $decorationfontsize; }
4523 else { $ut = 60/1000* $decorationfontsize; }
4524 if (isset($this->fonts[$decorationfontkey]['up']) && $this->fonts[$decorationfontkey]['up']) { $up=$this->fonts[$decorationfontkey]['up']; }
4525 else { $up = -100; }
4526 $adjusty = (-$up/1000* $decorationfontsize) + $ut/2;
4527 $ubaseline = $glyphYorigin - $this->textparam['u-decoration']['baseline'] / $shrin_k;
4528 $olw = $this->LineWidth;
4529 $sub .=' '.(sprintf(' %.3F w 0 j 0 J ',$ut*_MPDFK));
4530 $sub .=' '.$this->_dounderline($this->x+$dx,$this->y+$ubaseline+$adjusty,$txt,$OTLdata,$textvar);
4531 $sub .=' '.(sprintf(' %.3F w 2 j 2 J ',$olw*_MPDFK));
4532 if($this->FillColor!=$c) { $sub .= ' '.$this->FillColor.' '; }
4533 }
4534
4535 // STRIKETHROUGH
4536 if($textvar & FD_LINETHROUGH) { // mPDF 5.7.1 // mPDF 6
4537 // mPDF 5.7.3 inline text-decoration parameters
4538 $c = $this->textparam['s-decoration']['color'];
4539 if($this->FillColor!=$c) { $sub .= ' '.$c.' '; }
4540 // mPDF 5.7.3 inline text-decoration parameters
4541 $decorationfontkey = $this->textparam['s-decoration']['fontkey'];
4542 $decorationfontsize = $this->textparam['s-decoration']['fontsize'] / $shrin_k;
4543 // Use yStrikeoutSize from OS/2 if available
4544 if (isset($this->fonts[$decorationfontkey]['strs']) && $this->fonts[$decorationfontkey]['strs']) { $ut=$this->fonts[$decorationfontkey]['strs']/1000* $decorationfontsize; }
4545 // else use underlineThickness from post if available
4546 else if (isset($this->fonts[$decorationfontkey]['ut']) && $this->fonts[$decorationfontkey]['ut']) { $ut=$this->fonts[$decorationfontkey]['ut']/1000* $decorationfontsize; }
4547 else { $ut = 50/1000* $decorationfontsize; }
4548 // Use yStrikeoutPosition from OS/2 if available
4549 if (isset($this->fonts[$decorationfontkey]['strp']) && $this->fonts[$decorationfontkey]['strp']) {
4550 $up=$this->fonts[$decorationfontkey]['strp'];
4551 $adjusty = (-$up/1000* $decorationfontsize);
4552 }
4553 // else use a fraction ($this->baselineS) of CapHeight
4554 else {
4555 if (isset($this->fonts[$decorationfontkey]['desc']['CapHeight']) && $this->fonts[$decorationfontkey]['desc']['CapHeight']) { $ch=$this->fonts[$decorationfontkey]['desc']['CapHeight']; }
4556 else { $ch = 700; }
4557 $adjusty = (-$ch/1000* $decorationfontsize) * $this->baselineS;
4558 }
4559
4560 $sbaseline = $glyphYorigin - $this->textparam['s-decoration']['baseline'] / $shrin_k;
4561 $olw = $this->LineWidth;
4562 $sub .=' '.(sprintf(' %.3F w 0 j 0 J ',$ut*_MPDFK));
4563 $sub .=' '.$this->_dounderline($this->x+$dx,$this->y+$sbaseline+$adjusty,$txt,$OTLdata,$textvar);
4564 $sub .=' '.(sprintf(' %.3F w 2 j 2 J ',$olw*_MPDFK));
4565 if($this->FillColor!=$c) { $sub .= ' '.$this->FillColor.' '; }
4566 }
4567
4568 // mPDF 5.7.3 inline text-decoration parameters
4569 // OVERLINE
4570 if($textvar & FD_OVERLINE) { // mPDF 5.7.1 // mPDF 6
4571 // mPDF 5.7.3 inline text-decoration parameters
4572 $c = $this->textparam['o-decoration']['color'];
4573 if($this->FillColor!=$c) { $sub .= ' '.$c.' '; }
4574 // mPDF 5.7.3 inline text-decoration parameters
4575 $decorationfontkey = $this->textparam['o-decoration']['fontkey'] / $shrin_k;
4576 $decorationfontsize = $this->textparam['o-decoration']['fontsize'];
4577 if (isset($this->fonts[$decorationfontkey]['ut']) && $this->fonts[$decorationfontkey]['ut']) { $ut=$this->fonts[$decorationfontkey]['ut']/1000* $decorationfontsize; }
4578 else { $ut = 60/1000* $decorationfontsize; }
4579 if (isset($this->fonts[$decorationfontkey]['desc']['CapHeight']) && $this->fonts[$decorationfontkey]['desc']['CapHeight']) { $ch=$this->fonts[$decorationfontkey]['desc']['CapHeight']; }
4580 else { $ch = 700; }
4581 $adjusty = (-$ch/1000* $decorationfontsize) * $this->baselineO;
4582 $obaseline = $glyphYorigin - $this->textparam['o-decoration']['baseline'] / $shrin_k;
4583 $olw = $this->LineWidth;
4584 $sub .=' '.(sprintf(' %.3F w 0 j 0 J ',$ut*_MPDFK));
4585 $sub .=' '.$this->_dounderline($this->x+$dx,$this->y+$obaseline+$adjusty,$txt,$OTLdata,$textvar);
4586 $sub .=' '.(sprintf(' %.3F w 2 j 2 J ',$olw*_MPDFK));
4587 if($this->FillColor!=$c) { $sub .= ' '.$this->FillColor.' '; }
4588 }
4589
4590 // TEXT SHADOW
4591 if ($this->textshadow) { // First to process is last in CSS comma separated shadows
4592 foreach($this->textshadow AS $ts) {
4593 $s .= ' q ';
4594 $s .= $this->SetTColor($ts['col'], true)."\n";
4595 if ($ts['col']{0}==5 && ord($ts['col']{4})<100) { // RGBa
4596 $s .= $this->SetAlpha(ord($ts['col']{4})/100, 'Normal', true, 'F')."\n";
4597 }
4598 else if ($ts['col']{0}==6 && ord($ts['col']{5})<100) { // CMYKa
4599 $s .= $this->SetAlpha(ord($ts['col']{5})/100, 'Normal', true, 'F')."\n";
4600 }
4601 else if ($ts['col']{0}==1 && $ts['col']{2}==1 && ord($ts['col']{3})<100) { // Gray
4602 $s .= $this->SetAlpha(ord($ts['col']{3})/100, 'Normal', true, 'F')."\n";
4603 }
4604 $s .= sprintf(' 1 0 0 1 %.4F %.4F cm', $ts['x']*_MPDFK, -$ts['y']*_MPDFK)."\n";
4605 $s .= $sub;
4606 $s .= ' Q ';
4607 }
4608 }
4609
4610 $s .= $sub;
4611
4612 // COLOR
4613 if($this->ColorFlag) $s .=' Q';
4614
4615 // LINK
4616 if($link!='') {
4617 $this->Link($this->x,$boxtop,$w,$boxheight,$link);
4618 }
4619 }
4620 if($s) $this->_out($s);
4621
4622 // WORD SPACING
4623 if ($this->ws && !$this->usingCoreFont) {
4624 $this->_out(sprintf('BT %.3F Tc ET',$this->charspacing));
4625 }
4626 $this->lasth=$h;
4627 if( strpos($txt,"\n") !== false) $ln=1; // cell recognizes \n from <BR> tag
4628 if($ln>0)
4629 {
4630 //Go to next line
4631 $this->y += $h;
4632 if($ln==1) {
4633 //Move to next line
4634 if ($currentx != 0) { $this->x=$currentx; }
4635 else { $this->x=$this->lMargin; }
4636 }
4637 }
4638 else $this->x+=$w;
4639
4640
4641 }
4642
4643
4644 function applyGPOSpdf($txt, $aix, $x, $y, $OTLdata, $textvar=0 ) {
4645 // Generate PDF string
4646 //==============================
4647 if ((isset($this->CurrentFont['sip']) && $this->CurrentFont['sip']) || (isset($this->CurrentFont['smp']) && $this->CurrentFont['smp'])) { $sipset = true; }
4648 else { $sipset = false; }
4649
4650 if ($textvar & FC_SMALLCAPS) { $smcaps = true; } // IF SmallCaps using transformation, NOT OTL
4651 else { $smcaps = false; }
4652
4653 if ($sipset) {
4654 $fontid = $last_fontid = $original_fontid = $this->CurrentFont['subsetfontids'][0];
4655 }
4656 else {
4657 $fontid = $last_fontid = $original_fontid = $this->CurrentFont['i'];
4658 }
4659 $SmallCapsON = false; // state: uppercase/not
4660 $lastSmallCapsON = false; // state: uppercase/not
4661 $last_fontsize = $fontsize = $this->FontSizePt;
4662 $last_fontstretch = $fontstretch = 100;
4663 $groupBreak = false;
4664
4665 $unicode = $this->UTF8StringToArray($txt);
4666
4667 $GPOSinfo = (isset($OTLdata['GPOSinfo']) ? $OTLdata['GPOSinfo'] : array());
4668 $charspacing = ($this->charspacing * 1000 / $this->FontSizePt);
4669 $wordspacing = ($this->ws * 1000 / $this->FontSizePt);
4670
4671 $XshiftBefore = 0;
4672 $XshiftAfter = 0;
4673 $lastYPlacement = 0;
4674
4675 if ($sipset) {
4676 // mPDF 6 DELETED ********
4677 // $txt= preg_replace('/'.preg_quote($this->aliasNbPg,'/').'/', chr(7), $txt); // ? Need to adjust OTL info
4678 // $txt= preg_replace('/'.preg_quote($this->aliasNbPgGp,'/').'/', chr(8), $txt); // ? Need to adjust OTL info
4679 $tj = '<';
4680 }
4681 else {
4682 $tj = '(';
4683 }
4684
4685 for($i=0;$i<count($unicode);$i++) {
4686 $c = $unicode[$i];
4687 $tx = '';
4688 $XshiftBefore = $XshiftAfter;
4689 $XshiftAfter = 0;
4690 $YPlacement = 0;
4691 $groupBreak = false;
4692 $kashida = 0;
4693 if (!empty($OTLdata)) {
4694 // YPlacement from GPOS
4695 if (isset($GPOSinfo[$i]['YPlacement']) && $GPOSinfo[$i]['YPlacement']) {
4696 $YPlacement = $GPOSinfo[$i]['YPlacement'] * $this->FontSizePt / $this->CurrentFont['unitsPerEm'];
4697 $groupBreak = true;
4698
4699 }
4700 // XPlacement from GPOS
4701 if (isset($GPOSinfo[$i]['XPlacement']) && $GPOSinfo[$i]['XPlacement']) {
4702
4703 if (!isset($GPOSinfo[$i]['wDir']) || $GPOSinfo[$i]['wDir'] != 'RTL') {
4704 if (isset($GPOSinfo[$i]['BaseWidth'])) {
4705 $GPOSinfo[$i]['XPlacement'] -= $GPOSinfo[$i]['BaseWidth'];
4706 }
4707 }
4708
4709 // Convert to PDF Text space (thousandths of a unit );
4710 $XshiftBefore += $GPOSinfo[$i]['XPlacement'] * 1000 / $this->CurrentFont['unitsPerEm'];
4711 $XshiftAfter += -$GPOSinfo[$i]['XPlacement'] * 1000 / $this->CurrentFont['unitsPerEm'];
4712 }
4713
4714 // Kashida from GPOS
4715 // Kashida is set as an absolute length value, but to adjust text needs to be converted to
4716 // font-related size
4717 if (isset($GPOSinfo[$i]['kashida_space']) && $GPOSinfo[$i]['kashida_space']) {
4718 $kashida = $GPOSinfo[$i]['kashida_space'];
4719 }
4720
4721 if ($c==32) { // word spacing
4722 $XshiftAfter += $wordspacing;
4723 }
4724
4725 if (substr($OTLdata['group'],($i+1),1)!='M') { // Don't add inter-character spacing before Marks
4726 $XshiftAfter += $charspacing;
4727 }
4728
4729 // ...applyGPOSpdf...
4730 // XAdvance from GPOS - Convert to PDF Text space (thousandths of a unit );
4731 if (((isset($GPOSinfo[$i]['wDir']) && $GPOSinfo[$i]['wDir'] != 'RTL') || !isset($GPOSinfo[$i]['wDir'])) && isset($GPOSinfo[$i]['XAdvanceL']) && $GPOSinfo[$i]['XAdvanceL']) {
4732 $XshiftAfter += $GPOSinfo[$i]['XAdvanceL'] * 1000 / $this->CurrentFont['unitsPerEm'];
4733 }
4734 else if (isset($GPOSinfo[$i]['wDir']) && $GPOSinfo[$i]['wDir'] == 'RTL' && isset($GPOSinfo[$i]['XAdvanceR']) && $GPOSinfo[$i]['XAdvanceR']) {
4735 $XshiftAfter += $GPOSinfo[$i]['XAdvanceR'] * 1000 / $this->CurrentFont['unitsPerEm'];
4736 }
4737 }
4738 // Character & Word spacing - if NOT OTL
4739 else {
4740 $XshiftAfter += $charspacing;
4741 if ($c==32) { $XshiftAfter += $wordspacing; }
4742 }
4743
4744 // IF Kerning done using pairs rather than OTL
4745 if ($textvar & FC_KERNING) {
4746 if ($i > 0 && isset($this->CurrentFont['kerninfo'][$unicode[($i-1)]][$unicode[$i]])) {
4747 $XshiftBefore += $this->CurrentFont['kerninfo'][$unicode[($i-1)]][$unicode[$i]];
4748 }
4749 }
4750
4751 if ($YPlacement != $lastYPlacement) { $groupBreak = true; }
4752
4753 if ($XshiftBefore) { // +ve value in PDF moves to the left
4754 // If Fontstretch is ongoing, need to adjust X adjustments because these will be stretched out.
4755 $XshiftBefore *= 100/$last_fontstretch;
4756 if ($sipset) { $tj .= sprintf('>%d<',(-$XshiftBefore) ); }
4757 else { $tj .= sprintf(')%d(',(-$XshiftBefore) ); }
4758 }
4759
4760 // Small-Caps
4761 if ($smcaps) {
4762 if (isset($this->upperCase[$c])) {
4763 $c = $this->upperCase[$c];
4764 //$this->CurrentFont['subset'][$this->upperCase[$c]] = $this->upperCase[$c]; // add the CAP to subset
4765 $SmallCapsON = true;
4766 // For $sipset
4767 if (!$lastSmallCapsON) { // Turn ON SmallCaps
4768 $groupBreak = true;
4769 $fontstretch = $this->smCapsStretch;
4770 $fontsize=$this->FontSizePt*$this->smCapsScale;
4771 }
4772 }
4773 else {
4774 $SmallCapsON = false;
4775 if ($lastSmallCapsON) { // Turn OFF SmallCaps
4776 $groupBreak = true;
4777 $fontstretch = 100;
4778 $fontsize=$this->FontSizePt;
4779 }
4780 }
4781 }
4782
4783 // Prepare Text and Select Font ID
4784 if ($sipset) {
4785 // mPDF 6 DELETED ********
4786 //if ($c == 7 || $c == 8) {
4787 // if ($original_fontid != $last_fontid) {
4788 // $groupBreak = true;
4789 // $fontid = $original_fontid;
4790 // }
4791 // if ($c == 7) { $tj .= $this->aliasNbPgHex; }
4792 // else { $tj .= $this->aliasNbPgGpHex; }
4793 // continue;
4794 //}
4795 for ($j=0; $j<99; $j++) {
4796 $init = array_search($c, $this->CurrentFont['subsets'][$j]);
4797 if ($init!==false) {
4798 if ($this->CurrentFont['subsetfontids'][$j] != $last_fontid) {
4799 $groupBreak = true;
4800 $fontid = $this->CurrentFont['subsetfontids'][$j];
4801 }
4802 $tx = sprintf("%02s", strtoupper(dechex($init)));
4803 break;
4804 }
4805 else if (count($this->CurrentFont['subsets'][$j]) < 255) {
4806 $n = count($this->CurrentFont['subsets'][$j]);
4807 $this->CurrentFont['subsets'][$j][$n] = $c;
4808 if ($this->CurrentFont['subsetfontids'][$j] != $last_fontid) {
4809 $groupBreak = true;
4810 $fontid = $this->CurrentFont['subsetfontids'][$j];
4811 }
4812 $tx = sprintf("%02s", strtoupper(dechex($n)));
4813 break;
4814 }
4815 else if (!isset($this->CurrentFont['subsets'][($j+1)])) {
4816 $this->CurrentFont['subsets'][($j+1)] = array(0=>0);
4817 $this->CurrentFont['subsetfontids'][($j+1)] = count($this->fonts)+$this->extraFontSubsets+1;
4818 $this->extraFontSubsets++;
4819 }
4820 }
4821 }
4822 else {
4823 $tx = code2utf($c);
4824 if ($this->usingCoreFont) {
4825 $tx = utf8_decode($tx);
4826 }
4827 else {
4828 $tx = $this->UTF8ToUTF16BE($tx, false);
4829 }
4830 $tx = $this->_escape($tx);
4831 }
4832
4833 // If any settings require a new Text Group
4834 if ($groupBreak || $fontstretch != $last_fontstretch) {
4835 if ($sipset) { $tj .= '>] TJ '; }
4836 else { $tj .= ')] TJ '; }
4837 if ($fontid != $last_fontid || $fontsize != $last_fontsize) { $tj .= sprintf(' /F%d %.3F Tf ', $fontid , $fontsize); }
4838 if ($fontstretch != $last_fontstretch) { $tj .= sprintf('%d Tz ', $fontstretch); }
4839 if ($YPlacement != $lastYPlacement) { $tj .= sprintf('%.3F Ts ', $YPlacement); }
4840 if ($sipset) { $tj .= '[<'; }
4841 else { $tj .= '[('; }
4842 }
4843
4844 // Output the code for the txt character
4845 $tj .= $tx;
4846 $lastSmallCapsON = $SmallCapsON;
4847 $last_fontid = $fontid;
4848 $last_fontsize = $fontsize;
4849 $last_fontstretch = $fontstretch ;
4850
4851 // Kashida
4852 if ($kashida) {
4853 $c = 0x0640; // add the Tatweel U+0640
4854 if (isset($this->CurrentFont['subset'])) {
4855 $this->CurrentFont['subset'][$c] = $c;
4856 }
4857 $kashida *= 1000 / $this->FontSizePt;
4858 $tatw = $this->_getCharWidth($this->CurrentFont['cw'], 0x0640);
4859
4860 // Get YPlacement from next Base character
4861 $nextbase = $i+1;
4862 while($OTLdata['group']{$nextbase}!='C') { $nextbase++; }
4863 if (isset($GPOSinfo[$nextbase]) && isset($GPOSinfo[$nextbase]['YPlacement']) && $GPOSinfo[$nextbase]['YPlacement']) {
4864 $YPlacement = $GPOSinfo[$nextbase]['YPlacement'] * $this->FontSizePt / $this->CurrentFont['unitsPerEm'];
4865 }
4866
4867 // Prepare Text and Select Font ID
4868 if ($sipset) {
4869 for ($j=0; $j<99; $j++) {
4870 $init = array_search($c, $this->CurrentFont['subsets'][$j]);
4871 if ($init!==false) {
4872 if ($this->CurrentFont['subsetfontids'][$j] != $last_fontid) {
4873 $fontid = $this->CurrentFont['subsetfontids'][$j];
4874 }
4875 $tx = sprintf("%02s", strtoupper(dechex($init)));
4876 break;
4877 }
4878 else if (count($this->CurrentFont['subsets'][$j]) < 255) {
4879 $n = count($this->CurrentFont['subsets'][$j]);
4880 $this->CurrentFont['subsets'][$j][$n] = $c;
4881 if ($this->CurrentFont['subsetfontids'][$j] != $last_fontid) {
4882 $fontid = $this->CurrentFont['subsetfontids'][$j];
4883 }
4884 $tx = sprintf("%02s", strtoupper(dechex($n)));
4885 break;
4886 }
4887 else if (!isset($this->CurrentFont['subsets'][($j+1)])) {
4888 $this->CurrentFont['subsets'][($j+1)] = array(0=>0);
4889 $this->CurrentFont['subsetfontids'][($j+1)] = count($this->fonts)+$this->extraFontSubsets+1;
4890 $this->extraFontSubsets++;
4891 }
4892 }
4893 }
4894 else {
4895 $tx = code2utf($c);
4896 $tx = $this->UTF8ToUTF16BE($tx, false);
4897 $tx = $this->_escape($tx);
4898 }
4899
4900 if ($kashida > $tatw) {
4901 // Insert multiple tatweel characters, repositioning the last one to give correct total length
4902 $fontstretch = 100;
4903 $nt = intval($kashida / $tatw);
4904 $nudgeback = (($nt+1)*$tatw) - $kashida;
4905 $optx = str_repeat($tx, $nt);
4906 if ($sipset) { $optx .= sprintf('>%d<',($nudgeback) ); }
4907 else { $optx .= sprintf(')%d(',($nudgeback) ); }
4908 $optx .= $tx; // #last
4909 }
4910 else {
4911 // Insert single tatweel character and use fontstretch to get correct length
4912 $fontstretch = ($kashida / $tatw) * 100;
4913 $optx = $tx;
4914 }
4915
4916 if ($sipset) { $tj .= '>] TJ '; }
4917 else { $tj .= ')] TJ '; }
4918 if ($fontid != $last_fontid || $fontsize != $last_fontsize) { $tj .= sprintf(' /F%d %.3F Tf ', $fontid , $fontsize); }
4919 if ($fontstretch != $last_fontstretch) { $tj .= sprintf('%d Tz ', $fontstretch); }
4920 $tj .= sprintf('%.3F Ts ', $YPlacement);
4921 if ($sipset) { $tj .= '[<'; }
4922 else { $tj .= '[('; }
4923
4924 // Output the code for the txt character(s)
4925 $tj .= $optx;
4926 $last_fontid = $fontid;
4927 $last_fontstretch = $fontstretch ;
4928 $fontstretch = 100;
4929 }
4930
4931 $lastYPlacement = $YPlacement;
4932
4933 }
4934
4935
4936 // Finish up
4937 if ($sipset) {
4938 $tj .= '>';
4939 if ($XshiftAfter) { $tj .= sprintf('%d',(-$XshiftAfter) ); }
4940 if ($last_fontid != $original_fontid) {
4941 $tj .= '] TJ ';
4942 $tj .= sprintf(' /F%d %.3F Tf ', $original_fontid, $fontsize);
4943 $tj .= '[';
4944 }
4945 $tj = preg_replace('/([^\\\])<>/', '\\1 ', $tj);
4946 }
4947 else {
4948 $tj .= ')';
4949 if ($XshiftAfter) { $tj .= sprintf('%d',(-$XshiftAfter) ); }
4950 if ($last_fontid != $original_fontid) {
4951 $tj .= '] TJ ';
4952 $tj .= sprintf(' /F%d %.3F Tf ', $original_fontid, $fontsize);
4953 $tj .= '[';
4954 }
4955 $tj = preg_replace('/([^\\\])\(\)/', '\\1 ', $tj);
4956 }
4957
4958
4959 $s = sprintf(' BT '.$aix.' 0 Tc 0 Tw [%s] TJ ET ', $x, $y, $tj);
4960
4961 //echo $s."\n\n"; // exit;
4962
4963 return $s;
4964 }
4965
4966 function _kern($txt, $mode, $aix, $x, $y) {
4967 if ($mode == 'MBTw') { // Multibyte requiring word spacing
4968 $space = ' ';
4969 //Convert string to UTF-16BE without BOM
4970 $space= $this->UTF8ToUTF16BE($space , false);
4971 $space=$this->_escape($space );
4972 $s = sprintf(' BT '.$aix,$x*_MPDFK,($this->h-$y)*_MPDFK);
4973 $t = explode(' ',$txt);
4974 for($i=0;$i<count($t);$i++) {
4975 $tx = $t[$i];
4976
4977 $tj = '(';
4978 $unicode = $this->UTF8StringToArray($tx);
4979 for($ti=0;$ti<count($unicode);$ti++) {
4980 if ($ti > 0 && isset($this->CurrentFont['kerninfo'][$unicode[($ti-1)]][$unicode[$ti]])) {
4981 $kern = -$this->CurrentFont['kerninfo'][$unicode[($ti-1)]][$unicode[$ti]];
4982 $tj .= sprintf(')%d(',$kern);
4983 }
4984 $tc = code2utf($unicode[$ti]);
4985 $tc = $this->UTF8ToUTF16BE($tc, false);
4986 $tj .= $this->_escape($tc);
4987 }
4988 $tj .= ')';
4989 $s.=sprintf(' %.3F Tc [%s] TJ',$this->charspacing,$tj);
4990
4991
4992 if (($i+1)<count($t)) {
4993 $s.=sprintf(' %.3F Tc (%s) Tj',$this->ws+$this->charspacing,$space);
4994 }
4995 }
4996 $s.=' ET ';
4997 }
4998 else if (!$this->usingCoreFont) {
4999 $s = '';
5000 $tj = '(';
5001 $unicode = $this->UTF8StringToArray($txt);
5002 for($i=0;$i<count($unicode);$i++) {
5003 if ($i > 0 && isset($this->CurrentFont['kerninfo'][$unicode[($i-1)]][$unicode[$i]])) {
5004 $kern = -$this->CurrentFont['kerninfo'][$unicode[($i-1)]][$unicode[$i]];
5005 $tj .= sprintf(')%d(',$kern);
5006 }
5007 $tx = code2utf($unicode[$i]);
5008 $tx = $this->UTF8ToUTF16BE($tx, false);
5009 $tj .= $this->_escape($tx);
5010 }
5011 $tj .= ')';
5012 $s.=sprintf(' BT '.$aix.' [%s] TJ ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$tj);
5013 }
5014 else { // CORE Font
5015 $s = '';
5016 $tj = '(';
5017 $l = strlen($txt);
5018 for($i=0;$i<$l;$i++) {
5019 if ($i > 0 && isset($this->CurrentFont['kerninfo'][$txt[($i-1)]][$txt[$i]])) {
5020 $kern = -$this->CurrentFont['kerninfo'][$txt[($i-1)]][$txt[$i]];
5021 $tj .= sprintf(')%d(',$kern);
5022 }
5023 $tj .= $this->_escape($txt[$i]);
5024 }
5025 $tj .= ')';
5026 $s.=sprintf(' BT '.$aix.' [%s] TJ ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$tj);
5027 }
5028
5029 return $s;
5030 }
5031
5032
5033
5034
5035 function MultiCell($w,$h,$txt,$border=0,$align='',$fill=0,$link='',$directionality='ltr',$encoded=false, $OTLdata=false, $maxrows=false)
5036 {
5037 // maxrows is called from mpdfform->TEXTAREA
5038 // Parameter (pre-)encoded - When called internally from form::textarea - mb_encoding already done and OTL - but not reverse RTL
5039 if (!$encoded) {
5040 $txt = $this->purify_utf8_text($txt);
5041 if ($this->text_input_as_HTML) {
5042 $txt = $this->all_entities_to_utf8($txt);
5043 }
5044 if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
5045 if (preg_match("/([".$this->pregRTLchars."])/u", $txt)) { $this->biDirectional = true; } // *OTL*
5046 /*-- OTL --*/
5047 $OTLdata = array();
5048 // Use OTL OpenType Table Layout - GSUB & GPOS
5049 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
5050 $txt = $this->otl->applyOTL($txt, $this->CurrentFont['useOTL']);
5051 $OTLdata = $this->otl->OTLdata;
5052 }
5053 if ($directionality == 'rtl' || $this->biDirectional) {
5054 if (!isset($OTLdata)) {
5055 $unicode = $this->UTF8StringToArray($txt, false);
5056 $is_strong = false;
5057 $this->getBasicOTLdata($OTLdata, $unicode, $is_strong);
5058 }
5059 }
5060 /*-- END OTL --*/
5061 }
5062 if (!$align) { $align = $this->defaultAlign; }
5063
5064 //Output text with automatic or explicit line breaks
5065 $cw=&$this->CurrentFont['cw'];
5066 if($w==0) $w=$this->w-$this->rMargin-$this->x;
5067
5068 $wmax = ($w - ($this->cMarginL+$this->cMarginR));
5069 if ($this->usingCoreFont) {
5070 $s=str_replace("\r",'',$txt);
5071 $nb=strlen($s);
5072 while($nb>0 and $s[$nb-1]=="\n") $nb--;
5073 }
5074 else {
5075 $s=str_replace("\r",'',$txt);
5076 $nb=mb_strlen($s, $this->mb_enc );
5077 while($nb>0 and mb_substr($s,$nb-1,1,$this->mb_enc )=="\n") $nb--;
5078 }
5079 $b=0;
5080 if($border) {
5081 if($border==1) {
5082 $border='LTRB';
5083 $b='LRT';
5084 $b2='LR';
5085 }
5086 else {
5087 $b2='';
5088 if(is_int(strpos($border,'L'))) $b2.='L';
5089 if(is_int(strpos($border,'R'))) $b2.='R';
5090 $b=is_int(strpos($border,'T')) ? $b2.'T' : $b2;
5091 }
5092 }
5093 $sep=-1;
5094 $i=0;
5095 $j=0;
5096 $l=0;
5097 $ns=0;
5098 $nl=1;
5099
5100 $rows = 0;
5101 $start_y = $this->y;
5102
5103 if (!$this->usingCoreFont) {
5104 $inclCursive=false;
5105 if (preg_match("/([".$this->pregCURSchars."])/u", $s)) { $inclCursive = true; }
5106 while($i<$nb) {
5107 //Get next character
5108 $c = mb_substr($s,$i,1,$this->mb_enc );
5109 if($c == "\n") {
5110 //Explicit line break
5111 // WORD SPACING
5112 $this->ResetSpacing();
5113 $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
5114 $tmpOTLdata = false;
5115 /*-- OTL --*/
5116 if (isset($OTLdata)) {
5117 $tmpOTLdata = $this->otl->sliceOTLdata($OTLdata, $j, $i-$j);
5118 $this->otl->trimOTLdata($tmpOTLdata, false, true);
5119 $this->magic_reverse_dir($tmp, $directionality, $tmpOTLdata);
5120 }
5121 /*-- END OTL --*/
5122 $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link,0,0,0,'M', 0, false, $tmpOTLdata);
5123 if ($maxrows!=false && isset($this->mpdfform) && ($this->y - $start_y) / $h > $maxrows) { return false; }
5124 $i++;
5125 $sep=-1;
5126 $j=$i;
5127 $l=0;
5128 $ns=0;
5129 $nl++;
5130 if($border and $nl==2) $b=$b2;
5131 continue;
5132 }
5133 if($c == " ") {
5134 $sep=$i;
5135 $ls=$l;
5136 $ns++;
5137 }
5138
5139 $l += $this->GetCharWidthNonCore($c);
5140
5141 if($l>$wmax) {
5142 //Automatic line break
5143 if($sep==-1) { // Only one word
5144 if($i==$j) $i++;
5145 // WORD SPACING
5146 $this->ResetSpacing();
5147 $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
5148 $tmpOTLdata = false;
5149 /*-- OTL --*/
5150 if (isset($OTLdata)) {
5151 $tmpOTLdata = $this->otl->sliceOTLdata($OTLdata, $j, $i-$j);
5152 $this->otl->trimOTLdata($tmpOTLdata, false, true);
5153 $this->magic_reverse_dir($tmp, $directionality, $tmpOTLdata);
5154 }
5155 /*-- END OTL --*/
5156 $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link,0,0,0,'M', 0, false, $tmpOTLdata);
5157 }
5158 else {
5159 $tmp = rtrim(mb_substr($s,$j,$sep-$j,$this->mb_enc));
5160 $tmpOTLdata = false;
5161 /*-- OTL --*/
5162 if (isset($OTLdata)) {
5163 $tmpOTLdata = $this->otl->sliceOTLdata($OTLdata, $j, $sep-$j);
5164 $this->otl->trimOTLdata($tmpOTLdata, false, true);
5165 }
5166 /*-- END OTL --*/
5167 if($align=='J') {
5168 //////////////////////////////////////////
5169 // JUSTIFY J using Unicode fonts (Word spacing doesn't work)
5170 // WORD SPACING UNICODE
5171 // Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
5172 $tmp = str_replace(chr(194).chr(160),chr(32),$tmp );
5173 $len_ligne = $this->GetStringWidth($tmp, false, $tmpOTLdata);
5174 $nb_carac = mb_strlen( $tmp , $this->mb_enc ) ;
5175 $nb_spaces = mb_substr_count( $tmp ,' ', $this->mb_enc ) ;
5176 // Take off number of Marks
5177 // Use GPOS OTL
5178 if (isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'])) {
5179 if (isset($tmpOTLdata['group']) && $tmpOTLdata['group']) {
5180 $nb_carac -= substr_count($tmpOTLdata['group'], 'M');
5181 }
5182 }
5183
5184 list($charspacing,$ws,$kashida) = $this->GetJspacing($nb_carac,$nb_spaces,((($wmax) - $len_ligne) * _MPDFK),$inclCursive, $tmpOTLdata);
5185 $this->SetSpacing($charspacing,$ws);
5186 //////////////////////////////////////////
5187 }
5188 if (isset($OTLdata)) {
5189 $this->magic_reverse_dir($tmp, $directionality, $tmpOTLdata);
5190 }
5191 $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link,0,0,0,'M', 0, false, $tmpOTLdata);
5192 $i=$sep+1;
5193 }
5194 if ($maxrows!=false && isset($this->mpdfform) && ($this->y - $start_y) / $h > $maxrows) { return false; }
5195 $sep=-1;
5196 $j=$i;
5197 $l=0;
5198 $ns=0;
5199 $nl++;
5200 if($border and $nl==2) $b=$b2;
5201 }
5202 else $i++;
5203 }
5204 //Last chunk
5205 // WORD SPACING
5206
5207 $this->ResetSpacing();
5208
5209 }
5210
5211
5212 else {
5213
5214 while($i<$nb) {
5215 //Get next character
5216 $c=$s[$i];
5217 if($c == "\n") {
5218 //Explicit line break
5219 // WORD SPACING
5220 $this->ResetSpacing();
5221 $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link);
5222 if ($maxrows!=false && isset($this->mpdfform) && ($this->y - $start_y) / $h > $maxrows) { return false; }
5223 $i++;
5224 $sep=-1;
5225 $j=$i;
5226 $l=0;
5227 $ns=0;
5228 $nl++;
5229 if($border and $nl==2) $b=$b2;
5230 continue;
5231 }
5232 if($c == " ") {
5233 $sep=$i;
5234 $ls=$l;
5235 $ns++;
5236 }
5237
5238 $l += $this->GetCharWidthCore($c);
5239 if($l>$wmax) {
5240 //Automatic line break
5241 if($sep==-1) {
5242 if($i==$j) $i++;
5243 // WORD SPACING
5244 $this->ResetSpacing();
5245 $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link);
5246 }
5247 else {
5248 if($align=='J') {
5249 $tmp = rtrim(substr($s,$j,$sep-$j));
5250 //////////////////////////////////////////
5251 // JUSTIFY J using Unicode fonts (Word spacing doesn't work)
5252 // WORD SPACING NON_UNICODE/CJK
5253 // Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
5254 $tmp = str_replace(chr(160),chr(32),$tmp);
5255 $len_ligne = $this->GetStringWidth($tmp );
5256 $nb_carac = strlen( $tmp ) ;
5257 $nb_spaces = substr_count( $tmp ,' ' ) ;
5258 $tmpOTLdata = array();
5259 list($charspacing,$ws,$kashida) = $this->GetJspacing($nb_carac,$nb_spaces,((($wmax) - $len_ligne) * _MPDFK),false, $tmpOTLdata);
5260 $this->SetSpacing($charspacing,$ws);
5261 //////////////////////////////////////////
5262 }
5263 $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill,$link);
5264 $i=$sep+1;
5265 }
5266 if ($maxrows!=false && isset($this->mpdfform) && ($this->y - $start_y) / $h > $maxrows) { return false; }
5267 $sep=-1;
5268 $j=$i;
5269 $l=0;
5270 $ns=0;
5271 $nl++;
5272 if($border and $nl==2) $b=$b2;
5273 }
5274 else $i++;
5275 }
5276 //Last chunk
5277 // WORD SPACING
5278
5279 $this->ResetSpacing();
5280
5281 }
5282 //Last chunk
5283 if($border and is_int(strpos($border,'B'))) $b.='B';
5284 if (!$this->usingCoreFont) {
5285 $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
5286 $tmpOTLdata = false;
5287 /*-- OTL --*/
5288 if (isset($OTLdata)) {
5289 $tmpOTLdata = $this->otl->sliceOTLdata($OTLdata, $j, $i-$j);
5290 $this->otl->trimOTLdata($tmpOTLdata, false, true);
5291 $this->magic_reverse_dir($tmp, $directionality, $tmpOTLdata);
5292 }
5293 /*-- END OTL --*/
5294 $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link,0,0,0,'M', 0, false, $tmpOTLdata);
5295 }
5296 else { $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link); }
5297 $this->x=$this->lMargin;
5298 }
5299
5300
5301 /*-- DIRECTW --*/
5302 function Write($h,$txt,$currentx=0,$link='',$directionality='ltr',$align='') {
5303 if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
5304 if (empty($this->directw)) { $this->directw = new directw($this); }
5305 $this->directw->Write($h,$txt,$currentx,$link,$directionality,$align);
5306 }
5307 /*-- END DIRECTW --*/
5308
5309
5310 /*-- HTML-CSS --*/
5311 function saveInlineProperties() {
5312 $saved = array();
5313 $saved[ 'family' ] = $this->FontFamily;
5314 $saved[ 'style' ] = $this->FontStyle;
5315 $saved[ 'sizePt' ] = $this->FontSizePt;
5316 $saved[ 'size' ] = $this->FontSize;
5317 $saved[ 'HREF' ] = $this->HREF;
5318 $saved[ 'textvar' ] = $this->textvar; // mPDF 5.7.1
5319 $saved[ 'OTLtags' ] = $this->OTLtags; // mPDF 5.7.1
5320 $saved[ 'textshadow' ] = $this->textshadow;
5321 $saved[ 'linewidth' ] = $this->LineWidth;
5322 $saved[ 'drawcolor' ] = $this->DrawColor;
5323 $saved[ 'textparam' ] = $this->textparam;
5324 $saved[ 'lSpacingCSS' ] = $this->lSpacingCSS;
5325 $saved[ 'wSpacingCSS' ] = $this->wSpacingCSS;
5326 $saved[ 'I' ] = $this->I;
5327 $saved[ 'B' ] = $this->B;
5328 $saved[ 'colorarray' ] = $this->colorarray;
5329 $saved[ 'bgcolorarray' ] = $this->spanbgcolorarray;
5330 $saved[ 'border' ] = $this->spanborddet;
5331 $saved[ 'color' ] = $this->TextColor;
5332 $saved[ 'bgcolor' ] = $this->FillColor;
5333 $saved[ 'lang' ] = $this->currentLang;
5334 $saved[ 'fontLanguageOverride' ] = $this->fontLanguageOverride; // mPDF 5.7.1
5335 $saved[ 'display_off' ] = $this->inlineDisplayOff;
5336
5337 return $saved;
5338 }
5339
5340 function restoreInlineProperties( &$saved) {
5341 $FontFamily = $saved[ 'family' ];
5342 $this->FontStyle = $saved[ 'style' ];
5343 $this->FontSizePt = $saved[ 'sizePt' ];
5344 $this->FontSize = $saved[ 'size' ];
5345
5346 $this->currentLang = $saved['lang'];
5347 $this->fontLanguageOverride = $saved[ 'fontLanguageOverride' ]; // mPDF 5.7.1
5348
5349 $this->ColorFlag = ($this->FillColor != $this->TextColor); //Restore ColorFlag as well
5350
5351 $this->HREF = $saved[ 'HREF' ];
5352 $this->textvar = $saved[ 'textvar' ]; // mPDF 5.7.1
5353 $this->OTLtags = $saved[ 'OTLtags' ]; // mPDF 5.7.1
5354 $this->textshadow = $saved[ 'textshadow' ];
5355 $this->LineWidth = $saved[ 'linewidth' ];
5356 $this->DrawColor = $saved[ 'drawcolor' ];
5357 $this->textparam = $saved[ 'textparam' ];
5358 $this->inlineDisplayOff = $saved['display_off'];
5359
5360 $this->lSpacingCSS = $saved[ 'lSpacingCSS' ];
5361 if (($this->lSpacingCSS || $this->lSpacingCSS==='0') && strtoupper($this->lSpacingCSS) != 'NORMAL') {
5362 $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize);
5363 }
5364 else { $this->fixedlSpacing = false; }
5365 $this->wSpacingCSS = $saved[ 'wSpacingCSS' ];
5366 if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') {
5367 $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize);
5368 }
5369 else { $this->minwSpacing = 0; }
5370
5371 $this->SetFont($FontFamily, $saved[ 'style' ],$saved[ 'sizePt' ],false);
5372
5373 $this->currentfontstyle = $saved[ 'style' ];
5374 $this->currentfontsize = $saved[ 'sizePt' ];
5375 $this->SetStylesArray(array('B'=>$saved[ 'B' ], 'I'=>$saved[ 'I' ])); // mPDF 5.7.1
5376
5377 $this->TextColor = $saved[ 'color' ];
5378 $this->FillColor = $saved[ 'bgcolor' ];
5379 $this->colorarray = $saved[ 'colorarray' ];
5380 $cor = $saved[ 'colorarray' ];
5381 if ($cor) $this->SetTColor($cor);
5382 $this->spanbgcolorarray = $saved[ 'bgcolorarray' ];
5383 $cor = $saved[ 'bgcolorarray' ];
5384 if ($cor) $this->SetFColor($cor);
5385 $this->spanborddet = $saved[ 'border' ];
5386 }
5387
5388
5389
5390 // Used when ColActive for tables - updated to return first block with background fill OR borders
5391 function GetFirstBlockFill() {
5392 // Returns the first blocklevel that uses a bgcolor fill
5393 $startfill = 0;
5394 for ($i=1;$i<=$this->blklvl;$i++) {
5395 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'] ) {
5396 $startfill = $i;
5397 break;
5398 }
5399 }
5400 return $startfill;
5401 }
5402
5403
5404 //-------------------------FLOWING BLOCK------------------------------------//
5405 //The following functions were originally written by Damon Kohler //
5406 //--------------------------------------------------------------------------//
5407
5408 function saveFont() {
5409 $saved = array();
5410 $saved[ 'family' ] = $this->FontFamily;
5411 $saved[ 'style' ] = $this->FontStyle;
5412 $saved[ 'sizePt' ] = $this->FontSizePt;
5413 $saved[ 'size' ] = $this->FontSize;
5414 $saved[ 'curr' ] = &$this->CurrentFont;
5415 $saved[ 'lang' ] = $this->currentLang; // mPDF 6
5416 $saved[ 'color' ] = $this->TextColor;
5417 $saved[ 'spanbgcolor' ] = $this->spanbgcolor;
5418 $saved[ 'spanbgcolorarray' ] = $this->spanbgcolorarray;
5419 $saved[ 'bord' ] = $this->spanborder;
5420 $saved[ 'border' ] = $this->spanborddet;
5421 $saved[ 'HREF' ] = $this->HREF;
5422 $saved[ 'textvar' ] = $this->textvar; // mPDF 5.7.1
5423 $saved[ 'textshadow' ] = $this->textshadow;
5424 $saved[ 'linewidth' ] = $this->LineWidth;
5425 $saved[ 'drawcolor' ] = $this->DrawColor;
5426 $saved[ 'textparam' ] = $this->textparam;
5427 $saved[ 'ReqFontStyle' ] = $this->ReqFontStyle;
5428 $saved[ 'fixedlSpacing' ] = $this->fixedlSpacing;
5429 $saved[ 'minwSpacing' ] = $this->minwSpacing;
5430 return $saved;
5431 }
5432
5433 function restoreFont( &$saved, $write=true) {
5434 if (!isset($saved) || empty($saved)) return;
5435
5436 $this->FontFamily = $saved[ 'family' ];
5437 $this->FontStyle = $saved[ 'style' ];
5438 $this->FontSizePt = $saved[ 'sizePt' ];
5439 $this->FontSize = $saved[ 'size' ];
5440 $this->CurrentFont = &$saved[ 'curr' ];
5441 $this->currentLang = $saved[ 'lang' ]; // mPDF 6
5442 $this->TextColor = $saved[ 'color' ];
5443 $this->spanbgcolor = $saved[ 'spanbgcolor' ];
5444 $this->spanbgcolorarray = $saved[ 'spanbgcolorarray' ];
5445 $this->spanborder = $saved[ 'bord' ];
5446 $this->spanborddet = $saved[ 'border' ];
5447 $this->ColorFlag = ($this->FillColor != $this->TextColor); //Restore ColorFlag as well
5448 $this->HREF = $saved[ 'HREF' ];
5449 $this->fixedlSpacing = $saved[ 'fixedlSpacing' ];
5450 $this->minwSpacing = $saved[ 'minwSpacing' ];
5451 $this->textvar = $saved[ 'textvar' ]; // mPDF 5.7.1
5452 $this->textshadow = $saved[ 'textshadow' ];
5453 $this->LineWidth = $saved[ 'linewidth' ];
5454 $this->DrawColor = $saved[ 'drawcolor' ];
5455 $this->textparam = $saved[ 'textparam' ];
5456 if ($write) {
5457 $this->SetFont($saved[ 'family' ],$saved[ 'style' ],$saved[ 'sizePt' ],true,true); // force output
5458 $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
5459 if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) { $this->_out($fontout); }
5460 $this->pageoutput[$this->page]['Font'] = $fontout;
5461 }
5462 else
5463 $this->SetFont($saved[ 'family' ],$saved[ 'style' ],$saved[ 'sizePt' ],false);
5464 $this->ReqFontStyle = $saved[ 'ReqFontStyle' ];
5465 }
5466
5467 function newFlowingBlock( $w, $h, $a = '', $is_table = false, $blockstate = 0, $newblock=true, $blockdir='ltr', $table_draft=false)
5468 {
5469 if (!$a) {
5470 if ($blockdir=='rtl') { $a = 'R'; }
5471 else { $a = 'L'; }
5472 }
5473 $this->flowingBlockAttr[ 'width' ] = ($w * _MPDFK);
5474 // line height in user units
5475 $this->flowingBlockAttr[ 'is_table' ] = $is_table;
5476 $this->flowingBlockAttr[ 'table_draft' ] = $table_draft;
5477 $this->flowingBlockAttr[ 'height' ] = $h;
5478 $this->flowingBlockAttr[ 'lineCount' ] = 0;
5479 $this->flowingBlockAttr[ 'align' ] = $a;
5480 $this->flowingBlockAttr[ 'font' ] = array();
5481 $this->flowingBlockAttr[ 'content' ] = array();
5482 $this->flowingBlockAttr[ 'contentB' ] = array();
5483 $this->flowingBlockAttr[ 'contentWidth' ] = 0;
5484 $this->flowingBlockAttr[ 'blockstate' ] = $blockstate;
5485
5486 $this->flowingBlockAttr[ 'newblock' ] = $newblock;
5487 $this->flowingBlockAttr[ 'valign' ] = 'M';
5488 $this->flowingBlockAttr[ 'blockdir' ] = $blockdir;
5489 $this->flowingBlockAttr[ 'cOTLdata' ] = array(); // mPDF 5.7.1
5490 $this->flowingBlockAttr[ 'lastBidiText' ] = ''; // mPDF 5.7.1
5491 if (!empty($this->otl)) { $this->otl->lastBidiStrongType=''; } // *OTL*
5492
5493 }
5494
5495 function finishFlowingBlock($endofblock=false, $next='') {
5496 $currentx = $this->x;
5497 //prints out the last chunk
5498 $is_table = $this->flowingBlockAttr[ 'is_table' ];
5499 $table_draft = $this->flowingBlockAttr[ 'table_draft' ];
5500 $maxWidth =& $this->flowingBlockAttr[ 'width' ];
5501 $stackHeight =& $this->flowingBlockAttr[ 'height' ];
5502 $align =& $this->flowingBlockAttr[ 'align' ];
5503 $content =& $this->flowingBlockAttr[ 'content' ];
5504 $contentB =& $this->flowingBlockAttr[ 'contentB' ];
5505 $font =& $this->flowingBlockAttr[ 'font' ];
5506 $contentWidth =& $this->flowingBlockAttr[ 'contentWidth' ];
5507 $lineCount =& $this->flowingBlockAttr[ 'lineCount' ];
5508 $valign =& $this->flowingBlockAttr[ 'valign' ];
5509 $blockstate = $this->flowingBlockAttr[ 'blockstate' ];
5510
5511 $cOTLdata =& $this->flowingBlockAttr[ 'cOTLdata' ]; // mPDF 5.7.1
5512 $newblock = $this->flowingBlockAttr[ 'newblock' ];
5513 $blockdir = $this->flowingBlockAttr['blockdir'];
5514
5515 // *********** BLOCK BACKGROUND COLOR *****************//
5516 if ($this->blk[$this->blklvl]['bgcolor'] && !$is_table) {
5517 $fill = 0;
5518 }
5519 else {
5520 $this->SetFColor($this->ConvertColor(255));
5521 $fill = 0;
5522 }
5523
5524 $hanger = '';
5525 // Always right trim!
5526 // Right trim last content and adjust width if needed to justify (later)
5527 if (isset($content[count($content)-1]) && preg_match('/[ ]+$/',$content[count($content)-1], $m)) {
5528 $strip = strlen($m[0]);
5529 $content[count($content)-1] = substr($content[count($content)-1],0,(strlen($content[count($content)-1])-$strip));
5530 /*-- OTL --*/
5531 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
5532 $this->otl->trimOTLdata($cOTLdata[count($cOTLdata)-1], false, true);
5533 }
5534 /*-- END OTL --*/
5535 }
5536
5537 // the amount of space taken up so far in user units
5538 $usedWidth = 0;
5539
5540 // COLS
5541 $oldcolumn = $this->CurrCol;
5542
5543 if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
5544
5545 // Print out each chunk
5546
5547 /*-- TABLES --*/
5548 if ($is_table) {
5549 $ipaddingL = 0;
5550 $ipaddingR = 0;
5551 $paddingL = 0;
5552 $paddingR = 0;
5553 }
5554 else {
5555 /*-- END TABLES --*/
5556 $ipaddingL = $this->blk[$this->blklvl]['padding_left'];
5557 $ipaddingR = $this->blk[$this->blklvl]['padding_right'];
5558 $paddingL = ($ipaddingL * _MPDFK);
5559 $paddingR = ($ipaddingR * _MPDFK);
5560 $this->cMarginL = $this->blk[$this->blklvl]['border_left']['w'];
5561 $this->cMarginR = $this->blk[$this->blklvl]['border_right']['w'];
5562
5563 // Added mPDF 3.0 Float DIV
5564 $fpaddingR = 0;
5565 $fpaddingL = 0;
5566 /*-- CSS-FLOAT --*/
5567 if (count($this->floatDivs)) {
5568 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
5569 if ($r_exists) { $fpaddingR = $r_width; }
5570 if ($l_exists) { $fpaddingL = $l_width; }
5571 }
5572 /*-- END CSS-FLOAT --*/
5573
5574 $usey = $this->y + 0.002;
5575 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
5576 $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
5577 }
5578 /*-- CSS-IMAGE-FLOAT --*/
5579 // If float exists at this level
5580 if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
5581 if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
5582 /*-- END CSS-IMAGE-FLOAT --*/
5583 } // *TABLES*
5584
5585
5586 $lineBox = array();
5587
5588 $this->_setInlineBlockHeights($lineBox, $stackHeight, $content, $font, $is_table);
5589
5590 if ($is_table && count($content)==0) { $stackHeight = 0; }
5591
5592 if ($table_draft) {
5593 $this->y += $stackHeight;
5594 $this->objectbuffer = array();
5595 return 0;
5596 }
5597
5598 // While we're at it, check if contains cursive text
5599 // Change NBSP to SPACE.
5600
5601 // Re-calculate contentWidth
5602 $contentWidth = 0;
5603
5604 foreach ( $content as $k => $chunk )
5605 {
5606 $this->restoreFont( $font[ $k ],false );
5607 if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
5608 // Soft Hyphens chr(173)
5609 if (!$this->usingCoreFont) {
5610 /*-- OTL --*/
5611 // mPDF 5.7.1
5612 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
5613 $this->otl->removeChar($chunk, $cOTLdata[$k], "\xc2\xad");
5614 $this->otl->replaceSpace($chunk, $cOTLdata[$k]);
5615 $content[$k] = $chunk;
5616 }
5617 /*-- END OTL --*/
5618 else { // *OTL*
5619 $content[$k] = $chunk = str_replace("\xc2\xad",'',$chunk );
5620 $content[$k] = $chunk = str_replace(chr(194).chr(160),chr(32),$chunk );
5621 } // *OTL*
5622 }
5623 else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
5624 $content[$k] = $chunk = str_replace(chr(173),'',$chunk );
5625 $content[$k] = $chunk = str_replace(chr(160),chr(32),$chunk );
5626 }
5627 $contentWidth += $this->GetStringWidth( $chunk, true, (isset($cOTLdata[$k]) ? $cOTLdata[$k] : false), $this->textvar ) * _MPDFK;
5628
5629 }
5630 else if (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]) {
5631 // LIST MARKERS // mPDF 6 Lists
5632 if ($this->objectbuffer[$k]['type'] == 'image' && isset($this->objectbuffer[$k]['listmarker']) && $this->objectbuffer[$k]['listmarker'] && $this->objectbuffer[$k]['listmarkerposition'] == 'outside') {
5633 // do nothing
5634 }
5635 else {
5636 $contentWidth += $this->objectbuffer[$k]['OUTER-WIDTH'] * _MPDFK;
5637 }
5638 }
5639 }
5640
5641 if(isset($font[count($font)-1])) {
5642 $lastfontreqstyle = (isset($font[count($font)-1]['ReqFontStyle']) ? $font[count($font)-1]['ReqFontStyle'] : '');
5643 $lastfontstyle = (isset($font[count($font)-1]['style']) ? $font[count($font)-1]['style'] : '');
5644 }
5645 else {
5646 $lastfontreqstyle=null;
5647 $lastfontstyle=null;
5648 }
5649 if ($blockdir == 'ltr' && strpos($lastfontreqstyle,"I") !== false && strpos($lastfontstyle,"I") === false) { // Artificial italic
5650 $lastitalic = $this->FontSize*0.15*_MPDFK;
5651 }
5652 else { $lastitalic = 0; }
5653
5654 // Get PAGEBREAK TO TEST for height including the bottom border/padding
5655 $check_h = max($this->divheight,$stackHeight);
5656
5657 // This fixes a proven bug...
5658 if ($endofblock && $newblock && $blockstate==0 && !$content) { $check_h = 0; }
5659 // but ? needs to fix potentially more widespread...
5660 // if (!$content) { $check_h = 0; }
5661
5662 if ($this->blklvl > 0 && !$is_table) {
5663 if ($endofblock && $blockstate > 1) {
5664 if ($this->blk[$this->blklvl]['page_break_after_avoid']) { $check_h += $stackHeight; }
5665 $check_h += ($this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w']);
5666 }
5667 if (($newblock && ($blockstate==1 || $blockstate==3) && $lineCount == 0) || ($endofblock && $blockstate ==3 && $lineCount == 0)) {
5668 $check_h += ($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['border_top']['w']);
5669 }
5670 }
5671
5672 // Force PAGE break if column height cannot take check-height
5673 if ($this->ColActive && $check_h > ($this->PageBreakTrigger - $this->y0)) {
5674 $this->SetCol($this->NbCol-1);
5675 }
5676
5677 // Avoid just border/background-color moved on to next page
5678 if ($endofblock && $blockstate > 1 && !$content) { $buff = $this->margBuffer; }
5679 else { $buff = 0; }
5680
5681
5682 // PAGEBREAK
5683 if(!$is_table && ($this->y+$check_h) > ($this->PageBreakTrigger + $buff) and !$this->InFooter and $this->AcceptPageBreak()) {
5684 $bak_x=$this->x;//Current X position
5685 // WORD SPACING
5686 $ws=$this->ws;//Word Spacing
5687 $charspacing=$this->charspacing;//Character Spacing
5688 $this->ResetSpacing();
5689
5690 $this->AddPage($this->CurOrientation);
5691
5692 $this->x=$bak_x;
5693 // Added to correct for OddEven Margins
5694 $currentx += $this->MarginCorrection;
5695 $this->x += $this->MarginCorrection;
5696
5697 // WORD SPACING
5698 $this->SetSpacing($charspacing,$ws);
5699 }
5700
5701
5702 /*-- COLUMNS --*/
5703 // COLS
5704 // COLUMN CHANGE
5705 if ($this->CurrCol != $oldcolumn) {
5706 $currentx += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
5707 $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
5708 $oldcolumn = $this->CurrCol;
5709 }
5710
5711
5712 if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; }
5713 /*-- END COLUMNS --*/
5714
5715 // TOP MARGIN
5716 if ($newblock && ($blockstate==1 || $blockstate==3) && ($this->blk[$this->blklvl]['margin_top']) && $lineCount == 0 && !$is_table) {
5717 $this->DivLn($this->blk[$this->blklvl]['margin_top'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
5718 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
5719 }
5720
5721 if ($newblock && ($blockstate==1 || $blockstate==3) && $lineCount == 0 && !$is_table) {
5722 $this->blk[$this->blklvl]['y0'] = $this->y;
5723 $this->blk[$this->blklvl]['startpage'] = $this->page;
5724 if ($this->blk[$this->blklvl]['float']) { $this->blk[$this->blklvl]['float_start_y'] = $this->y; }
5725 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
5726 }
5727
5728 // Paragraph INDENT
5729 $WidthCorrection = 0;
5730 if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && ($align != 'C')) {
5731 $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->blk[$this->blklvl]['InlineProperties']['size'],false); // mPDF 5.7.4
5732 $WidthCorrection = ($ti*_MPDFK);
5733 }
5734
5735
5736 // PADDING and BORDER spacing/fill
5737 if (($newblock) && ($blockstate==1 || $blockstate==3) && (($this->blk[$this->blklvl]['padding_top']) || ($this->blk[$this->blklvl]['border_top'])) && ($lineCount == 0) && (!$is_table)) {
5738 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
5739 $this->DivLn($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'],-3,true,false,1);
5740 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
5741 $this->x = $currentx;
5742 }
5743
5744
5745 // Added mPDF 3.0 Float DIV
5746 $fpaddingR = 0;
5747 $fpaddingL = 0;
5748 /*-- CSS-FLOAT --*/
5749 if (count($this->floatDivs)) {
5750 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
5751 if ($r_exists) { $fpaddingR = $r_width; }
5752 if ($l_exists) { $fpaddingL = $l_width; }
5753 }
5754 /*-- END CSS-FLOAT --*/
5755
5756 $usey = $this->y + 0.002;
5757 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
5758 $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
5759 }
5760 /*-- CSS-IMAGE-FLOAT --*/
5761 // If float exists at this level
5762 if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
5763 if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
5764 /*-- END CSS-IMAGE-FLOAT --*/
5765
5766
5767 if ($content) {
5768
5769 // In FinishFlowing Block no lines are justified as it is always last line
5770 // but if CJKorphan has allowed content width to go over max width, use J charspacing to compress line
5771 // JUSTIFICATION J - NOT!
5772 $nb_carac = 0;
5773 $nb_spaces = 0;
5774 $jcharspacing = 0;
5775 $jkashida = 0;
5776 $jws = 0;
5777 $inclCursive=false;
5778 $dottab = false;
5779 foreach ( $content as $k => $chunk ) {
5780 if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
5781 $nb_carac += mb_strlen( $chunk, $this->mb_enc );
5782 $nb_spaces += mb_substr_count( $chunk,' ', $this->mb_enc );
5783 // mPDF 6
5784 // Use GPOS OTL
5785 $this->restoreFont( $font[ $k ], false);
5786 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
5787 if (isset($cOTLdata[$k]['group']) && $cOTLdata[$k]['group']) {
5788 $nb_marks = substr_count($cOTLdata[$k]['group'], 'M');
5789 $nb_carac -= $nb_marks ;
5790 }
5791 if (preg_match("/([".$this->pregCURSchars."])/u", $chunk)) { $inclCursive = true; }
5792 }
5793 }
5794 else {
5795 $nb_carac ++ ; // mPDF 6 allow spacing for inline object
5796 if ($this->objectbuffer[$k]['type']=='dottab') { $dottab = $this->objectbuffer[$k]['outdent']; }
5797 }
5798 }
5799
5800 // DIRECTIONALITY RTL
5801 $chunkorder = range(0, count($content)-1); // mPDF 6
5802 /*-- OTL --*/
5803 // mPDF 6
5804 if ($blockdir == 'rtl' || $this->biDirectional) {
5805 $this->otl->_bidiReorder($chunkorder, $content, $cOTLdata, $blockdir);
5806 // From this point on, $content and $cOTLdata may contain more elements (and re-ordered) compared to
5807 // $this->objectbuffer and $font ($chunkorder contains the mapping)
5808 }
5809 /*-- END OTL --*/
5810
5811 // Remove any XAdvance from OTL data at end of line
5812 // And correct for XPlacement on last character
5813 // BIDI is applied
5814 foreach($chunkorder AS $aord=>$k) {
5815 if (count($cOTLdata)) {
5816 $this->restoreFont( $font[ $k ], false);
5817 // ...FinishFlowingBlock...
5818 if ($aord == count($chunkorder)-1 && isset($cOTLdata[$aord]['group'])) { // Last chunk on line
5819 $nGPOS = strlen($cOTLdata[$aord]['group'])-1; // Last character
5820 if (isset($cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceL']) || isset($cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceR'])) {
5821 if (isset($cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceL'])) {
5822 $w = $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceL'] * 1000/$this->CurrentFont['unitsPerEm'];
5823 }
5824 else {
5825 $w = $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceR'] * 1000/$this->CurrentFont['unitsPerEm'];
5826 }
5827 $w *= ($this->FontSize/ 1000);
5828 $contentWidth -= $w * _MPDFK;
5829 $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceL'] = 0;
5830 $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceR'] = 0;
5831 }
5832
5833 // If last character has an XPlacement set, adjust width calculation, and add to XAdvance to account for it
5834 if (isset($cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XPlacement'])) {
5835 $w = -$cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XPlacement'] * 1000/$this->CurrentFont['unitsPerEm'];
5836 $w *= ($this->FontSize/ 1000);
5837 $contentWidth -= $w * _MPDFK;
5838 $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceL'] = $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XPlacement'];
5839 $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceR'] = $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XPlacement'];
5840 }
5841
5842 }
5843 }
5844 }
5845
5846 // 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)
5847 // If "orphans" in fact is just a final space - ignore this
5848 $lastchar = mb_substr($content[(count($chunkorder)-1)],mb_strlen($content[(count($chunkorder)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
5849 if (preg_match("/[".$this->CJKoverflow."]/u", $lastchar)) { $CJKoverflow = true; }
5850 else {$CJKoverflow = false; }
5851 if ((((($contentWidth + $lastitalic) > $maxWidth) && ($content[(count($chunkorder)-1)] != ' ') ) ||
5852 (!$endofblock && $align=='J' && ($next=='image' || $next=='select' || $next=='input' || $next=='textarea' || ($next=='br' && $this->justifyB4br)))) && !($CJKoverflow && $this->allowCJKoverflow) ) {
5853 // WORD SPACING
5854 list($jcharspacing,$jws,$jkashida) = $this->GetJspacing($nb_carac,$nb_spaces,($maxWidth-$lastitalic-$contentWidth-$WidthCorrection-(($this->cMarginL+$this->cMarginR)*_MPDFK)-($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) )),$inclCursive, $cOTLdata);
5855 }
5856 /*-- CJK-FONTS --*/
5857 else if ($this->checkCJK && $align=='J' && $CJKoverflow && $this->allowCJKoverflow && $this->CJKforceend) {
5858 // force-end overhang
5859 $hanger = mb_substr($content[(count($chunkorder)-1)],mb_strlen($content[(count($chunkorder)-1)],$this->mb_enc)-1,1,$this->mb_enc );
5860 if (preg_match("/[".$this->CJKoverflow."]/u", $hanger)) {
5861 $content[(count($chunkorder)-1)] = mb_substr($content[(count($chunkorder)-1)],0,mb_strlen($content[(count($chunkorder)-1)],$this->mb_enc)-1,$this->mb_enc );
5862 $this->restoreFont( $font[ $chunkorder[count($chunkorder)-1] ],false );
5863 $contentWidth -= $this->GetStringWidth($hanger) * _MPDFK;
5864 $nb_carac -= 1;
5865 list($jcharspacing,$jws,$jkashida) = $this->GetJspacing($nb_carac,$nb_spaces,($maxWidth-$lastitalic-$contentWidth-$WidthCorrection-(($this->cMarginL+$this->cMarginR)*_MPDFK)-($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) )),$inclCursive, $cOTLdata);
5866 }
5867 }
5868 /*-- END CJK-FONTS --*/
5869
5870 // Check if will fit at word/char spacing of previous line - if so continue it
5871 // but only allow a maximum of $this->jSmaxWordLast and $this->jSmaxCharLast
5872 else if ($contentWidth < ($maxWidth - $lastitalic-$WidthCorrection - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK))) && !$this->fixedlSpacing) {
5873 if ($this->ws > $this->jSmaxWordLast) {
5874 $jws = $this->jSmaxWordLast;
5875 }
5876 if ($this->charspacing > $this->jSmaxCharLast) {
5877 $jcharspacing = $this->jSmaxCharLast;
5878 }
5879 $check = $maxWidth - $lastitalic-$WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) ) - ( $jcharspacing * $nb_carac) - ( $jws * $nb_spaces);
5880 if ($check <= 0) {
5881 $jcharspacing = 0;
5882 $jws = 0;
5883 }
5884 }
5885
5886 $empty = $maxWidth - $lastitalic-$WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
5887
5888
5889 $empty -= ($jcharspacing * ($nb_carac-1)); // mPDF 6 nb_carac MINUS 1
5890 $empty -= ($jws * $nb_spaces);
5891 $empty -= ($jkashida);
5892
5893 $empty /= _MPDFK;
5894
5895 if (!$is_table) {
5896 $this->maxPosR = max($this->maxPosR , ($this->w - $this->rMargin - $this->blk[$this->blklvl]['outer_right_margin'] - $empty));
5897 $this->maxPosL = min($this->maxPosL , ($this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $empty));
5898 }
5899
5900 $arraysize = count($chunkorder);
5901
5902 $margins = ($this->cMarginL+$this->cMarginR) + ($ipaddingL+$ipaddingR + $fpaddingR + $fpaddingR );
5903
5904 if (!$is_table) { $this->DivLn($stackHeight,$this->blklvl,false); } // false -> don't advance y
5905
5906 $this->x = $currentx + $this->cMarginL + $ipaddingL + $fpaddingL;
5907 if ($dottab !== false && $blockdir=='rtl') { $this->x -= $dottab; }
5908 else if ($align == 'R') { $this->x += $empty; }
5909 else if ($align == 'J' && $blockdir == 'rtl') { $this->x += $empty; }
5910 else if ($align == 'C') { $this->x += ($empty / 2); }
5911
5912 // Paragraph INDENT
5913 $WidthCorrection = 0;
5914 if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && ($align !='C')) {
5915 $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->blk[$this->blklvl]['InlineProperties']['size'],false); // mPDF 5.7.4
5916 if ($blockdir!='rtl') { $this->x += $ti; } // mPDF 6
5917 }
5918
5919 foreach($chunkorder AS $aord=>$k) { // mPDF 5.7
5920 $chunk = $content[$aord];
5921 if (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]) {
5922
5923 $xadj = $this->x - $this->objectbuffer[$k]['OUTER-X'];
5924 $this->objectbuffer[$k]['OUTER-X'] += $xadj;
5925 $this->objectbuffer[$k]['BORDER-X'] += $xadj;
5926 $this->objectbuffer[$k]['INNER-X'] += $xadj;
5927
5928 if ($this->objectbuffer[$k]['type'] == 'listmarker') {
5929 $this->objectbuffer[$k]['lineBox'] = $lineBox[-1]; // Block element details for glyph-origin
5930 }
5931 $yadj = $this->y - $this->objectbuffer[$k]['OUTER-Y'];
5932 if ($this->objectbuffer[$k]['type'] == 'dottab') { // mPDF 6 DOTTAB
5933 $this->objectbuffer[$k]['lineBox'] = $lineBox[$k]; // element details for glyph-origin
5934 }
5935 if ($this->objectbuffer[$k]['type'] != 'dottab') { // mPDF 6 DOTTAB
5936 $yadj += $lineBox[$k]['top'];
5937 }
5938 $this->objectbuffer[$k]['OUTER-Y'] += $yadj;
5939 $this->objectbuffer[$k]['BORDER-Y'] += $yadj;
5940 $this->objectbuffer[$k]['INNER-Y'] += $yadj;
5941
5942 }
5943
5944 $this->restoreFont( $font[ $k ] ); // mPDF 5.7
5945
5946 if ($is_table && substr($align,0,1)=='D' && $aord==0 ) {
5947 $dp = $this->decimal_align[substr($align,0,2)];
5948 $s = preg_split('/'.preg_quote($dp,'/').'/', $content[0], 2); // ? needs to be /u if not core
5949 $s0 = $this->GetStringWidth($s[0], false);
5950 $this->x += ($this->decimal_offset - $s0);
5951 }
5952
5953 $this->SetSpacing(($this->fixedlSpacing*_MPDFK)+$jcharspacing,($this->fixedlSpacing+$this->minwSpacing)*_MPDFK+$jws);
5954 $this->fixedlSpacing = false;
5955 $this->minwSpacing = 0;
5956
5957 $save_vis = $this->visibility;
5958 if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->textparam['visibility'] != $this->visibility) {
5959 $this->SetVisibility($this->textparam['visibility']);
5960 }
5961
5962 // *********** SPAN BACKGROUND COLOR ***************** //
5963 if (isset($this->spanbgcolor) && $this->spanbgcolor) {
5964 $cor = $this->spanbgcolorarray;
5965 $this->SetFColor($cor);
5966 $save_fill = $fill; $spanfill = 1; $fill = 1;
5967 }
5968 if (!empty($this->spanborddet)) {
5969 if (strpos($contentB[$k],'L')!==false && isset($this->spanborddet['L'])) $this->x += $this->spanborddet['L']['w'];
5970 if (strpos($contentB[$k],'L')===false) $this->spanborddet['L']['s'] = $this->spanborddet['L']['w'] = 0;
5971 if (strpos($contentB[$k],'R')===false) $this->spanborddet['R']['s'] = $this->spanborddet['R']['w'] = 0;
5972 }
5973 // WORD SPACING
5974 // mPDF 5.7.1
5975 $stringWidth = $this->GetStringWidth($chunk, true, (isset($cOTLdata[$aord]) ? $cOTLdata[$aord] : false), $this->textvar );
5976 $nch = mb_strlen($chunk,$this->mb_enc );
5977 // Use GPOS OTL
5978 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
5979 if (isset($cOTLdata[$aord]['group']) && $cOTLdata[$aord]['group']) {
5980 $nch -= substr_count($cOTLdata[$aord]['group'], 'M');
5981 }
5982 }
5983 $stringWidth += ( $this->charspacing * $nch / _MPDFK );
5984
5985 $stringWidth += ( $this->ws * mb_substr_count($chunk,' ',$this->mb_enc ) / _MPDFK );
5986
5987 if (isset($this->objectbuffer[$k])) {
5988 if ($this->objectbuffer[$k]['type']=='dottab') {
5989 $this->objectbuffer[$k]['OUTER-WIDTH'] +=$empty;
5990 $this->objectbuffer[$k]['OUTER-WIDTH'] +=$this->objectbuffer[$k]['outdent'];
5991 }
5992 // LIST MARKERS // mPDF 6 Lists
5993 if ($this->objectbuffer[$k]['type'] == 'image' && isset($this->objectbuffer[$k]['listmarker']) && $this->objectbuffer[$k]['listmarker'] && $this->objectbuffer[$k]['listmarkerposition'] == 'outside') {
5994 // do nothing
5995 }
5996 else {
5997 $stringWidth = $this->objectbuffer[$k]['OUTER-WIDTH'];
5998 }
5999 }
6000
6001 if ($stringWidth==0) { $stringWidth = 0.000001; }
6002 if ($aord == $arraysize-1) { // mPDF 5.7
6003 // mPDF 5.7.1
6004 if ($this->checkCJK && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $hanger && $this->CJKforceend) {
6005 // force-end overhang
6006 $this->Cell( $stringWidth, $stackHeight, $chunk, '', 0, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, true, (isset($cOTLdata[$aord]) ? $cOTLdata[$aord] : false), $this->textvar, (isset($lineBox[$k]) ? $lineBox[$k] : false)); // mPDF 5.7.1
6007 $this->Cell( $this->GetStringWidth($hanger), $stackHeight, $hanger, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, true, (isset($cOTLdata[$aord]) ? $cOTLdata[$aord] : false), $this->textvar, (isset($lineBox[$k]) ? $lineBox[$k] : false)); // mPDF 5.7.1
6008 }
6009 else {
6010 $this->Cell( $stringWidth, $stackHeight, $chunk, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, true, (isset($cOTLdata[$aord]) ? $cOTLdata[$aord] : false), $this->textvar, (isset($lineBox[$k]) ? $lineBox[$k] : false)); // mPDF 5.7.1
6011 }
6012 }
6013 else $this->Cell( $stringWidth, $stackHeight, $chunk, '', 0, '', $fill, $this->HREF, 0, 0,0,'M', $fill, true, (isset($cOTLdata[$aord]) ? $cOTLdata[$aord] : false), $this->textvar, (isset($lineBox[$k]) ? $lineBox[$k] : false));//first or middle part // mPDF 5.7.1
6014
6015
6016 if (!empty($this->spanborddet)) {
6017 if (strpos($contentB[$k],'R')!==false && $aord != $arraysize-1) $this->x += $this->spanborddet['R']['w'];
6018 }
6019 // *********** SPAN BACKGROUND COLOR OFF - RESET BLOCK BGCOLOR ***************** //
6020 if (isset($spanfill) && $spanfill) {
6021 $fill = $save_fill; $spanfill = 0;
6022 if ($fill) { $this->SetFColor($bcor); }
6023 }
6024 if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->visibility != $save_vis) {
6025 $this->SetVisibility($save_vis);
6026 }
6027
6028 }
6029
6030 $this->printobjectbuffer($is_table, $blockdir);
6031 $this->objectbuffer = array();
6032 $this->ResetSpacing();
6033
6034 } // END IF CONTENT
6035
6036 /*-- CSS-IMAGE-FLOAT --*/
6037 // Update values if set to skipline
6038 if ($this->floatmargins) { $this->_advanceFloatMargins(); }
6039
6040
6041 if ($endofblock && $blockstate>1) {
6042 // If float exists at this level
6043 if (isset($this->floatmargins['R']['y1'])) { $fry1 = $this->floatmargins['R']['y1']; }
6044 else { $fry1 = 0; }
6045 if (isset($this->floatmargins['L']['y1'])) { $fly1 = $this->floatmargins['L']['y1']; }
6046 else { $fly1 = 0; }
6047 if ($this->y < $fry1 || $this->y < $fly1) {
6048 $drop = max($fry1,$fly1) - $this->y;
6049 $this->DivLn($drop);
6050 $this->x = $currentx;
6051 }
6052 }
6053 /*-- END CSS-IMAGE-FLOAT --*/
6054
6055
6056 // PADDING and BORDER spacing/fill
6057 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)) {
6058 // If CSS height set, extend bottom - if on same page as block started, and CSS HEIGHT > actual height,
6059 // and does not force pagebreak
6060 $extra = 0;
6061 if (isset($this->blk[$this->blklvl]['css_set_height']) && $this->blk[$this->blklvl]['css_set_height'] && $this->blk[$this->blklvl]['startpage']==$this->page) {
6062 // predicted height
6063 $h1 = ($this->y-$this->blk[$this->blklvl]['y0']) + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'];
6064 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; }
6065 if($this->y + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'] + $extra > $this->PageBreakTrigger) {
6066 $extra = $this->PageBreakTrigger - ($this->y + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w']);
6067 }
6068 }
6069
6070 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
6071 $this->DivLn($this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'] + $extra,-3,true,false,2);
6072 $this->x = $currentx;
6073
6074 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
6075
6076 }
6077
6078 // SET Bottom y1 of block (used for painting borders)
6079 if (($endofblock) && ($blockstate > 1) && (!$is_table)) {
6080 $this->blk[$this->blklvl]['y1'] = $this->y;
6081 }
6082
6083 // BOTTOM MARGIN
6084 if (($endofblock) && ($blockstate > 1) && ($this->blk[$this->blklvl]['margin_bottom']) && (!$is_table)) {
6085 if($this->y+$this->blk[$this->blklvl]['margin_bottom'] < $this->PageBreakTrigger and !$this->InFooter) {
6086 $this->DivLn($this->blk[$this->blklvl]['margin_bottom'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
6087 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
6088 }
6089 }
6090
6091 // Reset lineheight
6092 $stackHeight = $this->divheight;
6093 }
6094
6095
6096
6097
6098
6099 function printobjectbuffer($is_table=false, $blockdir=false) {
6100 if (!$blockdir) { $blockdir = $this->directionality; }
6101 if ($is_table && $this->shrin_k > 1) { $k = $this->shrin_k; }
6102 else { $k = 1; }
6103 $save_y = $this->y;
6104 $save_x = $this->x;
6105 $save_currentfontfamily = $this->FontFamily;
6106 $save_currentfontsize = $this->FontSizePt;
6107 $save_currentfontstyle = $this->FontStyle;
6108 if ($blockdir == 'rtl') { $rtlalign = 'R'; } else { $rtlalign = 'L'; }
6109 foreach ($this->objectbuffer AS $ib => $objattr) {
6110 if ($objattr['type'] == 'bookmark' || $objattr['type'] == 'indexentry' || $objattr['type'] == 'toc') {
6111 $x = $objattr['OUTER-X'];
6112 $y = $objattr['OUTER-Y'];
6113 $this->y = $y - $this->FontSize/2;
6114 $this->x = $x;
6115 if ($objattr['type'] == 'bookmark' ) { $this->Bookmark($objattr['CONTENT'],$objattr['bklevel'] ,$y - $this->FontSize); } // *BOOKMARKS*
6116 if ($objattr['type'] == 'indexentry') { $this->IndexEntry($objattr['CONTENT']); } // *INDEX*
6117 if ($objattr['type'] == 'toc') { $this->TOC_Entry($objattr['CONTENT'], $objattr['toclevel'], (isset($objattr['toc_id']) ? $objattr['toc_id'] : '')); } // *TOC*
6118 }
6119 /*-- ANNOTATIONS --*/
6120 else if ($objattr['type'] == 'annot') {
6121 if ($objattr['POS-X']) { $x = $objattr['POS-X']; }
6122 else if ($this->annotMargin<>0) { $x = -$objattr['OUTER-X']; }
6123 else { $x = $objattr['OUTER-X']; }
6124 if ($objattr['POS-Y']) { $y = $objattr['POS-Y']; }
6125 else { $y = $objattr['OUTER-Y'] - $this->FontSize/2; }
6126 // Create a dummy entry in the _out/columnBuffer with position sensitive data,
6127 // linking $y-1 in the Columnbuffer with entry in $this->columnAnnots
6128 // and when columns are split in length will not break annotation from current line
6129 $this->y = $y-1;
6130 $this->x = $x-1;
6131 $this->Line($x-1,$y-1,$x-1,$y-1);
6132 $this->Annotation($objattr['CONTENT'], $x , $y , $objattr['ICON'], $objattr['AUTHOR'], $objattr['SUBJECT'], $objattr['OPACITY'], $objattr['COLOR'], (isset($objattr['POPUP']) ? $objattr['POPUP'] : '') , (isset($objattr['FILE']) ? $objattr['FILE'] : '') );
6133 }
6134 /*-- END ANNOTATIONS --*/
6135 else {
6136 $y = $objattr['OUTER-Y'];
6137 $x = $objattr['OUTER-X'];
6138 $w = $objattr['OUTER-WIDTH'];
6139 $h = $objattr['OUTER-HEIGHT'];
6140 if (isset($objattr['text'])) { $texto = $objattr['text']; }
6141 $this->y = $y;
6142 $this->x = $x;
6143 if (isset($objattr['fontfamily'])) { $this->SetFont($objattr['fontfamily'],'',$objattr['fontsize'] ); }
6144 }
6145
6146 // HR
6147 if ($objattr['type'] == 'hr') {
6148 $this->SetDColor($objattr['color']);
6149 switch($objattr['align']) {
6150 case 'C':
6151 $empty = $objattr['OUTER-WIDTH'] - $objattr['INNER-WIDTH'];
6152 $empty /= 2;
6153 $x += $empty;
6154 break;
6155 case 'R':
6156 $empty = $objattr['OUTER-WIDTH'] - $objattr['INNER-WIDTH'];
6157 $x += $empty;
6158 break;
6159 }
6160 $oldlinewidth = $this->LineWidth;
6161 $this->SetLineWidth($objattr['linewidth']/$k );
6162 $this->y += ($objattr['linewidth']/2) + $objattr['margin_top']/$k;
6163 $this->Line($x,$this->y,$x+$objattr['INNER-WIDTH'],$this->y);
6164 $this->SetLineWidth($oldlinewidth);
6165 $this->SetDColor($this->ConvertColor(0));
6166 }
6167 // IMAGE
6168 if ($objattr['type'] == 'image') {
6169 // mPDF 5.7.3 TRANSFORMS
6170 if (isset($objattr['transform'])) {
6171 $this->_out("\n".'% BTR'); // Begin Transform
6172 }
6173 if (isset($objattr['z-index']) && $objattr['z-index'] > 0 && $this->current_layer==0) {
6174 $this->BeginLayer($objattr['z-index']);
6175 }
6176 if(isset($objattr['visibility']) && $objattr['visibility']!='visible' && $objattr['visibility']) {
6177 $this->SetVisibility($objattr['visibility']);
6178 }
6179 if (isset($objattr['opacity'])) { $this->SetAlpha($objattr['opacity']); }
6180
6181 $obiw = $objattr['INNER-WIDTH'];
6182 $obih = $objattr['INNER-HEIGHT'];
6183 $sx = $objattr['INNER-WIDTH']*_MPDFK / $objattr['orig_w'];
6184 $sy = abs($objattr['INNER-HEIGHT'])*_MPDFK / abs($objattr['orig_h']);
6185 $sx = ($objattr['INNER-WIDTH']*_MPDFK / $objattr['orig_w']);
6186 $sy = ($objattr['INNER-HEIGHT']*_MPDFK / $objattr['orig_h']);
6187
6188 $rotate = 0;
6189 if (isset($objattr['ROTATE'])) { $rotate = $objattr['ROTATE']; }
6190 if ($rotate==90) {
6191 // Clockwise
6192 $obiw = $objattr['INNER-HEIGHT'];
6193 $obih = $objattr['INNER-WIDTH'];
6194 $tr = $this->transformTranslate(0, -$objattr['INNER-WIDTH'], true) ;
6195 $tr .= ' '. $this->transformRotate(90, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-WIDTH'] ),true) ;
6196 $sx = $obiw*_MPDFK / $objattr['orig_h'];
6197 $sy = $obih*_MPDFK / $objattr['orig_w'];
6198 }
6199 else if ($rotate==-90 || $rotate==270) {
6200 // AntiClockwise
6201 $obiw = $objattr['INNER-HEIGHT'];
6202 $obih = $objattr['INNER-WIDTH'];
6203 $tr = $this->transformTranslate($objattr['INNER-WIDTH'], ($objattr['INNER-HEIGHT']-$objattr['INNER-WIDTH']), true) ;
6204 $tr .= ' '. $this->transformRotate(-90, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-WIDTH'] ),true) ;
6205 $sx = $obiw*_MPDFK / $objattr['orig_h'];
6206 $sy = $obih*_MPDFK / $objattr['orig_w'];
6207 }
6208 else if ($rotate==180) {
6209 // Mirror
6210 $tr = $this->transformTranslate($objattr['INNER-WIDTH'], -$objattr['INNER-HEIGHT'], true) ;
6211 $tr .= ' '. $this->transformRotate(180, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-HEIGHT'] ),true) ;
6212 }
6213 else { $tr = ''; }
6214 $tr = trim($tr);
6215 if ($tr) { $tr .= ' '; }
6216 $gradmask = '';
6217
6218 // mPDF 5.7.3 TRANSFORMS
6219 $tr2 = '';
6220 if (isset($objattr['transform'])) {
6221 $maxsize_x = $w;
6222 $maxsize_y = $h;
6223 $cx = $x + $w/2;
6224 $cy = $y + $h/2;
6225 preg_match_all('/(translatex|translatey|translate|scalex|scaley|scale|rotate|skewX|skewY|skew)\((.*?)\)/is',$objattr['transform'],$m);
6226 if (count($m[0])) {
6227 for($i=0; $i<count($m[0]); $i++) {
6228 $c = strtolower($m[1][$i]);
6229 $v = trim($m[2][$i]);
6230 $vv = preg_split('/[ ,]+/',$v);
6231 if ($c=='translate' && count($vv)) {
6232 $translate_x = $this->ConvertSize($vv[0],$maxsize_x,false,false);
6233 if (count($vv)==2) { $translate_y = $this->ConvertSize($vv[1],$maxsize_y,false,false); }
6234 else { $translate_y = 0; }
6235 $tr2 .= $this->transformTranslate($translate_x, $translate_y, true).' ';
6236 }
6237 else if ($c=='translatex' && count($vv)) {
6238 $translate_x = $this->ConvertSize($vv[0],$maxsize_x,false,false);
6239 $tr2 .= $this->transformTranslate($translate_x, 0, true).' ';
6240 }
6241 else if ($c=='translatey' && count($vv)) {
6242 $translate_y = $this->ConvertSize($vv[1],$maxsize_y,false,false);
6243 $tr2 .= $this->transformTranslate(0, $translate_y, true).' ';
6244 }
6245 else if ($c=='scale' && count($vv)) {
6246 $scale_x = $vv[0] * 100;
6247 if (count($vv)==2) { $scale_y = $vv[1] * 100; }
6248 else { $scale_y = $scale_x; }
6249 $tr2 .= $this->transformScale($scale_x, $scale_y, $cx, $cy, true).' ';
6250 }
6251 else if ($c=='scalex' && count($vv)) {
6252 $scale_x = $vv[0] * 100;
6253 $tr2 .= $this->transformScale($scale_x, 0, $cx, $cy, true).' ';
6254 }
6255 else if ($c=='scaley' && count($vv)) {
6256 $scale_y = $vv[1] * 100;
6257 $tr2 .= $this->transformScale(0, $scale_y, $cx, $cy, true).' ';
6258 }
6259 else if ($c=='skew' && count($vv)) {
6260 $angle_x = $this->ConvertAngle($vv[0], false);
6261 if (count($vv)==2) { $angle_y = $this->ConvertAngle($vv[1], false); }
6262 else { $angle_y = 0; }
6263 $tr2 .= $this->transformSkew($angle_x, $angle_y, $cx, $cy, true).' ';
6264 }
6265 else if ($c=='skewx' && count($vv)) {
6266 $angle = $this->ConvertAngle($vv[0], false);
6267 $tr2 .= $this->transformSkew($angle, 0, $cx, $cy, true).' ';
6268 }
6269 else if ($c=='skewy' && count($vv)) {
6270 $angle = $this->ConvertAngle($vv[0], false);
6271 $tr2 .= $this->transformSkew(0, $angle, $cx, $cy, true).' ';
6272 }
6273 else if ($c=='rotate' && count($vv)) {
6274 $angle = $this->ConvertAngle($vv[0]);
6275 $tr2 .= $this->transformRotate($angle, $cx, $cy, true).' ';
6276 }
6277 }
6278 }
6279 }
6280
6281 // LIST MARKERS (Images) // mPDF 6 Lists
6282 if (isset($objattr['listmarker']) && $objattr['listmarker'] && $objattr['listmarkerposition']=='outside') {
6283 $mw = $objattr['OUTER-WIDTH'];
6284 // NB If change marker-offset, also need to alter in function _getListMarkerWidth
6285 $adjx = $this->ConvertSize($this->list_marker_offset,$this->FontSize);
6286 if ($objattr['dir'] == 'rtl') {
6287 $objattr['INNER-X'] += $adjx ;
6288 }
6289 else {
6290 $objattr['INNER-X'] -= $adjx ;
6291 $objattr['INNER-X'] -= $mw;
6292 }
6293 }
6294 // mPDF 5.7.3 TRANSFORMS / BACKGROUND COLOR
6295 // Transform also affects image background
6296 if ($tr2) { $this->_out('q '.$tr2.' '); }
6297 if (isset($objattr['bgcolor']) && $objattr['bgcolor']) {
6298 $bgcol = $objattr['bgcolor'];
6299 $this->SetFColor($bgcol);
6300 $this->Rect($x,$y,$w,$h, 'F');
6301 $this->SetFColor($this->ConvertColor(255));
6302 }
6303 if ($tr2) { $this->_out('Q'); }
6304
6305 /*-- BACKGROUNDS --*/
6306 if (isset($objattr['GRADIENT-MASK'])) {
6307 $g = $this->grad->parseMozGradient( $objattr['GRADIENT-MASK'] );
6308 if ($g) {
6309 $dummy = $this->grad->Gradient($objattr['INNER-X'], $objattr['INNER-Y'], $obiw, $obih, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true, true);
6310 $gradmask = '/TGS'.count($this->gradients).' gs ';
6311 }
6312 }
6313 /*-- END BACKGROUNDS --*/
6314 /*-- IMAGES-WMF --*/
6315 if (isset($objattr['itype']) && $objattr['itype']=='wmf') {
6316 $outstring = sprintf('q '.$tr.$tr2.'%.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']); // mPDF 5.7.3 TRANSFORMS
6317 }
6318 else
6319 /*-- END IMAGES-WMF --*/
6320 if (isset($objattr['itype']) && $objattr['itype']=='svg') {
6321 $outstring = sprintf('q '.$tr.$tr2.'%.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']); // mPDF 5.7.3 TRANSFORMS
6322 }
6323 else {
6324 $outstring = sprintf("q ".$tr.$tr2."%.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'] ); // mPDF 5.7.3 TRANSFORMS
6325 }
6326 $this->_out($outstring);
6327 // LINK
6328 if (isset($objattr['link'])) $this->Link($objattr['INNER-X'],$objattr['INNER-Y'],$objattr['INNER-WIDTH'],$objattr['INNER-HEIGHT'],$objattr['link']);
6329 if (isset($objattr['opacity'])) { $this->SetAlpha(1); }
6330
6331 // mPDF 5.7.3 TRANSFORMS
6332 // Transform also affects image borders
6333 if ($tr2) { $this->_out('q '.$tr2.' '); }
6334 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); }
6335 if ($tr2) { $this->_out('Q'); }
6336
6337 if(isset($objattr['visibility']) && $objattr['visibility']!='visible' && $objattr['visibility']) {
6338 $this->SetVisibility('visible');
6339 }
6340 if (isset($objattr['z-index']) && $objattr['z-index'] > 0 && $this->current_layer==0) {
6341 $this->EndLayer();
6342 }
6343 // mPDF 5.7.3 TRANSFORMS
6344 if (isset($objattr['transform'])) {
6345 $this->_out("\n".'% ETR'); // End Transform
6346 }
6347 }
6348
6349 /*-- BARCODES --*/
6350 // BARCODE
6351 if ($objattr['type'] == 'barcode') {
6352 $bgcol = $this->ConvertColor(255);
6353 if (isset($objattr['bgcolor']) && $objattr['bgcolor']) {
6354 $bgcol = $objattr['bgcolor'];
6355 }
6356 $col = $this->ConvertColor(0);
6357 if (isset($objattr['color']) && $objattr['color']) {
6358 $col = $objattr['color'];
6359 }
6360 $this->SetFColor($bgcol);
6361 $this->Rect($objattr['BORDER-X'], $objattr['BORDER-Y'], $objattr['BORDER-WIDTH'], $objattr['BORDER-HEIGHT'], 'F');
6362 $this->SetFColor($this->ConvertColor(255));
6363 if (isset($objattr['BORDER-WIDTH'])) { $this->PaintImgBorder($objattr,$is_table); }
6364 if ($objattr['btype'] == 'EAN13' || $objattr['btype'] == 'ISBN' || $objattr['btype'] == 'ISSN' || $objattr['btype'] == 'UPCA' || $objattr['btype'] == 'UPCE' || $objattr['btype'] == 'EAN8') {
6365 $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'], (isset($objattr['bsupp_code']) ? $objattr['bsupp_code'] : ''), $k);
6366 }
6367 // QR-code
6368 else if ($objattr['btype']=='QR') {
6369 if (!class_exists('QRcode', false)) {
6370 include(_MPDF_PATH.'qrcode/qrcode.class.php');
6371 }
6372 $this->qrcode = new QRcode($objattr['code'], $objattr['errorlevel']);
6373 $this->qrcode->displayFPDF($this, $objattr['INNER-X'], $objattr['INNER-Y'], $objattr['bsize']*25, array(255,255,255), array(0,0,0));
6374 }
6375 else {
6376 $this->WriteBarcode2($objattr['code'], $objattr['INNER-X'], $objattr['INNER-Y'], $objattr['bsize'], $objattr['bheight'], $bgcol, $col, $objattr['btype'], $objattr['pr_ratio'], $k);
6377 }
6378 }
6379 /*-- END BARCODES --*/
6380
6381 // TEXT CIRCLE
6382 if ($objattr['type'] == 'textcircle') {
6383 $bgcol = '';
6384 if (isset($objattr['bgcolor']) && $objattr['bgcolor']) {
6385 $bgcol = $objattr['bgcolor'];
6386 }
6387 $col = $this->ConvertColor(0);
6388 if (isset($objattr['color']) && $objattr['color']) {
6389 $col = $objattr['color'];
6390 }
6391 $this->SetTColor($col);
6392 $this->SetFColor($bgcol);
6393 if ($bgcol) $this->Rect($objattr['BORDER-X'], $objattr['BORDER-Y'], $objattr['BORDER-WIDTH'], $objattr['BORDER-HEIGHT'], 'F');
6394 $this->SetFColor($this->ConvertColor(255));
6395 if (isset($objattr['BORDER-WIDTH'])) { $this->PaintImgBorder($objattr,$is_table); }
6396 if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
6397 if (empty($this->directw)) { $this->directw = new directw($this); }
6398 if (isset($objattr['top-text'])) {
6399 $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'], (isset($objattr['divider']) ? $objattr['divider'] : ''));
6400 }
6401 if (isset($objattr['bottom-text'])) {
6402 $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'], (isset($objattr['divider']) ? $objattr['divider'] : ''));
6403 }
6404 }
6405
6406 $this->ResetSpacing();
6407
6408 // LIST MARKERS (Text or bullets) // mPDF 6 Lists
6409 if ($objattr['type'] == 'listmarker') {
6410 if (isset($objattr['fontfamily'])) { $this->SetFont($objattr['fontfamily'],$objattr['fontstyle'],$objattr['fontsizept'] ); }
6411 $col = $this->ConvertColor(0);
6412 if (isset($objattr['colorarray']) && ($objattr['colorarray'])) {
6413 $col = $objattr['colorarray'];
6414 }
6415
6416 if (isset($objattr['bullet']) && $objattr['bullet']) { // Used for position "outside" only
6417 $type = $objattr['bullet'];
6418 $size = $objattr['size'];
6419
6420 if ($objattr['listmarkerposition'] == 'inside') {
6421 $adjx = $size/2;
6422 if ($objattr['dir'] == 'rtl') {
6423 $adjx += $objattr['offset'];
6424 }
6425 $this->x += $adjx;
6426 }
6427 else {
6428 $adjx = $objattr['offset'];
6429 $adjx += $size/2;
6430 if ($objattr['dir'] == 'rtl') {
6431 $this->x += $adjx;
6432 }
6433 else {
6434 $this->x -= $adjx;
6435 }
6436 }
6437
6438 $yadj = $objattr['lineBox']['glyphYorigin'];
6439 if (isset($this->CurrentFont['desc']['XHeight']) && $this->CurrentFont['desc']['XHeight']) { $xh=$this->CurrentFont['desc']['XHeight']; }
6440 else { $xh = 500; }
6441 $yadj -= ($this->FontSize * $xh/1000) * 0.625; // Vertical height of bullet (centre) from baseline= XHeight * 0.625
6442 $this->y += $yadj;
6443
6444 $this->_printListBullet($this->x, $this->y, $size, $type, $col);
6445 }
6446 else {
6447 $this->SetTColor($col);
6448 $w = $this->GetStringWidth($texto);
6449 // NB If change marker-offset, also need to alter in function _getListMarkerWidth
6450 $adjx = $this->ConvertSize($this->list_marker_offset,$this->FontSize);
6451 if ($objattr['dir'] == 'rtl') {
6452 $align = 'L';
6453 $this->x += $adjx;
6454 }
6455 else {
6456 // Use these lines to set as marker-offset, right-aligned - default
6457 $align = 'R';
6458 $this->x -= $adjx;
6459 $this->x -= $w;
6460 }
6461 $this->Cell($w,$this->FontSize,$texto,0,0,$align,0,'',0,0,0, 'T', 0, false, false, 0 ,$objattr['lineBox']);
6462 $this->SetTColor($this->ConvertColor(0));
6463 }
6464 }
6465
6466 // DOT-TAB
6467 if ($objattr['type'] == 'dottab') {
6468 if (isset($objattr['fontfamily'])) { $this->SetFont($objattr['fontfamily'],'',$objattr['fontsize'] ); }
6469 $sp = $this->GetStringWidth(' ');
6470 $nb=floor(($w-2*$sp)/$this->GetStringWidth('.'));
6471 if ($nb>0) { $dots=' '.str_repeat('.',$nb).' '; }
6472 else { $dots=' '; }
6473 $col = $this->ConvertColor(0);
6474 if (isset($objattr['colorarray']) && ($objattr['colorarray'])) {
6475 $col = $objattr['colorarray'];
6476 }
6477 $this->SetTColor($col);
6478 $save_dh = $this->divheight;
6479 $save_sbd = $this->spanborddet;
6480 $save_textvar = $this->textvar; // mPDF 5.7.1
6481 $this->spanborddet = '';
6482 $this->divheight = 0;
6483 $this->textvar = 0x00; // mPDF 5.7.1
6484
6485 $this->Cell($w,$h,$dots,0,0,'C',0,'',0,0,0, 'T', 0, false, false, 0 ,$objattr['lineBox']); // mPDF 6 DOTTAB
6486 $this->spanborddet = $save_sbd;
6487 $this->textvar = $save_textvar; // mPDF 5.7.1
6488 $this->divheight = $save_dh;
6489 $this->SetTColor($this->ConvertColor(0));
6490 }
6491
6492 /*-- FORMS --*/
6493 // TEXT/PASSWORD INPUT
6494 if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'TEXT' || $objattr['subtype'] == 'PASSWORD')) {
6495 $this->mpdfform->print_ob_text($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
6496 }
6497
6498 // TEXTAREA
6499 if ($objattr['type'] == 'textarea') {
6500 $this->mpdfform->print_ob_textarea($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
6501 }
6502
6503 // SELECT
6504 if ($objattr['type'] == 'select') {
6505 $this->mpdfform->print_ob_select($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
6506 }
6507
6508
6509 // INPUT/BUTTON as IMAGE
6510 if ($objattr['type'] == 'input' && $objattr['subtype'] == 'IMAGE') {
6511 $this->mpdfform->print_ob_imageinput($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
6512 }
6513
6514 // BUTTON
6515 if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'SUBMIT' || $objattr['subtype'] == 'RESET' || $objattr['subtype'] == 'BUTTON')) {
6516 $this->mpdfform->print_ob_button($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
6517 }
6518
6519 // CHECKBOX
6520 if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'CHECKBOX')) {
6521 $this->mpdfform->print_ob_checkbox($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir,$x,$y);
6522 }
6523 // RADIO
6524 if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'RADIO')) {
6525 $this->mpdfform->print_ob_radio($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir,$x,$y);
6526 }
6527 /*-- END FORMS --*/
6528 }
6529 $this->SetFont($save_currentfontfamily,$save_currentfontstyle,$save_currentfontsize);
6530 $this->y = $save_y;
6531 $this->x = $save_x;
6532 unset($content);
6533 }
6534
6535 function _printListBullet($x, $y, $size, $type, $color) {
6536 // x and y are the centre of the bullet; size is the width and/or height in mm
6537 $fcol = $this->SetTColor($color,true);
6538 $lcol = strtoupper($fcol); // change 0 0 0 rg to 0 0 0 RG
6539 $this->_out( sprintf('q %s %s',$lcol, $fcol) );
6540 $this->_out( '0 j 0 J [] 0 d' );
6541 if ($type=='square') {
6542 $size *= 0.85; // Smaller to appear the same size as circle/disc
6543 $this->_out( sprintf('%.3F %.3F %.3F %.3F re f',($x-$size/2)*_MPDFK,($this->h-$y+$size/2)*_MPDFK,($size)*_MPDFK,(-$size)*_MPDFK) );
6544 }
6545 else if ($type=='disc') {
6546 $this->Circle($x, $y, $size/2, 'F'); // Fill
6547 }
6548 else if ($type=='circle') {
6549 $lw = $size/12; // Line width
6550 $this->_out( sprintf('%.3F w ',$lw*_MPDFK) );
6551 $this->Circle($x, $y, $size/2 - $lw/2, 'S'); // Stroke
6552 }
6553 $this->_out( 'Q' );
6554 }
6555
6556 // mPDF 6
6557 // Get previous character and move pointers
6558 function _moveToPrevChar(&$contentctr, &$charctr, $content) {
6559 $lastchar = false;
6560 $charctr--;
6561 while ($charctr<0) { // go back to previous $content[]
6562 $contentctr--;
6563 if ($contentctr<0) { return false; }
6564 if ($this->usingCoreFont) { $charctr = strlen( $content[$contentctr] )-1; }
6565 else { $charctr = mb_strlen( $content[$contentctr], $this->mb_enc )-1; }
6566 }
6567 if ($this->usingCoreFont) { $lastchar = $content[$contentctr][$charctr]; }
6568 else { $lastchar = mb_substr($content[$contentctr],$charctr,1,$this->mb_enc ); }
6569 return $lastchar;
6570 }
6571 // Get previous character
6572 function _getPrevChar($contentctr, $charctr, $content) {
6573 $lastchar = false;
6574 $charctr--;
6575 while ($charctr<0) { // go back to previous $content[]
6576 $contentctr--;
6577 if ($contentctr<0) { return false; }
6578 if ($this->usingCoreFont) { $charctr = strlen( $content[$contentctr] )-1; }
6579 else { $charctr = mb_strlen( $content[$contentctr], $this->mb_enc )-1; }
6580 }
6581 if ($this->usingCoreFont) {$lastchar = $content[$contentctr][$charctr]; }
6582 else { $lastchar = mb_substr($content[$contentctr],$charctr,1,$this->mb_enc ); }
6583 return $lastchar;
6584 }
6585
6586
6587
6588 function WriteFlowingBlock( $s, $sOTLdata) { // mPDF 5.7.1
6589 $currentx = $this->x;
6590 $is_table = $this->flowingBlockAttr[ 'is_table' ];
6591 $table_draft = $this->flowingBlockAttr[ 'table_draft' ];
6592 // width of all the content so far in points
6593 $contentWidth =& $this->flowingBlockAttr[ 'contentWidth' ];
6594 // cell width in points
6595 $maxWidth =& $this->flowingBlockAttr[ 'width' ];
6596 $lineCount =& $this->flowingBlockAttr[ 'lineCount' ];
6597 // line height in user units
6598 $stackHeight =& $this->flowingBlockAttr[ 'height' ];
6599 $align =& $this->flowingBlockAttr[ 'align' ];
6600 $content =& $this->flowingBlockAttr[ 'content' ];
6601 $contentB =& $this->flowingBlockAttr[ 'contentB' ];
6602 $font =& $this->flowingBlockAttr[ 'font' ];
6603 $valign =& $this->flowingBlockAttr[ 'valign' ];
6604 $blockstate = $this->flowingBlockAttr[ 'blockstate' ];
6605 $cOTLdata =& $this->flowingBlockAttr[ 'cOTLdata' ]; // mPDF 5.7.1
6606
6607 $newblock = $this->flowingBlockAttr[ 'newblock' ];
6608 $blockdir = $this->flowingBlockAttr['blockdir'];
6609
6610 // *********** BLOCK BACKGROUND COLOR ***************** //
6611 if ($this->blk[$this->blklvl]['bgcolor'] && !$is_table) {
6612 $fill = 0;
6613 }
6614 else {
6615 $this->SetFColor($this->ConvertColor(255));
6616 $fill = 0;
6617 }
6618 $font[] = $this->saveFont();
6619 $content[] = '';
6620 $contentB[] = '';
6621 $cOTLdata[] = $sOTLdata; // mPDF 5.7.1
6622 $currContent =& $content[ count( $content ) - 1 ];
6623
6624 $CJKoverflow = false;
6625 $Oikomi = false; // mPDF 6
6626 $hanger = '';
6627
6628 // COLS
6629 $oldcolumn = $this->CurrCol;
6630 if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
6631
6632 /*-- TABLES --*/
6633 if ($is_table) {
6634 $ipaddingL = 0;
6635 $ipaddingR = 0;
6636 $paddingL = 0;
6637 $paddingR = 0;
6638 $cpaddingadjustL = 0;
6639 $cpaddingadjustR = 0;
6640 // Added mPDF 3.0
6641 $fpaddingR = 0;
6642 $fpaddingL = 0;
6643 }
6644 else {
6645 /*-- END TABLES --*/
6646 $ipaddingL = $this->blk[$this->blklvl]['padding_left'];
6647 $ipaddingR = $this->blk[$this->blklvl]['padding_right'];
6648 $paddingL = ($ipaddingL * _MPDFK);
6649 $paddingR = ($ipaddingR * _MPDFK);
6650 $this->cMarginL = $this->blk[$this->blklvl]['border_left']['w'];
6651 $cpaddingadjustL = -$this->cMarginL;
6652 $this->cMarginR = $this->blk[$this->blklvl]['border_right']['w'];
6653 $cpaddingadjustR = -$this->cMarginR;
6654 // Added mPDF 3.0 Float DIV
6655 $fpaddingR = 0;
6656 $fpaddingL = 0;
6657 /*-- CSS-FLOAT --*/
6658 if (count($this->floatDivs)) {
6659 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
6660 if ($r_exists) { $fpaddingR = $r_width; }
6661 if ($l_exists) { $fpaddingL = $l_width; }
6662 }
6663 /*-- END CSS-FLOAT --*/
6664
6665 $usey = $this->y + 0.002;
6666 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
6667 $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
6668 }
6669 /*-- CSS-IMAGE-FLOAT --*/
6670 // If float exists at this level
6671 if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
6672 if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
6673 /*-- END CSS-IMAGE-FLOAT --*/
6674 } // *TABLES*
6675
6676 //OBJECTS - IMAGES & FORM Elements (NB has already skipped line/page if required - in printbuffer)
6677 if (substr($s,0,3) == "\xbb\xa4\xac") { //identifier has been identified!
6678 $objattr = $this->_getObjAttr($s);
6679 $h_corr = 0;
6680 if ($is_table) { // *TABLES*
6681 $maximumW = ($maxWidth/_MPDFK) - ($this->cellPaddingL + $this->cMarginL + $this->cellPaddingR + $this->cMarginR); // *TABLES*
6682 } // *TABLES*
6683 else { // *TABLES*
6684 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']; }
6685 $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 );
6686 } // *TABLES*
6687 $objattr = $this->inlineObject($objattr['type'],$this->lMargin + $fpaddingL + ($contentWidth/_MPDFK),($this->y + $h_corr), $objattr, $this->lMargin,($contentWidth/_MPDFK),$maximumW,$stackHeight,true,$is_table);
6688
6689 // SET LINEHEIGHT for this line ================ RESET AT END
6690 $stackHeight = MAX($stackHeight,$objattr['OUTER-HEIGHT']);
6691 $this->objectbuffer[count($content)-1] = $objattr;
6692 // if (isset($objattr['vertical-align'])) { $valign = $objattr['vertical-align']; }
6693 // else { $valign = ''; }
6694 // LIST MARKERS // mPDF 6 Lists
6695 if ($objattr['type'] == 'image' && isset($objattr['listmarker']) && $objattr['listmarker'] && $objattr['listmarkerposition'] == 'outside') {
6696 // do nothing
6697 }
6698 else {
6699 $contentWidth += ($objattr['OUTER-WIDTH'] * _MPDFK);
6700 }
6701 return;
6702 }
6703
6704 $lbw = $rbw = 0; // Border widths
6705 if (!empty($this->spanborddet)) {
6706 if (isset($this->spanborddet['L'])) $lbw = $this->spanborddet['L']['w'];
6707 if (isset($this->spanborddet['R'])) $rbw = $this->spanborddet['R']['w'];
6708 }
6709
6710 if ($this->usingCoreFont) {
6711 $clen = strlen( $s );
6712 }
6713 else {
6714 $clen = mb_strlen( $s, $this->mb_enc );
6715 }
6716
6717 // for every character in the string
6718 for ( $i = 0; $i < $clen; $i++ ) {
6719
6720 // extract the current character
6721 // get the width of the character in points
6722 if ($this->usingCoreFont) {
6723 $c = $s[$i];
6724 // Soft Hyphens chr(173)
6725 $cw = ($this->GetCharWidthCore($c) * _MPDFK);
6726 if (($this->textvar & FC_KERNING) && $i > 0) { // mPDF 5.7.1
6727 if (isset($this->CurrentFont['kerninfo'][$s[($i-1)]][$c])) {
6728 $cw += ($this->CurrentFont['kerninfo'][$s[($i-1)]][$c] * $this->FontSizePt / 1000 );
6729 }
6730 }
6731 }
6732 else {
6733 $c = mb_substr($s,$i,1,$this->mb_enc );
6734 $cw = ($this->GetCharWidthNonCore($c, false) * _MPDFK);
6735 // mPDF 5.7.1
6736 // Use OTL GPOS
6737 if (isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0xFF)) {
6738 // ...WriteFlowingBlock...
6739 // Only add XAdvanceL (not sure at present whether RTL or LTR writing direction)
6740 // At this point, XAdvanceL and XAdvanceR will balance
6741 if (isset($sOTLdata['GPOSinfo'][$i]['XAdvanceL'])) {
6742 $cw += $sOTLdata['GPOSinfo'][$i]['XAdvanceL']* (1000/$this->CurrentFont['unitsPerEm']) * ($this->FontSize/ 1000) * _MPDFK;
6743 }
6744 }
6745 if (($this->textvar & FC_KERNING) && $i > 0) { // mPDF 5.7.1
6746 $lastc = mb_substr($s,($i-1),1,$this->mb_enc );
6747 $ulastc = $this->UTF8StringToArray($lastc, false);
6748 $uc = $this->UTF8StringToArray($c, false);
6749 if (isset($this->CurrentFont['kerninfo'][$ulastc[0]][$uc[0]])) {
6750 $cw += ($this->CurrentFont['kerninfo'][$ulastc[0]][$uc[0]] * $this->FontSizePt / 1000 );
6751 }
6752 }
6753 }
6754
6755 if ($i==0) {
6756 $cw += $lbw*_MPDFK;
6757 $contentB[(count($contentB)-1)] .= 'L';
6758 }
6759 if ($i==($clen-1)) {
6760 $cw += $rbw*_MPDFK;
6761 $contentB[(count($contentB)-1)] .= 'R';
6762 }
6763 if ($c==' ') {
6764 $currContent .= $c;
6765 $contentWidth += $cw;
6766 continue;
6767 }
6768
6769 // Paragraph INDENT
6770 $WidthCorrection = 0;
6771 if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && ($align != 'C')) {
6772 $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->blk[$this->blklvl]['InlineProperties']['size'],false); // mPDF 5.7.4
6773 $WidthCorrection = ($ti*_MPDFK);
6774 }
6775 // OUTDENT
6776 foreach ($this->objectbuffer AS $k => $objattr) { // mPDF 6 DOTTAB
6777 if ($objattr['type'] == 'dottab') {
6778 $WidthCorrection -= ($objattr['outdent'] * _MPDFK);
6779 break;
6780 }
6781 }
6782
6783
6784 // Added mPDF 3.0 Float DIV
6785 $fpaddingR = 0;
6786 $fpaddingL = 0;
6787 /*-- CSS-FLOAT --*/
6788 if (count($this->floatDivs)) {
6789 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
6790 if ($r_exists) { $fpaddingR = $r_width; }
6791 if ($l_exists) { $fpaddingL = $l_width; }
6792 }
6793 /*-- END CSS-FLOAT --*/
6794
6795 $usey = $this->y + 0.002;
6796 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
6797 $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
6798 }
6799
6800 /*-- CSS-IMAGE-FLOAT --*/
6801 // If float exists at this level
6802 if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
6803 if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
6804 /*-- END CSS-IMAGE-FLOAT --*/
6805
6806
6807 // try adding another char
6808 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
6809 // it won't fit, output what we already have
6810 $lineCount++;
6811
6812 // contains any content that didn't make it into this print
6813 $savedContent = '';
6814 $savedContentB = '';
6815 $savedOTLdata = array(); // mPDF 5.7.1
6816 $savedFont = array();
6817 $savedObj = array();
6818 $savedPreOTLdata = array(); // mPDF 5.7.1
6819 $savedPreContent = array();
6820 $savedPreContentB = array();
6821 $savedPreFont = array();
6822
6823 // mPDF 6
6824 // New line-breaking algorithm
6825 /////////////////////
6826 // LINE BREAKING
6827 /////////////////////
6828 $breakfound = false;
6829 $contentctr = count($content)-1;
6830 if ($this->usingCoreFont) { $charctr = strlen($currContent); }
6831 else { $charctr = mb_strlen($currContent,$this->mb_enc ); }
6832 $checkchar = $c;
6833 $prevchar = $this->_getPrevChar($contentctr, $charctr, $content);
6834
6835 /*-- CJK-FONTS --*/
6836 /////////////////////
6837 // 1) CJK Overflowing a) punctuation or b) Oikomi
6838 /////////////////////
6839 // Next character ($c) is suitable to add as overhanging or squeezed punctuation, or Oikomi
6840 if ($CJKoverflow || $Oikomi) { // If flag already set
6841 $CJKoverflow = false;
6842 $Oikomi = false;
6843 $breakfound = true;
6844 }
6845 if (!$this->usingCoreFont && !$breakfound && $this->checkCJK) {
6846 // Get next/following character (in this chunk)
6847 $followingchar = '';
6848 if ($i<($clen-1)) {
6849 if ($this->usingCoreFont) { $followingchar = $s[$i+1]; }
6850 else { $followingchar = mb_substr($s,$i+1,1,$this->mb_enc ); }
6851 }
6852 /////////////////////
6853 // 1a) Overflow punctuation
6854 /////////////////////
6855 if (preg_match("/[".$this->pregCJKchars."]/u",$prevchar) && preg_match("/[".$this->CJKoverflow."]/u", $checkchar) && $this->allowCJKorphans) {
6856 // add character onto this line
6857 $currContent .= $c;
6858 $contentWidth += $cw;
6859 $CJKoverflow = true; // Set flag
6860 continue;
6861 }
6862 /////////////////////
6863 // 1b) Try squeezing another character(s) onto this line = Oikomi, if character cannot end line
6864 // or next character cannot start line (and not splitting CJK numerals)
6865 /////////////////////
6866 // NB otherwise it move lastchar(s) to next line to keep $c company = Oidashi, which is done below in standard way
6867 else if (preg_match("/[".$this->pregCJKchars."]/u",$checkchar) && $this->allowCJKorphans &&
6868 (preg_match("/[".$this->CJKleading."]/u", $followingchar) || preg_match("/[".$this->CJKfollowing."]/u", $checkchar)) &&
6869 !preg_match("/[".$this->CJKleading."]/u", $checkchar) && !preg_match("/[".$this->CJKfollowing."]/u", $followingchar) &&
6870 !(preg_match("/[0-9\x{ff10}-\x{ff19}]/u", $followingchar) && preg_match("/[0-9\x{ff10}-\x{ff19}]/u", $checkchar))) {
6871 // add character onto this line
6872 $currContent .= $c;
6873 $contentWidth += $cw;
6874 $Oikomi = true; // Set flag
6875 continue;
6876 }
6877 }
6878 /*-- END CJK-FONTS --*/
6879 /*-- HYPHENATION --*/
6880 /////////////////////
6881 // AUTOMATIC HYPHENATION
6882 // 2) Automatic hyphen in current word (does not cross tags)
6883 /////////////////////
6884 if (isset($this->textparam['hyphens']) && $this->textparam['hyphens'] == 1 ) {
6885 $currWord = '';
6886 // Look back and ahead to get current word
6887 for($ac = $charctr-1; $ac>=0; $ac--) {
6888 if ($this->usingCoreFont) { $addc = substr($currContent,$ac,1); }
6889 else { $addc = mb_substr($currContent,$ac,1,$this->mb_enc ); }
6890 if ($addc == ' ') { break; }
6891 $currWord = $addc.$currWord;
6892 }
6893 $start = $ac+1;
6894 for($ac = $i; $ac<($clen-1); $ac++) {
6895 if ($this->usingCoreFont) { $addc = substr($s,$ac,1); }
6896 else { $addc = mb_substr($s,$ac,1,$this->mb_enc ); }
6897 if ($addc == ' ') { break; }
6898 $currWord .= $addc;
6899 }
6900 $ptr = $this->hyphenateWord($currWord, $charctr-$start);
6901 if ($ptr>-1) {
6902 $breakfound = array($contentctr, $start+$ptr, $contentctr, $start+$ptr, 'hyphen');
6903 }
6904 }
6905 /*-- END HYPHENATION --*/
6906
6907 // Search backwards to find first line-break opportunity
6908 while ($breakfound==false && $prevchar !== false) {
6909 $cutcontentctr = $contentctr;
6910 $cutcharctr = $charctr;
6911 $prevchar = $this->_moveToPrevChar($contentctr, $charctr, $content);
6912 /////////////////////
6913 // 3) Break at SPACE
6914 /////////////////////
6915 if ($prevchar == ' ') {
6916 $breakfound = array($contentctr, $charctr, $cutcontentctr, $cutcharctr, 'discard');
6917 }
6918 /////////////////////
6919 // 4) Break at U+200B in current word (Khmer, Lao & Thai Invisible word boundary, and Tibetan)
6920 /////////////////////
6921 else if ($prevchar == "\xe2\x80\x8b") { // U+200B Zero-width Word Break
6922 $breakfound = array($contentctr, $charctr, $cutcontentctr, $cutcharctr, 'discard');
6923 }
6924 /////////////////////
6925 // 5) Break at Hard HYPHEN '-' or U+2010
6926 /////////////////////
6927 else if (isset($this->textparam['hyphens']) && $this->textparam['hyphens'] != 2 && ($prevchar == '-' || $prevchar == "\xe2\x80\x90")) {
6928 // Don't break a URL
6929 // Look back to get first part of current word
6930 $checkw = '';
6931 for($ac = $charctr-1; $ac>=0; $ac--) {
6932 if ($this->usingCoreFont) { $addc = substr($currContent,$ac,1); }
6933 else { $addc = mb_substr($currContent,$ac,1,$this->mb_enc ); }
6934 if ($addc == ' ') { break; }
6935 $checkw = $addc.$checkw;
6936 }
6937 // Don't break if HyphenMinus AND (a URL or before a numeral or before a >)
6938 if ((!preg_match('/(http:|ftp:|https:|www\.)/',$checkw) && $checkchar!='>' && !preg_match('/[0-9]/',$checkchar)) || $prevchar == "\xe2\x80\x90") {
6939 $breakfound = array($cutcontentctr, $cutcharctr, $cutcontentctr, $cutcharctr, 'cut');
6940 }
6941 }
6942 /////////////////////
6943 // 6) Break at Soft HYPHEN (replace with hard hyphen)
6944 /////////////////////
6945 else if (isset($this->textparam['hyphens']) && $this->textparam['hyphens'] != 2 && !$this->usingCoreFont && $prevchar == "\xc2\xad") {
6946 $breakfound = array($cutcontentctr, $cutcharctr, $cutcontentctr, $cutcharctr, 'cut');
6947 $content[$contentctr] = mb_substr($content[$contentctr],0,$charctr,$this->mb_enc) . '-' . mb_substr($content[$contentctr],$charctr+1,mb_strlen($content[$contentctr]),$this->mb_enc);
6948 if (!empty($cOTLdata[$contentctr])) {
6949 $cOTLdata[$contentctr]['char_data'][$charctr] = array('bidi_class'=>9, 'uni'=>45);
6950 $cOTLdata[$contentctr]['group'][$charctr] = 'C';
6951 }
6952 }
6953 else if (isset($this->textparam['hyphens']) && $this->textparam['hyphens'] != 2 && $this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats' && $prevchar == chr(173)) {
6954 $breakfound = array($cutcontentctr, $cutcharctr, $cutcontentctr, $cutcharctr, 'cut');
6955 $content[$contentctr] = substr($content[$contentctr],0,$charctr) . '-' . substr($content[$contentctr],$charctr+1);
6956 }
6957 /*-- CJK-FONTS --*/
6958 /////////////////////
6959 // 7) Break at CJK characters (unless forbidden characters to end or start line)
6960 // CJK Avoiding line break in the middle of numerals
6961 /////////////////////
6962 else if (!$this->usingCoreFont && $this->checkCJK && preg_match("/[".$this->pregCJKchars."]/u",$checkchar) &&
6963 !preg_match("/[".$this->CJKfollowing."]/u", $checkchar) && !preg_match("/[".$this->CJKleading."]/u", $prevchar) &&
6964 !(preg_match("/[0-9\x{ff10}-\x{ff19}]/u", $prevchar) && preg_match("/[0-9\x{ff10}-\x{ff19}]/u", $checkchar))) {
6965 $breakfound = array($cutcontentctr, $cutcharctr, $cutcontentctr, $cutcharctr, 'cut');
6966 }
6967 /*-- END CJK-FONTS --*/
6968 /////////////////////
6969 // 8) Break at OBJECT (Break before all objects here - selected objects are moved forward to next line below e.g. dottab)
6970 /////////////////////
6971 if (isset($this->objectbuffer[$contentctr])) {
6972 $breakfound = array($cutcontentctr, $cutcharctr, $cutcontentctr, $cutcharctr, 'cut');
6973 }
6974
6975
6976 $checkchar = $prevchar;
6977 }
6978
6979 // If a line-break opportunity found:
6980 if (is_array($breakfound)) {
6981 $contentctr = $breakfound[0];
6982 $charctr = $breakfound[1];
6983 $cutcontentctr = $breakfound[2];
6984 $cutcharctr = $breakfound[3];
6985 $type = $breakfound[4];
6986 // Cache chunks which are already processed, but now need to be passed on to the new line
6987 for ($ix=count($content)-1;$ix>$cutcontentctr;$ix--) {
6988 // save and crop off any subsequent chunks
6989 /*-- OTL --*/
6990 if (!empty($sOTLdata)) {
6991 $tmpOTL = array_pop($cOTLdata);
6992 $savedPreOTLdata[] = $tmpOTL;
6993 }
6994 /*-- END OTL --*/
6995 $savedPreContent[] = array_pop($content);
6996 $savedPreContentB[] = array_pop($contentB);
6997 $savedPreFont[] = array_pop($font);
6998 }
6999
7000 // Next cache the part which will start the next line
7001 if ($this->usingCoreFont) {
7002 $savedPreContent[] = substr($content[$cutcontentctr],$cutcharctr);
7003 }
7004 else {
7005 $savedPreContent[] = mb_substr($content[$cutcontentctr],$cutcharctr,mb_strlen($content[$cutcontentctr]),$this->mb_enc);
7006 }
7007 $savedPreContentB[] = preg_replace('/L/','',$contentB[$cutcontentctr]);
7008 $savedPreFont[] = $font[$cutcontentctr];
7009 /*-- OTL --*/
7010 if (!empty($sOTLdata)) {
7011 $savedPreOTLdata[] = $this->otl->splitOTLdata($cOTLdata[$cutcontentctr], $cutcharctr, $cutcharctr);
7012 }
7013 /*-- END OTL --*/
7014
7015
7016 // Finally adjust the Current content which ends this line
7017 if ($cutcharctr == 0 && $type=='discard') {
7018 array_pop($content);
7019 array_pop($contentB);
7020 array_pop($font);
7021 array_pop($cOTLdata);
7022 }
7023
7024 $currContent =& $content[ count( $content ) - 1 ];
7025 if ($this->usingCoreFont) {
7026 $currContent = substr($currContent,0,$charctr);
7027 }
7028 else {
7029 $currContent = mb_substr($currContent,0,$charctr,$this->mb_enc);
7030 }
7031
7032 if (!empty($sOTLdata)) {
7033 $savedPreOTLdata[] = $this->otl->splitOTLdata($cOTLdata[(count($cOTLdata)-1)], mb_strlen($currContent,$this->mb_enc));
7034 }
7035
7036 if (strpos($contentB[(count($contentB)-1)],'R')!==false) { // ???
7037 $contentB[count($content)-1] = preg_replace('/R/','',$contentB[count($content)-1]); // ???
7038 }
7039
7040 if ($type=='hyphen') {
7041 $currContent .= '-';
7042 if (!empty($cOTLdata[(count($cOTLdata)-1)])) {
7043 $cOTLdata[(count($cOTLdata)-1)]['char_data'][] = array('bidi_class'=>9, 'uni'=>45);
7044 $cOTLdata[(count($cOTLdata)-1)]['group'] .= 'C';
7045 }
7046 }
7047
7048 $savedContent = '';
7049 $savedContentB = '';
7050 $savedFont = array();
7051 $savedOTLdata = array();
7052
7053
7054 }
7055 // If no line-break opportunity found - split at current position
7056 // or - Next character ($c) is suitable to add as overhanging or squeezed punctuation, or Oikomi, as set above by:
7057 // 1) CJK Overflowing a) punctuation or b) Oikomi
7058 // in which case $breakfound==1 and NOT array
7059
7060 if (!is_array($breakfound)) {
7061 $savedFont = $this->saveFont();
7062 if (!empty($sOTLdata)) {
7063 $savedOTLdata = $this->otl->splitOTLdata($cOTLdata[(count($cOTLdata)-1)], mb_strlen($currContent,$this->mb_enc));
7064 }
7065 }
7066
7067 if ($content[ count($content)-1 ] == '' && !isset($this->objectbuffer[ count($content)-1 ])) {
7068 array_pop($content);
7069 array_pop($contentB);
7070 array_pop($font);
7071 array_pop($cOTLdata);
7072 $currContent =& $content[ count($content)-1 ];
7073 }
7074
7075 // Right Trim current content - including CJK space, and for OTLdata
7076 // incl. CJK - strip CJK space at end of line &#x3000; = \xe3\x80\x80 = CJK space
7077 $currContent = rtrim( $currContent );
7078 if ($this->checkCJK) { $currContent = preg_replace("/\xe3\x80\x80$/",'',$currContent) ; } // *CJK-FONTS*
7079 /*-- OTL --*/
7080 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
7081 $this->otl->trimOTLdata($cOTLdata[count($cOTLdata)-1], false, true); // NB also does U+3000
7082 }
7083 /*-- END OTL --*/
7084
7085
7086 // Selected OBJECTS are moved forward to next line, unless they come before a space or U+200B (type='discard')
7087 if (isset($this->objectbuffer[(count($content)-1)]) && (!isset($type) || $type != 'discard')) {
7088 $objtype = $this->objectbuffer[(count($content)-1)]['type'];
7089 if ($objtype=='dottab' || $objtype=='bookmark' || $objtype=='indexentry' || $objtype=='toc' || $objtype=='annot') {
7090 $savedObj = array_pop( $this->objectbuffer );
7091 }
7092 }
7093
7094
7095 // Decimal alignment (cancel if wraps to > 1 line)
7096 if ($is_table && substr($align,0,1)=='D' ) { $align=substr($align,2,1); }
7097
7098 $lineBox = array();
7099
7100 $this->_setInlineBlockHeights($lineBox, $stackHeight, $content, $font, $is_table);
7101
7102 // update $contentWidth since it has changed with cropping
7103 $contentWidth = 0;
7104
7105 $inclCursive=false;
7106 foreach ( $content as $k => $chunk ) {
7107 if (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]) {
7108 // LIST MARKERS
7109 if ($this->objectbuffer[$k]['type'] == 'image' && isset($this->objectbuffer[$k]['listmarker']) && $this->objectbuffer[$k]['listmarker']) {
7110 if ($this->objectbuffer[$k]['listmarkerposition'] != 'outside') {
7111 $contentWidth += $this->objectbuffer[$k]['OUTER-WIDTH'] * _MPDFK;
7112 }
7113 }
7114 else {
7115 $contentWidth += $this->objectbuffer[$k]['OUTER-WIDTH'] * _MPDFK;
7116 }
7117 }
7118 else if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
7119 $this->restoreFont( $font[ $k ], false);
7120 if ($this->checkCJK && $k == count($content)-1 && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $this->CJKforceend) {
7121 // force-end overhang
7122 $hanger = mb_substr($chunk,mb_strlen($chunk,$this->mb_enc)-1,1,$this->mb_enc );
7123 // Probably ought to do something with char_data and GPOS in cOTLdata...
7124 $content[$k] = $chunk = mb_substr($chunk,0,mb_strlen($chunk,$this->mb_enc)-1,$this->mb_enc );
7125 }
7126
7127 // Soft Hyphens chr(173) + Replace NBSP with SPACE + Set inclcursive if includes CURSIVE TEXT
7128 if (!$this->usingCoreFont) {
7129 /*-- OTL --*/
7130 if ((isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) || !empty($sOTLdata)) {
7131 $this->otl->removeChar($chunk, $cOTLdata[$k], "\xc2\xad");
7132 $this->otl->replaceSpace($chunk, $cOTLdata[$k]); // NBSP -> space
7133 if (preg_match("/([".$this->pregCURSchars."])/u", $chunk)) { $inclCursive = true; }
7134 $content[$k] = $chunk;
7135 }
7136 /*-- END OTL --*/
7137 else { // *OTL*
7138 $content[$k] = $chunk = str_replace("\xc2\xad",'',$chunk );
7139 $content[$k] = $chunk = str_replace(chr(194).chr(160),chr(32),$chunk );
7140 } // *OTL*
7141 }
7142 else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
7143 $content[$k] = $chunk = str_replace(chr(173),'',$chunk );
7144 $content[$k] = $chunk = str_replace(chr(160),chr(32),$chunk );
7145 }
7146
7147 $contentWidth += $this->GetStringWidth( $chunk, true, (isset($cOTLdata[$k]) ? $cOTLdata[$k] : false), $this->textvar ) * _MPDFK; // mPDF 5.7.1
7148 if (!empty($this->spanborddet)) {
7149 if (isset($this->spanborddet['L']['w']) && strpos($contentB[$k],'L')!==false) $contentWidth += $this->spanborddet['L']['w'] * _MPDFK;
7150 if (isset($this->spanborddet['R']['w']) && strpos($contentB[$k],'R')!==false) $contentWidth += $this->spanborddet['R']['w'] * _MPDFK;
7151 }
7152 }
7153
7154 }
7155
7156 $lastfontreqstyle = (isset($font[count($font)-1]['ReqFontStyle']) ? $font[count($font)-1]['ReqFontStyle'] : '');
7157 $lastfontstyle = (isset($font[count($font)-1]['style']) ? $font[count($font)-1]['style'] : '');
7158 if ($blockdir == 'ltr' && strpos($lastfontreqstyle,"I") !== false && strpos($lastfontstyle,"I") === false) { // Artificial italic
7159 $lastitalic = $this->FontSize*0.15*_MPDFK;
7160 }
7161 else { $lastitalic = 0; }
7162
7163
7164
7165
7166 // NOW FORMAT THE LINE TO OUTPUT
7167 if (!$table_draft) {
7168 // DIRECTIONALITY RTL
7169 $chunkorder = range(0, count($content)-1); // mPDF 5.7
7170 /*-- OTL --*/
7171 // mPDF 6
7172 if ($blockdir == 'rtl' || $this->biDirectional) {
7173 $this->otl->_bidiReorder($chunkorder, $content, $cOTLdata, $blockdir);
7174 // From this point on, $content and $cOTLdata may contain more elements (and re-ordered) compared to
7175 // $this->objectbuffer and $font ($chunkorder contains the mapping)
7176 }
7177
7178 /*-- END OTL --*/
7179 // Remove any XAdvance from OTL data at end of line
7180 foreach($chunkorder AS $aord=>$k) {
7181 if (count($cOTLdata)) {
7182 $this->restoreFont( $font[ $k ], false);
7183 // ...WriteFlowingBlock...
7184 if ($aord == count($chunkorder)-1 && isset($cOTLdata[$aord]['group'])) { // Last chunk on line
7185 $nGPOS = strlen($cOTLdata[$aord]['group'])-1; // Last character
7186 if (isset($cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceL']) || isset($cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceR'])) {
7187 if (isset($cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceL'])) {
7188 $w = $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceL'] * 1000/$this->CurrentFont['unitsPerEm'];
7189 }
7190 else {
7191 $w = $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceR'] * 1000/$this->CurrentFont['unitsPerEm'];
7192 }
7193 $w *= ($this->FontSize/ 1000);
7194 $contentWidth -= $w * _MPDFK;
7195 $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceL'] = 0;
7196 $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceR'] = 0;
7197 }
7198
7199 // If last character has an XPlacement set, adjust width calculation, and add to XAdvance to account for it
7200 if (isset($cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XPlacement'])) {
7201 $w = -$cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XPlacement'] * 1000/$this->CurrentFont['unitsPerEm'];
7202 $w *= ($this->FontSize/ 1000);
7203 $contentWidth -= $w * _MPDFK;
7204 $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceL'] = $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XPlacement'];
7205 $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XAdvanceR'] = $cOTLdata[$aord]['GPOSinfo'][$nGPOS]['XPlacement'];
7206 }
7207
7208 }
7209 }
7210 }
7211
7212 // JUSTIFICATION J
7213 $jcharspacing = 0;
7214 $jws = 0;
7215 $nb_carac = 0;
7216 $nb_spaces = 0;
7217 $jkashida = 0;
7218 // if it's justified, we need to find the char/word spacing (or if hanger $this->CJKforceend)
7219 if ( ($align == 'J' && !$CJKoverflow) || (($contentWidth + $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
7220
7221 // JUSTIFY J (Use character spacing)
7222 // WORD SPACING
7223 foreach($chunkorder AS $aord=>$k) { // mPDF 5.7
7224 $chunk = $content[$aord];
7225 if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
7226 $nb_carac += mb_strlen( $chunk, $this->mb_enc ) ;
7227 $nb_spaces += mb_substr_count( $chunk,' ', $this->mb_enc ) ;
7228 // Use GPOS OTL
7229 if (isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0xFF)) {
7230 if (isset($cOTLdata[$aord]['group']) && $cOTLdata[$aord]['group']) {
7231 $nb_carac -= substr_count($cOTLdata[$aord]['group'], 'M');
7232 }
7233 }
7234 }
7235 else { $nb_carac ++ ; } // mPDF 6 allow spacing for inline object
7236 }
7237 // GetJSpacing adds kashida spacing to GPOSinfo if appropriate for Font
7238 list($jcharspacing,$jws,$jkashida) = $this->GetJspacing($nb_carac,$nb_spaces,($maxWidth-$lastitalic-$contentWidth-$WidthCorrection-(($this->cMarginL+$this->cMarginR)*_MPDFK)-($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) )),$inclCursive,$cOTLdata);
7239 }
7240
7241 // WORD SPACING
7242 $empty = $maxWidth - $lastitalic - $WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
7243
7244 $empty -= ($jcharspacing * ($nb_carac-1)); // mPDF 6 nb_carac MINUS 1
7245 $empty -= ($jws * $nb_spaces);
7246 $empty -= ($jkashida);
7247 $empty /= _MPDFK;
7248
7249 $b = ''; //do not use borders
7250 // Get PAGEBREAK TO TEST for height including the top border/padding
7251 $check_h = max($this->divheight,$stackHeight);
7252 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($this->blklvl > 0) && ($lineCount == 1) && (!$is_table)) {
7253 $check_h += ($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['border_top']['w']);
7254 }
7255
7256 if ($this->ColActive && $check_h > ($this->PageBreakTrigger - $this->y0)) {
7257 $this->SetCol($this->NbCol-1);
7258 }
7259
7260 // PAGEBREAK
7261 // 'If' below used in order to fix "first-line of other page with justify on" bug
7262 if(!$is_table && ($this->y+$check_h) > $this->PageBreakTrigger and !$this->InFooter and $this->AcceptPageBreak()) {
7263 $bak_x=$this->x;//Current X position
7264
7265 // WORD SPACING
7266 $ws=$this->ws;//Word Spacing
7267 $charspacing=$this->charspacing;//Character Spacing
7268 $this->ResetSpacing();
7269
7270 $this->AddPage($this->CurOrientation);
7271
7272 $this->x = $bak_x;
7273 // Added to correct for OddEven Margins
7274 $currentx += $this->MarginCorrection;
7275 $this->x += $this->MarginCorrection;
7276
7277 // WORD SPACING
7278 $this->SetSpacing($charspacing,$ws);
7279 }
7280
7281 if ($this->kwt && !$is_table) { // mPDF 5.7+
7282 $this->printkwtbuffer();
7283 $this->kwt = false;
7284 }
7285
7286
7287 /*-- COLUMNS --*/
7288 // COLS
7289 // COLUMN CHANGE
7290 if ($this->CurrCol != $oldcolumn) {
7291 $currentx += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
7292 $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
7293 $oldcolumn = $this->CurrCol;
7294 }
7295
7296 if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
7297 /*-- END COLUMNS --*/
7298
7299 // TOP MARGIN
7300 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($this->blk[$this->blklvl]['margin_top']) && ($lineCount == 1) && (!$is_table)) {
7301 $this->DivLn($this->blk[$this->blklvl]['margin_top'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
7302 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
7303 }
7304
7305
7306 // Update y0 for top of block (used to paint border)
7307 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 1) && (!$is_table)) {
7308 $this->blk[$this->blklvl]['y0'] = $this->y;
7309 $this->blk[$this->blklvl]['startpage'] = $this->page;
7310 if ($this->blk[$this->blklvl]['float']) { $this->blk[$this->blklvl]['float_start_y'] = $this->y; }
7311 }
7312
7313 // TOP PADDING and BORDER spacing/fill
7314 if (($newblock) && ($blockstate==1 || $blockstate==3) && (($this->blk[$this->blklvl]['padding_top']) || ($this->blk[$this->blklvl]['border_top'])) && ($lineCount == 1) && (!$is_table)) {
7315 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
7316 $this->DivLn($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'],-3,true,false,1);
7317 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
7318 }
7319
7320 $arraysize = count($chunkorder);
7321
7322 $margins = ($this->cMarginL+$this->cMarginR) + ($ipaddingL+$ipaddingR + $fpaddingR + $fpaddingR );
7323
7324 // PAINT BACKGROUND FOR THIS LINE
7325 if (!$is_table) { $this->DivLn($stackHeight,$this->blklvl,false); } // false -> don't advance y
7326
7327 $this->x = $currentx + $this->cMarginL + $ipaddingL + $fpaddingL ;
7328 if ($align == 'R') { $this->x += $empty; }
7329 else if ($align == 'C') { $this->x += ($empty / 2); }
7330
7331 // Paragraph INDENT
7332 if (isset($this->blk[$this->blklvl]['text_indent']) && ($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 1) && (!$is_table) && ($blockdir !='rtl') && ($align !='C')) {
7333 $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->blk[$this->blklvl]['InlineProperties']['size'],false); // mPDF 5.7.4
7334 $this->x += $ti;
7335 }
7336
7337 // BIDI magic_reverse moved upwards from here
7338
7339 foreach($chunkorder AS $aord=>$k) { // mPDF 5.7
7340 $chunk = $content[$aord];
7341
7342 if (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]) {
7343 $xadj = $this->x - $this->objectbuffer[$k]['OUTER-X'] ;
7344 $this->objectbuffer[$k]['OUTER-X'] += $xadj;
7345 $this->objectbuffer[$k]['BORDER-X'] += $xadj;
7346 $this->objectbuffer[$k]['INNER-X'] += $xadj;
7347
7348 if ($this->objectbuffer[$k]['type'] == 'listmarker') {
7349 $this->objectbuffer[$k]['lineBox'] = $lineBox[-1]; // Block element details for glyph-origin
7350 }
7351 $yadj = $this->y - $this->objectbuffer[$k]['OUTER-Y'];
7352 if ($this->objectbuffer[$k]['type'] == 'dottab') { // mPDF 6 DOTTAB
7353 $this->objectbuffer[$k]['lineBox'] = $lineBox[$k]; // element details for glyph-origin
7354 }
7355 if ($this->objectbuffer[$k]['type'] != 'dottab') { // mPDF 6 DOTTAB
7356 $yadj += $lineBox[$k]['top'];
7357 }
7358 $this->objectbuffer[$k]['OUTER-Y'] += $yadj;
7359 $this->objectbuffer[$k]['BORDER-Y'] += $yadj;
7360 $this->objectbuffer[$k]['INNER-Y'] += $yadj;
7361 }
7362
7363 $this->restoreFont( $font[ $k ] ); // mPDF 5.7
7364
7365 $this->SetSpacing(($this->fixedlSpacing*_MPDFK)+$jcharspacing,($this->fixedlSpacing+$this->minwSpacing)*_MPDFK+$jws);
7366 // Now unset these values so they don't influence GetStringwidth below or in fn. Cell
7367 $this->fixedlSpacing = false;
7368 $this->minwSpacing = 0;
7369
7370 $save_vis = $this->visibility;
7371 if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->textparam['visibility'] != $this->visibility) {
7372 $this->SetVisibility($this->textparam['visibility']);
7373 }
7374 // *********** SPAN BACKGROUND COLOR ***************** //
7375 if ($this->spanbgcolor) {
7376 $cor = $this->spanbgcolorarray;
7377 $this->SetFColor($cor);
7378 $save_fill = $fill; $spanfill = 1; $fill = 1;
7379 }
7380 if (!empty($this->spanborddet)) {
7381 if (strpos($contentB[$k],'L')!==false) $this->x += (isset($this->spanborddet['L']['w']) ? $this->spanborddet['L']['w'] : 0);
7382 if (strpos($contentB[$k],'L')===false) $this->spanborddet['L']['s'] = $this->spanborddet['L']['w'] = 0;
7383 if (strpos($contentB[$k],'R')===false) $this->spanborddet['R']['s'] = $this->spanborddet['R']['w'] = 0;
7384 }
7385
7386 // WORD SPACING
7387 // StringWidth this time includes any kashida spacing
7388 $stringWidth = $this->GetStringWidth($chunk, true, (isset($cOTLdata[$aord]) ? $cOTLdata[$aord] : false), $this->textvar, true);
7389
7390 $nch = mb_strlen($chunk,$this->mb_enc );
7391 // Use GPOS OTL
7392 if (isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0xFF)) {
7393 if (isset($cOTLdata[$aord]['group']) && $cOTLdata[$aord]['group']) {
7394 $nch -= substr_count($cOTLdata[$aord]['group'], 'M');
7395 }
7396 }
7397 $stringWidth += ( $this->charspacing * $nch / _MPDFK );
7398
7399 $stringWidth += ( $this->ws * mb_substr_count($chunk,' ',$this->mb_enc ) / _MPDFK );
7400
7401 if (isset($this->objectbuffer[$k])) {
7402 // LIST MARKERS // mPDF 6 Lists
7403 if ($this->objectbuffer[$k]['type'] == 'image' && isset($this->objectbuffer[$k]['listmarker']) && $this->objectbuffer[$k]['listmarker'] && $this->objectbuffer[$k]['listmarkerposition'] == 'outside') {
7404 $stringWidth = 0;
7405 }
7406 else {
7407 $stringWidth = $this->objectbuffer[$k]['OUTER-WIDTH'];
7408 }
7409 }
7410
7411 if ($stringWidth==0) { $stringWidth = 0.000001; }
7412
7413 if ($aord == $arraysize-1) {
7414 $stringWidth -= ( $this->charspacing / _MPDFK );
7415 if ($this->checkCJK && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $hanger && $this->CJKforceend) {
7416 // force-end overhang
7417 $this->Cell( $stringWidth, $stackHeight, $chunk, '', 0, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, true, (isset($cOTLdata[$aord]) ? $cOTLdata[$aord] : false), $this->textvar, (isset($lineBox[$k]) ? $lineBox[$k] : false));
7418 $this->Cell( $this->GetStringWidth($hanger), $stackHeight, $hanger, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, true, (isset($cOTLdata[$aord]) ? $cOTLdata[$aord] : false), $this->textvar, (isset($lineBox[$k]) ? $lineBox[$k] : false));
7419 }
7420 else {
7421 $this->Cell( $stringWidth, $stackHeight, $chunk, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, true, (isset($cOTLdata[$aord]) ? $cOTLdata[$aord] : false), $this->textvar, (isset($lineBox[$k]) ? $lineBox[$k] : false)); //mono-style line or last part (skips line)
7422 }
7423
7424 }
7425 else $this->Cell( $stringWidth, $stackHeight, $chunk, '', 0, '', $fill, $this->HREF, 0, 0,0,'M', $fill, true, (isset($cOTLdata[$aord]) ? $cOTLdata[$aord] : false), $this->textvar, (isset($lineBox[$k]) ? $lineBox[$k] : false));//first or middle part
7426
7427 if (!empty($this->spanborddet)) {
7428 if (strpos($contentB[$k],'R')!==false && $aord != $arraysize-1) $this->x += $this->spanborddet['R']['w'];
7429 }
7430 // *********** SPAN BACKGROUND COLOR OFF - RESET BLOCK BGCOLOR ***************** //
7431 if (isset($spanfill) && $spanfill) {
7432 $fill = $save_fill; $spanfill = 0;
7433 if ($fill) { $this->SetFColor($bcor); }
7434 }
7435 if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->visibility != $save_vis) {
7436 $this->SetVisibility($save_vis);
7437 }
7438
7439 }
7440 }
7441 else if ($table_draft) { $this->y += $stackHeight; }
7442
7443 if (!$is_table) {
7444 $this->maxPosR = max($this->maxPosR , ($this->w - $this->rMargin - $this->blk[$this->blklvl]['outer_right_margin']));
7445 $this->maxPosL = min($this->maxPosL , ($this->lMargin + $this->blk[$this->blklvl]['outer_left_margin']));
7446 }
7447
7448 // move on to the next line, reset variables, tack on saved content and current char
7449
7450 if (!$table_draft) $this->printobjectbuffer($is_table, $blockdir);
7451 $this->objectbuffer = array();
7452
7453
7454 /*-- CSS-IMAGE-FLOAT --*/
7455 // Update values if set to skipline
7456 if ($this->floatmargins) { $this->_advanceFloatMargins(); }
7457 /*-- END CSS-IMAGE-FLOAT --*/
7458
7459 // Reset lineheight
7460 $stackHeight = $this->divheight;
7461 $valign = 'M';
7462
7463 $font = array();
7464 $content = array();
7465 $contentB = array();
7466 $cOTLdata = array(); // mPDF 5.7.1
7467 $contentWidth = 0;
7468 if (!empty($savedObj)) {
7469 $this->objectbuffer[] = $savedObj;
7470 $font[] = $savedFont;
7471 $content[] = '';
7472 $contentB[] = '';
7473 $cOTLdata[] = array(); // mPDF 5.7.1
7474 $contentWidth += $savedObj['OUTER-WIDTH'] * _MPDFK;
7475 }
7476 if (count($savedPreContent) > 0) {
7477 for($ix=count($savedPreContent)-1;$ix>=0;$ix--) {
7478 $font[] = $savedPreFont[$ix];
7479 $content[] = $savedPreContent[$ix];
7480 $contentB[] = $savedPreContentB[$ix];
7481 if (!empty($sOTLdata)) {
7482 $cOTLdata[] = $savedPreOTLdata[$ix];
7483 }
7484 $this->restoreFont( $savedPreFont[$ix] );
7485 $lbw = $rbw = 0; // Border widths
7486 if (!empty($this->spanborddet)) {
7487 $lbw = (isset($this->spanborddet['L']['w']) ? $this->spanborddet['L']['w'] : 0);
7488 $rbw = (isset($this->spanborddet['R']['w']) ? $this->spanborddet['R']['w'] : 0);
7489 }
7490 if ($ix>0) {
7491 $contentWidth += $this->GetStringWidth( $savedPreContent[$ix], true, (isset($savedPreOTLdata[$ix]) ? $savedPreOTLdata[$ix] : false), $this->textvar ) * _MPDFK; // mPDF 5.7.1
7492 if (strpos($savedPreContentB[$ix],'L')!==false) $contentWidth += $lbw;
7493 if (strpos($savedPreContentB[$ix],'R')!==false) $contentWidth += $rbw;
7494 }
7495 }
7496 $savedPreContent = array();
7497 $savedPreContentB = array();
7498 $savedPreOTLdata = array(); // mPDF 5.7.1
7499 $savedPreFont = array();
7500 $content[ (count($content)-1) ] .= $c;
7501 }
7502 else {
7503 $font[] = $savedFont;
7504 $content[] = $savedContent . $c;
7505 $contentB[] = $savedContentB ;
7506 $cOTLdata[] = $savedOTLdata; // mPDF 5.7.1
7507 }
7508
7509 $currContent =& $content[ (count($content)-1) ];
7510 $this->restoreFont( $font[ (count($font)-1) ]); // mPDF 6.0
7511
7512 /*-- CJK-FONTS --*/
7513 // CJK - strip CJK space at start of line
7514 // &#x3000; = \xe3\x80\x80 = CJK space
7515 if ($this->checkCJK && $currContent == "\xe3\x80\x80") {
7516 $currContent = '';
7517 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
7518 $this->otl->trimOTLdata($cOTLdata[count($cOTLdata)-1], true, false); // left trim U+3000
7519 }
7520 }
7521 /*-- END CJK-FONTS --*/
7522
7523 $lbw = $rbw = 0; // Border widths
7524 if (!empty($this->spanborddet)) {
7525 $lbw = (isset($this->spanborddet['L']['w']) ? $this->spanborddet['L']['w'] : 0);
7526 $rbw = (isset($this->spanborddet['R']['w']) ? $this->spanborddet['R']['w'] : 0);
7527 }
7528
7529 $contentWidth += $this->GetStringWidth( $currContent, false, (isset($cOTLdata[(count($cOTLdata)-1)]) ? $cOTLdata[(count($cOTLdata)-1)] : false), $this->textvar ) * _MPDFK; // mPDF 5.7.1
7530 if (strpos($savedContentB,'L')!==false) $contentWidth += $lbw;
7531 $CJKoverflow = false;
7532 $hanger = '';
7533 }
7534 // another character will fit, so add it on
7535 else {
7536 $contentWidth += $cw;
7537 $currContent .= $c;
7538 }
7539 }
7540
7541 unset($content);
7542 unset($contentB);
7543 }
7544 //----------------------END OF FLOWING BLOCK------------------------------------//
7545
7546
7547 /*-- CSS-IMAGE-FLOAT --*/
7548 // Update values if set to skipline
7549 function _advanceFloatMargins() {
7550 // Update floatmargins - L
7551 if (isset($this->floatmargins['L']) && $this->floatmargins['L']['skipline'] && $this->floatmargins['L']['y0'] != $this->y) {
7552 $yadj = $this->y - $this->floatmargins['L']['y0'];
7553 $this->floatmargins['L']['y0'] = $this->y;
7554 $this->floatmargins['L']['y1'] += $yadj;
7555
7556 // Update objattr in floatbuffer
7557 if ($this->floatbuffer[$this->floatmargins['L']['id']]['border_left']['w']) {
7558 $this->floatbuffer[$this->floatmargins['L']['id']]['BORDER-Y'] += $yadj;
7559 }
7560 $this->floatbuffer[$this->floatmargins['L']['id']]['INNER-Y'] += $yadj;
7561 $this->floatbuffer[$this->floatmargins['L']['id']]['OUTER-Y'] += $yadj;
7562
7563 // Unset values
7564 $this->floatbuffer[$this->floatmargins['L']['id']]['skipline'] = false;
7565 $this->floatmargins['L']['skipline'] = false;
7566 $this->floatmargins['L']['id'] = '';
7567 }
7568 // Update floatmargins - R
7569 if (isset($this->floatmargins['R']) && $this->floatmargins['R']['skipline'] && $this->floatmargins['R']['y0'] != $this->y) {
7570 $yadj = $this->y - $this->floatmargins['R']['y0'];
7571 $this->floatmargins['R']['y0'] = $this->y;
7572 $this->floatmargins['R']['y1'] += $yadj;
7573
7574 // Update objattr in floatbuffer
7575 if ($this->floatbuffer[$this->floatmargins['R']['id']]['border_left']['w']) {
7576 $this->floatbuffer[$this->floatmargins['R']['id']]['BORDER-Y'] += $yadj;
7577 }
7578 $this->floatbuffer[$this->floatmargins['R']['id']]['INNER-Y'] += $yadj;
7579 $this->floatbuffer[$this->floatmargins['R']['id']]['OUTER-Y'] += $yadj;
7580
7581 // Unset values
7582 $this->floatbuffer[$this->floatmargins['R']['id']]['skipline'] = false;
7583 $this->floatmargins['R']['skipline'] = false;
7584 $this->floatmargins['R']['id'] = '';
7585 }
7586 }
7587 /*-- END CSS-IMAGE-FLOAT --*/
7588
7589
7590
7591 /*-- END HTML-CSS --*/
7592
7593 function _SetTextRendering($mode) {
7594 if (!(($mode == 0) || ($mode == 1) || ($mode == 2)))
7595 $this->Error("Text rendering mode should be 0, 1 or 2 (value : $mode)");
7596 $tr = ($mode.' Tr');
7597 if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']))) { $this->_out($tr); }
7598 $this->pageoutput[$this->page]['TextRendering'] = $tr;
7599
7600 }
7601
7602 function SetTextOutline($params=array()) {
7603 if (isset($params['outline-s']) && $params['outline-s'])
7604 {
7605 $this->SetLineWidth($params['outline-WIDTH']);
7606 $this->SetDColor($params['outline-COLOR']);
7607 $tr = ('2 Tr');
7608 if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']))) { $this->_out($tr); }
7609 $this->pageoutput[$this->page]['TextRendering'] = $tr;
7610 }
7611 else //Now resets all values
7612 {
7613 $this->SetLineWidth(0.2);
7614 $this->SetDColor($this->ConvertColor(0));
7615 $this->_SetTextRendering(0);
7616 $tr = ('0 Tr');
7617 if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']))) { $this->_out($tr); }
7618 $this->pageoutput[$this->page]['TextRendering'] = $tr;
7619 }
7620 }
7621
7622 function Image($file,$x,$y,$w=0,$h=0,$type='',$link='',$paint=true, $constrain=true, $watermark=false, $shownoimg=true, $allowvector=true) {
7623 $orig_srcpath = $file;
7624 $this->GetFullPath($file);
7625
7626 $info=$this->_getImage($file, true, $allowvector, $orig_srcpath );
7627 if(!$info && $paint) {
7628 $info = $this->_getImage($this->noImageFile);
7629 if ($info) {
7630 $file = $this->noImageFile;
7631 $w = ($info['w'] * (25.4/$this->dpi)); // 14 x 16px
7632 $h = ($info['h'] * (25.4/$this->dpi)); // 14 x 16px
7633 }
7634 }
7635 if(!$info) return false;
7636 //Automatic width and height calculation if needed
7637 if($w==0 and $h==0) {
7638 /*-- IMAGES-WMF --*/
7639 if ($info['type']=='wmf') {
7640 // WMF units are twips (1/20pt)
7641 // divide by 20 to get points
7642 // divide by k to get user units
7643 $w = abs($info['w'])/(20*_MPDFK);
7644 $h = abs($info['h']) / (20*_MPDFK);
7645 }
7646 else
7647 /*-- END IMAGES-WMF --*/
7648 if ($info['type']=='svg') {
7649 // returned SVG units are pts
7650 // divide by k to get user units (mm)
7651 $w = abs($info['w'])/_MPDFK;
7652 $h = abs($info['h']) /_MPDFK;
7653 }
7654 else {
7655 //Put image at default image dpi
7656 $w=($info['w']/_MPDFK) * (72/$this->img_dpi);
7657 $h=($info['h']/_MPDFK) * (72/$this->img_dpi);
7658 }
7659 }
7660 if($w==0) $w=abs($h*$info['w']/$info['h']);
7661 if($h==0) $h=abs($w*$info['h']/$info['w']);
7662
7663 /*-- WATERMARK --*/
7664 if ($watermark) {
7665 $maxw = $this->w;
7666 $maxh = $this->h;
7667 // Size = D PF or array
7668 if (is_array($this->watermark_size)) {
7669 $w = $this->watermark_size[0];
7670 $h = $this->watermark_size[1];
7671 }
7672 else if (!is_string($this->watermark_size)) {
7673 $maxw -= $this->watermark_size*2;
7674 $maxh -= $this->watermark_size*2;
7675 $w = $maxw;
7676 $h=abs($w*$info['h']/$info['w']);
7677 if ($h > $maxh ) {
7678 $h = $maxh ; $w=abs($h*$info['w']/$info['h']);
7679 }
7680 }
7681 else if ($this->watermark_size == 'F') {
7682 if ($this->ColActive) { $maxw = $this->w - ($this->DeflMargin + $this->DefrMargin); }
7683 else { $maxw = $this->pgwidth; }
7684 $maxh = $this->h - ($this->tMargin + $this->bMargin);
7685 $w = $maxw;
7686 $h=abs($w*$info['h']/$info['w']);
7687 if ($h > $maxh ) {
7688 $h = $maxh ; $w=abs($h*$info['w']/$info['h']);
7689 }
7690 }
7691 else if ($this->watermark_size == 'P') { // Default P
7692 $w = $maxw;
7693 $h=abs($w*$info['h']/$info['w']);
7694 if ($h > $maxh ) {
7695 $h = $maxh ; $w=abs($h*$info['w']/$info['h']);
7696 }
7697 }
7698 // Automatically resize to maximum dimensions of page if too large
7699 if ($w > $maxw) {
7700 $w = $maxw;
7701 $h=abs($w*$info['h']/$info['w']);
7702 }
7703 if ($h > $maxh ) {
7704 $h = $maxh ;
7705 $w=abs($h*$info['w']/$info['h']);
7706 }
7707 // Position
7708 if (is_array($this->watermark_pos)) {
7709 $x = $this->watermark_pos[0];
7710 $y = $this->watermark_pos[1];
7711 }
7712 else if ($this->watermark_pos == 'F') { // centred on printable area
7713 if ($this->ColActive) { // *COLUMNS*
7714 if (($this->mirrorMargins) && (($this->page)%2==0)) { $xadj = $this->DeflMargin-$this->DefrMargin; } // *COLUMNS*
7715 else { $xadj = 0; } // *COLUMNS*
7716 $x = ($this->DeflMargin - $xadj + ($this->w - ($this->DeflMargin + $this->DefrMargin))/2) - ($w/2); // *COLUMNS*
7717 } // *COLUMNS*
7718 else { // *COLUMNS*
7719 $x = ($this->lMargin + ($this->pgwidth)/2) - ($w/2);
7720 } // *COLUMNS*
7721 $y = ($this->tMargin + ($this->h - ($this->tMargin + $this->bMargin))/2) - ($h/2);
7722 }
7723 else { // default P - centred on whole page
7724 $x = ($this->w/2) - ($w/2);
7725 $y = ($this->h/2) - ($h/2);
7726 }
7727 /*-- IMAGES-WMF --*/
7728 if ($info['type']=='wmf') {
7729 $sx = $w*_MPDFK / $info['w'];
7730 $sy = -$h*_MPDFK / $info['h'];
7731 $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']);
7732 }
7733 else
7734 /*-- END IMAGES-WMF --*/
7735 if ($info['type']=='svg') {
7736 $sx = $w*_MPDFK / $info['w'];
7737 $sy = -$h*_MPDFK / $info['h'];
7738 $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']);
7739 }
7740 else {
7741 $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']);
7742 }
7743
7744 if ($this->watermarkImgBehind) {
7745 $outstring = $this->watermarkImgAlpha . "\n" . $outstring . "\n" . $this->SetAlpha(1, 'Normal', true) . "\n";
7746 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.$this->uniqstr.')/', "\n".$outstring."\n".'\\1', $this->pages[$this->page]);
7747 }
7748 else { $this->_out($outstring); }
7749
7750 return 0;
7751 } // end of IF watermark
7752 /*-- END WATERMARK --*/
7753
7754 if ($constrain) {
7755 // Automatically resize to maximum dimensions of page if too large
7756 if (isset($this->blk[$this->blklvl]['inner_width']) && $this->blk[$this->blklvl]['inner_width']) { $maxw = $this->blk[$this->blklvl]['inner_width']; }
7757 else { $maxw = $this->pgwidth; }
7758 if ($w > $maxw) {
7759 $w = $maxw;
7760 $h=abs($w*$info['h']/$info['w']);
7761 }
7762 if ($h > $this->h - ($this->tMargin + $this->bMargin + 1)) { // see below - +10 to avoid drawing too close to border of page
7763 $h = $this->h - ($this->tMargin + $this->bMargin + 1) ;
7764 if ($this->fullImageHeight) { $h = $this->fullImageHeight; }
7765 $w=abs($h*$info['w']/$info['h']);
7766 }
7767
7768
7769 //Avoid drawing out of the paper(exceeding width limits).
7770 //if ( ($x + $w) > $this->fw ) {
7771 if ( ($x + $w) > $this->w ) {
7772 $x = $this->lMargin;
7773 $y += 5;
7774 }
7775
7776 $changedpage = false;
7777 $oldcolumn = $this->CurrCol;
7778 //Avoid drawing out of the page.
7779 if($y+$h>$this->PageBreakTrigger and !$this->InFooter and $this->AcceptPageBreak()) {
7780 $this->AddPage($this->CurOrientation);
7781 // Added to correct for OddEven Margins
7782 $x=$x +$this->MarginCorrection;
7783 $y = $this->tMargin; // mPDF 5.7.3
7784 $changedpage = true;
7785 }
7786 /*-- COLUMNS --*/
7787 // COLS
7788 // COLUMN CHANGE
7789 if ($this->CurrCol != $oldcolumn) {
7790 $y = $this->y0;
7791 $x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
7792 $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
7793 }
7794 /*-- END COLUMNS --*/
7795 } // end of IF constrain
7796
7797 /*-- IMAGES-WMF --*/
7798 if ($info['type']=='wmf') {
7799 $sx = $w*_MPDFK / $info['w'];
7800 $sy = -$h*_MPDFK / $info['h'];
7801 $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']);
7802 }
7803 else
7804 /*-- END IMAGES-WMF --*/
7805 if ($info['type']=='svg') {
7806 $sx = $w*_MPDFK / $info['w'];
7807 $sy = -$h*_MPDFK / $info['h'];
7808 $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']);
7809 }
7810 else {
7811 $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']);
7812 }
7813
7814 if($paint) {
7815 $this->_out($outstring);
7816 if($link) $this->Link($x,$y,$w,$h,$link);
7817
7818 // Avoid writing text on top of the image. // THIS WAS OUTSIDE THE if ($paint) bit!!!!!!!!!!!!!!!!
7819 $this->y = $y + $h;
7820 }
7821
7822 //Return width-height array
7823 $sizesarray['WIDTH'] = $w;
7824 $sizesarray['HEIGHT'] = $h;
7825 $sizesarray['X'] = $x; //Position before painting image
7826 $sizesarray['Y'] = $y; //Position before painting image
7827 $sizesarray['OUTPUT'] = $outstring;
7828
7829 $sizesarray['IMAGE_ID'] = $info['i'];
7830 $sizesarray['itype'] = $info['type'];
7831 $sizesarray['set-dpi'] = (isset($info['set-dpi']) ? $info['set-dpi'] : 0);
7832 return $sizesarray;
7833 }
7834
7835
7836
7837 //=============================================================
7838 //=============================================================
7839 //=============================================================
7840 //=============================================================
7841 //=============================================================
7842 /*-- HTML-CSS --*/
7843
7844 function _getObjAttr($t) {
7845 $c = explode("\xbb\xa4\xac",$t,2);
7846 $c = explode(",",$c[1],2);
7847 foreach($c as $v) {
7848 $v = explode("=",$v,2);
7849 $sp[$v[0]] = $v[1];
7850 }
7851 return (unserialize($sp['objattr']));
7852 }
7853
7854
7855 function inlineObject($type,$x,$y,$objattr,$Lmargin,$widthUsed,$maxWidth,$lineHeight,$paint=false,$is_table=false)
7856 {
7857 if ($is_table) { $k = $this->shrin_k; } else { $k = 1; }
7858
7859 // NB $x is only used when paint=true
7860 // Lmargin not used
7861 $w = 0;
7862 if (isset($objattr['width'])) { $w = $objattr['width']/$k; }
7863 $h = 0;
7864 if (isset($objattr['height'])) { $h = abs($objattr['height']/$k); }
7865 $widthLeft = $maxWidth - $widthUsed;
7866 $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 10) ;
7867 if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
7868 // For Images
7869 if (isset($objattr['border_left'])) {
7870 $extraWidth = ($objattr['border_left']['w'] + $objattr['border_right']['w'] + $objattr['margin_left']+ $objattr['margin_right'])/$k;
7871 $extraHeight = ($objattr['border_top']['w'] + $objattr['border_bottom']['w'] + $objattr['margin_top']+ $objattr['margin_bottom'])/$k;
7872
7873 if ($type == 'image' || $type == 'barcode' || $type == 'textcircle') {
7874 $extraWidth += ($objattr['padding_left'] + $objattr['padding_right'])/$k;
7875 $extraHeight += ($objattr['padding_top'] + $objattr['padding_bottom'])/$k;
7876 }
7877 }
7878
7879 if (!isset($objattr['vertical-align'])) {
7880 if ($objattr['type'] == 'select') { $objattr['vertical-align'] = 'M'; }
7881 else { $objattr['vertical-align'] = 'BS'; }
7882 } // mPDF 6
7883
7884 if ($type == 'image' || (isset($objattr['subtype']) && $objattr['subtype'] == 'IMAGE')) {
7885 if (isset($objattr['itype']) && ($objattr['itype'] == 'wmf' || $objattr['itype'] == 'svg')) {
7886 $file = $objattr['file'];
7887 $info=$this->formobjects[$file];
7888 }
7889 else if (isset($objattr['file'])) {
7890 $file = $objattr['file'];
7891 $info=$this->images[$file];
7892 }
7893 }
7894 if ($type == 'annot' || $type == 'bookmark' || $type == 'indexentry' || $type == 'toc') {
7895 $w = 0.00001;
7896 $h = 0.00001;
7897 }
7898
7899 // TEST whether need to skipline
7900 if (!$paint) {
7901 if ($type == 'hr') { // always force new line
7902 if (($y + $h + $lineHeight > $this->PageBreakTrigger) && !$this->InFooter && !$is_table) { return array(-2, $w ,$h ); } // New page + new line
7903 else { return array(1, $w ,$h ); } // new line
7904 }
7905 else {
7906 // LIST MARKERS // mPDF 6 Lists
7907 $displayheight = $h; $displaywidth = $w;
7908 if ($objattr['type'] == 'image' && isset($objattr['listmarker']) && $objattr['listmarker']) {
7909 $displayheight = 0;
7910 if ($objattr['listmarkerposition'] == 'outside') { $displaywidth = 0; }
7911 }
7912
7913 if ($widthUsed > 0 && $displaywidth > $widthLeft && (!$is_table || $type != 'image')) { // New line needed
7914 // mPDF 6 Lists
7915 if (($y + $displayheight + $lineHeight > $this->PageBreakTrigger) && !$this->InFooter) { return array(-2,$w ,$h ); } // New page + new line
7916 return array(1,$w ,$h ); // new line
7917 }
7918 else if ($widthUsed > 0 && $displaywidth > $widthLeft && $is_table) { // New line needed in TABLE
7919 return array(1,$w ,$h ); // new line
7920 }
7921 // Will fit on line but NEW PAGE REQUIRED
7922 else if (($y + $displayheight > $this->PageBreakTrigger) && !$this->InFooter && !$is_table) { return array(-1,$w ,$h ); } // mPDF 6 Lists
7923 else { return array(0,$w ,$h ); }
7924 }
7925 }
7926
7927 if ($type == 'annot' || $type == 'bookmark' || $type == 'indexentry' || $type == 'toc') {
7928 $w = 0.00001;
7929 $h = 0.00001;
7930 $objattr['BORDER-WIDTH'] = 0;
7931 $objattr['BORDER-HEIGHT'] = 0;
7932 $objattr['BORDER-X'] = $x;
7933 $objattr['BORDER-Y'] = $y;
7934 $objattr['INNER-WIDTH'] = 0;
7935 $objattr['INNER-HEIGHT'] = 0;
7936 $objattr['INNER-X'] = $x;
7937 $objattr['INNER-Y'] = $y;
7938 }
7939
7940 if ($type == 'image') {
7941 // Automatically resize to width remaining
7942 if ($w > ($widthLeft + 0.0001) && !$is_table ) { // mPDF 5.7.4 0.0001 to allow for rounding errors when w==maxWidth
7943 $w = $widthLeft ;
7944 $h=abs($w*$info['h']/$info['w']);
7945 }
7946 $img_w = $w - $extraWidth ;
7947 $img_h = $h - $extraHeight ;
7948
7949 $objattr['BORDER-WIDTH'] = $img_w + $objattr['padding_left']/$k + $objattr['padding_right']/$k + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
7950 $objattr['BORDER-HEIGHT'] = $img_h + $objattr['padding_top']/$k + $objattr['padding_bottom']/$k + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
7951 $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
7952 $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
7953 $objattr['INNER-WIDTH'] = $img_w;
7954 $objattr['INNER-HEIGHT'] = $img_h;
7955 $objattr['INNER-X'] = $x + $objattr['padding_left']/$k + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
7956 $objattr['INNER-Y'] = $y + $objattr['padding_top']/$k + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
7957 $objattr['ID'] = $info['i'];
7958 }
7959
7960 if ($type == 'input' && $objattr['subtype'] == 'IMAGE') {
7961 $img_w = $w - $extraWidth ;
7962 $img_h = $h - $extraHeight ;
7963 $objattr['BORDER-WIDTH'] = $img_w + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
7964 $objattr['BORDER-HEIGHT'] = $img_h + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
7965 $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
7966 $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
7967 $objattr['INNER-WIDTH'] = $img_w;
7968 $objattr['INNER-HEIGHT'] = $img_h;
7969 $objattr['INNER-X'] = $x + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
7970 $objattr['INNER-Y'] = $y + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
7971 $objattr['ID'] = $info['i'];
7972 }
7973
7974 if ($type == 'barcode' || $type == 'textcircle') {
7975 $b_w = $w - $extraWidth ;
7976 $b_h = $h - $extraHeight ;
7977 $objattr['BORDER-WIDTH'] = $b_w + $objattr['padding_left']/$k + $objattr['padding_right']/$k + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
7978 $objattr['BORDER-HEIGHT'] = $b_h + $objattr['padding_top']/$k + $objattr['padding_bottom']/$k + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
7979 $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
7980 $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
7981 $objattr['INNER-X'] = $x + $objattr['padding_left']/$k + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
7982 $objattr['INNER-Y'] = $y + $objattr['padding_top']/$k + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
7983 $objattr['INNER-WIDTH'] = $b_w;
7984 $objattr['INNER-HEIGHT'] = $b_h;
7985 }
7986
7987
7988 if ($type == 'textarea') {
7989 // Automatically resize to width remaining
7990 if ($w > $widthLeft && !$is_table) {
7991 $w = $widthLeft ;
7992 }
7993 // This used to resize height to maximum remaining on page ? why. Causes problems when in table and causing a new column
7994 // if (($y + $h > $this->PageBreakTrigger) && !$this->InFooter) {
7995 // $h=$this->h - $y - $this->bMargin;
7996 // }
7997 }
7998
7999 if ($type == 'hr') {
8000 if ($is_table) {
8001 $objattr['INNER-WIDTH'] = $maxWidth * $objattr['W-PERCENT']/100;
8002 $objattr['width'] = $objattr['INNER-WIDTH'];
8003 $w = $maxWidth;
8004 }
8005 else {
8006 if ($w>$maxWidth) { $w = $maxWidth; }
8007 $objattr['INNER-WIDTH'] = $w;
8008 $w = $maxWidth;
8009 }
8010 }
8011
8012
8013
8014 if (($type == 'select') || ($type == 'input' && ($objattr['subtype'] == 'TEXT' || $objattr['subtype'] == 'PASSWORD'))) {
8015 // Automatically resize to width remaining
8016 if ($w > $widthLeft && !$is_table) {
8017 $w = $widthLeft;
8018 }
8019 }
8020
8021 if ($type == 'textarea' || $type == 'select' || $type == 'input') {
8022 if (isset($objattr['fontsize'])) $objattr['fontsize'] /= $k;
8023 if (isset($objattr['linewidth'])) $objattr['linewidth'] /= $k;
8024 }
8025
8026 if (!isset($objattr['BORDER-Y'])) { $objattr['BORDER-Y'] = 0; }
8027 if (!isset($objattr['BORDER-X'])) { $objattr['BORDER-X'] = 0; }
8028 if (!isset($objattr['INNER-Y'])) { $objattr['INNER-Y'] = 0; }
8029 if (!isset($objattr['INNER-X'])) { $objattr['INNER-X'] = 0; }
8030
8031 //Return width-height array
8032 $objattr['OUTER-WIDTH'] = $w;
8033 $objattr['OUTER-HEIGHT'] = $h;
8034 $objattr['OUTER-X'] = $x;
8035 $objattr['OUTER-Y'] = $y;
8036 return $objattr;
8037 }
8038
8039 /*-- END HTML-CSS --*/
8040
8041 //=============================================================
8042 //=============================================================
8043 //=============================================================
8044 //=============================================================
8045 //=============================================================
8046
8047 function SetLineJoin($mode=0)
8048 {
8049 $s=sprintf('%d j',$mode);
8050 if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineJoin']) && $this->pageoutput[$this->page]['LineJoin'] != $s) || !isset($this->pageoutput[$this->page]['LineJoin']))) { $this->_out($s); }
8051 $this->pageoutput[$this->page]['LineJoin'] = $s;
8052
8053 }
8054 function SetLineCap($mode=2) {
8055 $s=sprintf('%d J',$mode);
8056 if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineCap']) && $this->pageoutput[$this->page]['LineCap'] != $s) || !isset($this->pageoutput[$this->page]['LineCap']))) { $this->_out($s); }
8057 $this->pageoutput[$this->page]['LineCap'] = $s;
8058
8059 }
8060
8061 function SetDash($black=false,$white=false)
8062 {
8063 if($black and $white) $s=sprintf('[%.3F %.3F] 0 d',$black*_MPDFK,$white*_MPDFK);
8064 else $s='[] 0 d';
8065 if($this->page>0 && ((isset($this->pageoutput[$this->page]['Dash']) && $this->pageoutput[$this->page]['Dash'] != $s) || !isset($this->pageoutput[$this->page]['Dash']))) { $this->_out($s); }
8066 $this->pageoutput[$this->page]['Dash'] = $s;
8067
8068 }
8069
8070 function SetDisplayPreferences($preferences) {
8071 // String containing any or none of /HideMenubar/HideToolbar/HideWindowUI/DisplayDocTitle/CenterWindow/FitWindow
8072 $this->DisplayPreferences .= $preferences;
8073 }
8074
8075
8076 function Ln($h='',$collapsible=0) {
8077 // Added collapsible to allow collapsible top-margin on new page
8078 //Line feed; default value is last cell height
8079 $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
8080 if ($collapsible && ($this->y==$this->tMargin) && (!$this->ColActive)) { $h = 0; }
8081 if(is_string($h)) $this->y+=$this->lasth;
8082 else $this->y+=$h;
8083 }
8084
8085 /*-- HTML-CSS --*/
8086 function DivLn($h,$level=-3,$move_y=true,$collapsible=false,$state=0) {
8087 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
8088 // Used in Columns and keep-with-table i.e. "kwt"
8089 // writes background block by block so it can be repositioned
8090 // and also used in writingFlowingBlock at top and bottom of blocks to move y (not to draw/paint anything)
8091 // adds lines (y) where DIV bgcolors are filled in
8092 // this->x is returned as it was
8093 // allows .00001 as nominal height used for bookmarks/annotations etc.
8094 if ($collapsible && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->tMargin)) && (!$this->ColActive)) { return; }
8095
8096 // mPDF 6 Columns
8097 // if ($collapsible && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->y0)) && ($this->ColActive) && $this->CurrCol == 0) { return; } // *COLUMNS*
8098 if ($collapsible && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->y0)) && ($this->ColActive)) { return; } // *COLUMNS*
8099
8100 // Still use this method if columns or keep-with-table, as it allows repositioning later
8101 // otherwise, now uses PaintDivBB()
8102 if (!$this->ColActive && !$this->kwt) {
8103 if ($move_y && !$this->ColActive) { $this->y += $h; }
8104 return;
8105 }
8106
8107 if ($level == -3) { $level = $this->blklvl; }
8108 $firstblockfill = $this->GetFirstBlockFill();
8109 if ($firstblockfill && $this->blklvl > 0 && $this->blklvl >= $firstblockfill) {
8110 $last_x = 0;
8111 $last_w = 0;
8112 $last_fc = $this->FillColor;
8113 $bak_x = $this->x;
8114 $bak_h = $this->divheight;
8115 $this->divheight = 0; // Temporarily turn off divheight - as Cell() uses it to check for PageBreak
8116 for ($blvl=$firstblockfill;$blvl<=$level;$blvl++) {
8117 $this->x = $this->lMargin + $this->blk[$blvl]['outer_left_margin'];
8118 // mPDF 6
8119 if ($this->blk[$blvl]['bgcolor']) {
8120 $this->SetFColor($this->blk[$blvl]['bgcolorarray']);
8121 }
8122 if ($last_x != ($this->lMargin + $this->blk[$blvl]['outer_left_margin']) || ($last_w != $this->blk[$blvl]['width']) || $last_fc != $this->FillColor || (isset($this->blk[$blvl]['border_top']['s']) && $this->blk[$blvl]['border_top']['s']) || (isset($this->blk[$blvl]['border_bottom']['s']) && $this->blk[$blvl]['border_bottom']['s']) || (isset($this->blk[$blvl]['border_left']['s']) && $this->blk[$blvl]['border_left']['s']) || (isset($this->blk[$blvl]['border_right']['s']) && $this->blk[$blvl]['border_right']['s'])) {
8123 $x = $this->x;
8124 $this->Cell( ($this->blk[$blvl]['width']), $h, '', '', 0, '', 1);
8125 $this->x = $x;
8126 if (!$this->keep_block_together && !$this->writingHTMLheader && !$this->writingHTMLfooter) {
8127 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
8128 if ($blvl == $this->blklvl) { $this->PaintDivLnBorder($state,$blvl,$h); }
8129 else { $this->PaintDivLnBorder(0,$blvl,$h); }
8130 }
8131 }
8132 $last_x = $this->lMargin + $this->blk[$blvl]['outer_left_margin'];
8133 $last_w = $this->blk[$blvl]['width'];
8134 $last_fc = $this->FillColor;
8135 }
8136 // Reset current block fill
8137 if (isset($this->blk[$this->blklvl]['bgcolorarray'])) {
8138 $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
8139 $this->SetFColor($bcor);
8140 }
8141 $this->x = $bak_x;
8142 $this->divheight = $bak_h;
8143 }
8144 if ($move_y) { $this->y += $h; }
8145 }
8146 /*-- END HTML-CSS --*/
8147
8148
8149 function SetX($x)
8150 {
8151 //Set x position
8152 if($x >= 0) $this->x=$x;
8153 else $this->x = $this->w + $x;
8154 }
8155
8156 function SetY($y)
8157 {
8158 //Set y position and reset x
8159 $this->x=$this->lMargin;
8160 if($y>=0)
8161 $this->y=$y;
8162 else
8163 $this->y=$this->h+$y;
8164 }
8165
8166 function SetXY($x,$y)
8167 {
8168 //Set x and y positions
8169 $this->SetY($y);
8170 $this->SetX($x);
8171 }
8172
8173
8174 function Output($name='',$dest='')
8175 {
8176 //Output PDF to some destination
8177 if ($this->showStats) {
8178 echo '<div>Generated in '.sprintf('%.2F',(microtime(true) - $this->time0)).' seconds</div>';
8179 }
8180 //Finish document if necessary
8181 if ($this->progressBar) { $this->UpdateProgressBar(1,'100','Finished'); } // *PROGRESS-BAR*
8182 if($this->state < 3) $this->Close();
8183 if ($this->progressBar) { $this->UpdateProgressBar(2,'100','Finished'); } // *PROGRESS-BAR*
8184 // fn. error_get_last is only in PHP>=5.2
8185 if ($this->debug && function_exists('error_get_last') && error_get_last()) {
8186 $e = error_get_last();
8187 if (($e['type'] < 2048 && $e['type'] != 8) || (intval($e['type']) & intval(ini_get("error_reporting")))) {
8188 echo "<p>Error message detected - PDF file generation aborted.</p>";
8189 echo $e['message'].'<br />';
8190 echo 'File: '.$e['file'].'<br />';
8191 echo 'Line: '.$e['line'].'<br />';
8192 exit;
8193 }
8194 }
8195
8196
8197 if (($this->PDFA || $this->PDFX) && $this->encrypted) { $this->Error("PDFA1-b or PDFX/1-a does not permit encryption of documents."); }
8198 if (count($this->PDFAXwarnings) && (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto))) {
8199 if ($this->PDFA) {
8200 echo '<div>WARNING - This file could not be generated as it stands as a PDFA1-b compliant file.</div>';
8201 echo '<div>These issues can be automatically fixed by mPDF using <i>$mpdf-&gt;PDFAauto=true;</i></div>';
8202 echo '<div>Action that mPDF will take to automatically force PDFA1-b compliance are shown in brackets.</div>';
8203 }
8204 else {
8205 echo '<div>WARNING - This file could not be generated as it stands as a PDFX/1-a compliant file.</div>';
8206 echo '<div>These issues can be automatically fixed by mPDF using <i>$mpdf-&gt;PDFXauto=true;</i></div>';
8207 echo '<div>Action that mPDF will take to automatically force PDFX/1-a compliance are shown in brackets.</div>';
8208 }
8209 echo '<div>Warning(s) generated:</div><ul>';
8210 $this->PDFAXwarnings = array_unique($this->PDFAXwarnings);
8211 foreach($this->PDFAXwarnings AS $w) {
8212 echo '<li>'.$w.'</li>';
8213 }
8214 echo '</ul>';
8215 exit;
8216 }
8217
8218 if ($this->showStats) {
8219 echo '<div>Compiled in '.sprintf('%.2F',(microtime(true) - $this->time0)).' seconds (total)</div>';
8220 echo '<div>Peak Memory usage '.number_format((memory_get_peak_usage(true)/(1024*1024)),2).' MB</div>';
8221 echo '<div>PDF file size '.number_format((strlen($this->buffer)/1024)).' kB</div>';
8222 echo '<div>Number of fonts '.count($this->fonts).'</div>';
8223 exit;
8224 }
8225
8226
8227 if(is_bool($dest)) $dest=$dest ? 'D' : 'F';
8228 $dest=strtoupper($dest);
8229 if($dest=='') {
8230 if($name=='') {
8231 $name='mpdf.pdf';
8232 $dest='I';
8233 }
8234 else { $dest='F'; }
8235 }
8236
8237 /*-- PROGRESS-BAR --*/
8238 if ($this->progressBar && ($dest=='D' || $dest=='I')) {
8239 if($name=='') { $name='mpdf.pdf'; }
8240 $tempfile = '_tempPDF'.uniqid(rand(1,100000),true);
8241 //Save to local file
8242 $f=fopen(_MPDF_TEMP_PATH.$tempfile.'.pdf','wb');
8243 if(!$f) $this->Error('Unable to create temporary output file: '.$tempfile.'.pdf');
8244 fwrite($f,$this->buffer,strlen($this->buffer));
8245 fclose($f);
8246 $this->UpdateProgressBar(3,'','Finished');
8247
8248 echo '<script type="text/javascript">
8249
8250 var form = document.createElement("form");
8251 form.setAttribute("method", "post");
8252 form.setAttribute("action", "'._MPDF_URI.'includes/out.php");
8253
8254 var hiddenField = document.createElement("input");
8255 hiddenField.setAttribute("type", "hidden");
8256 hiddenField.setAttribute("name", "filename");
8257 hiddenField.setAttribute("value", "'.$tempfile.'");
8258 form.appendChild(hiddenField);
8259
8260 var hiddenField = document.createElement("input");
8261 hiddenField.setAttribute("type", "hidden");
8262 hiddenField.setAttribute("name", "dest");
8263 hiddenField.setAttribute("value", "'.$dest.'");
8264 form.appendChild(hiddenField);
8265
8266 var hiddenField = document.createElement("input");
8267 hiddenField.setAttribute("type", "hidden");
8268 hiddenField.setAttribute("name", "opname");
8269 hiddenField.setAttribute("value", "'.$name.'");
8270 form.appendChild(hiddenField);
8271
8272 var hiddenField = document.createElement("input");
8273 hiddenField.setAttribute("type", "hidden");
8274 hiddenField.setAttribute("name", "path");
8275 hiddenField.setAttribute("value", "'.urlencode(_MPDF_TEMP_PATH).'");
8276 form.appendChild(hiddenField);
8277
8278 document.body.appendChild(form);
8279 form.submit();
8280
8281 </script>
8282 </div>
8283 </body>
8284 </html>';
8285 exit;
8286 }
8287 else {
8288 if ($this->progressBar) { $this->UpdateProgressBar(3,'','Finished'); }
8289 /*-- END PROGRESS-BAR --*/
8290
8291 switch($dest) {
8292 case 'I':
8293 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; }
8294 //Send to standard output
8295 if(PHP_SAPI!='cli') {
8296 //We send to a browser
8297 header('Content-Type: application/pdf');
8298 if(headers_sent())
8299 $this->Error('Some data has already been output to browser, can\'t send PDF file');
8300 if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
8301 // don't use length if server using compression
8302 header('Content-Length: '.strlen($this->buffer));
8303 }
8304 header('Content-disposition: inline; filename="'.$name.'"');
8305 header('Cache-Control: public, must-revalidate, max-age=0');
8306 header('Pragma: public');
8307 header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
8308 header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
8309 }
8310 echo $this->buffer;
8311 break;
8312 case 'D':
8313 //Download file
8314 header('Content-Description: File Transfer');
8315 if (headers_sent())
8316 $this->Error('Some data has already been output to browser, can\'t send PDF file');
8317 header('Content-Transfer-Encoding: binary');
8318 header('Cache-Control: public, must-revalidate, max-age=0');
8319 header('Pragma: public');
8320 header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
8321 header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
8322 header('Content-Type: application/force-download');
8323 header('Content-Type: application/octet-stream', false);
8324 header('Content-Type: application/download', false);
8325 header('Content-Type: application/pdf', false);
8326 if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
8327 // don't use length if server using compression
8328 header('Content-Length: '.strlen($this->buffer));
8329 }
8330 header('Content-disposition: attachment; filename="'.$name.'"');
8331 echo $this->buffer;
8332 break;
8333 case 'F':
8334 //Save to local file
8335 $f=fopen($name,'wb');
8336 if(!$f) $this->Error('Unable to create output file: '.$name);
8337 fwrite($f,$this->buffer,strlen($this->buffer));
8338 fclose($f);
8339 break;
8340 case 'S':
8341 //Return as a string
8342 return $this->buffer;
8343 default:
8344 $this->Error('Incorrect output destination: '.$dest);
8345 }
8346
8347 } // *PROGRESS-BAR*
8348 //======================================================================================================
8349 // DELETE OLD TMP FILES - Housekeeping
8350 // Delete any files in tmp/ directory that are >1 hrs old
8351 $interval = 3600;
8352 if ($handle = @opendir(preg_replace('/\/$/','',_MPDF_TEMP_PATH))) { // mPDF 5.7.3
8353 while (false !== ($file = readdir($handle))) {
8354 if (($file != "..") && ($file != ".") && !is_dir($file) && ((filemtime(_MPDF_TEMP_PATH.$file)+$interval) < time()) && (substr($file, 0, 1) !== '.') && ($file !='dummy.txt')) { // mPDF 5.7.3
8355 unlink(_MPDF_TEMP_PATH.$file);
8356 }
8357 }
8358 closedir($handle);
8359 }
8360 //==============================================================================================================
8361
8362 return '';
8363 }
8364
8365
8366 // *****************************************************************************
8367 // *
8368 // Protected methods *
8369 // *
8370 // *****************************************************************************
8371 function _dochecks()
8372 {
8373 //Check for locale-related bug
8374 if(1.1==1)
8375 $this->Error('Don\'t alter the locale before including mPDF');
8376 //Check for decimal separator
8377 if(sprintf('%.1f',1.0)!='1.0')
8378 setlocale(LC_NUMERIC,'C');
8379 $mqr=ini_get("magic_quotes_runtime");
8380 if ($mqr) { $this->Error('mPDF requires magic_quotes_runtime to be turned off e.g. by using ini_set("magic_quotes_runtime", 0);'); }
8381 }
8382
8383
8384
8385 function _puthtmlheaders() {
8386 $this->state=2;
8387 $nb=$this->page;
8388 for($n=1;$n<=$nb;$n++) {
8389 if ($this->mirrorMargins && $n%2==0) { $OE = 'E'; } // EVEN
8390 else { $OE = 'O'; }
8391 $this->page = $n;
8392 $pn = $this->docPageNum($n);
8393 if ($pn)
8394 $pnstr = $this->pagenumPrefix.$pn.$this->pagenumSuffix;
8395 else { $pnstr = ''; }
8396 $pnt = $this->docPageNumTotal($n);
8397 if ($pnt)
8398 $pntstr = $this->nbpgPrefix.$pnt.$this->nbpgSuffix;
8399 else { $pntstr = ''; }
8400 if (isset($this->saveHTMLHeader[$n][$OE])) {
8401 $html = $this->saveHTMLHeader[$n][$OE]['html'];
8402 $this->lMargin = $this->saveHTMLHeader[$n][$OE]['ml'];
8403 $this->rMargin = $this->saveHTMLHeader[$n][$OE]['mr'];
8404 $this->tMargin = $this->saveHTMLHeader[$n][$OE]['mh'];
8405 $this->bMargin = $this->saveHTMLHeader[$n][$OE]['mf'];
8406 $this->margin_header = $this->saveHTMLHeader[$n][$OE]['mh'];
8407 $this->margin_footer = $this->saveHTMLHeader[$n][$OE]['mf'];
8408 $this->w = $this->saveHTMLHeader[$n][$OE]['pw'];
8409 $this->h = $this->saveHTMLHeader[$n][$OE]['ph'];
8410 $rotate = (isset($this->saveHTMLHeader[$n][$OE]['rotate']) ? $this->saveHTMLHeader[$n][$OE]['rotate'] : null);
8411 $this->Reset();
8412 $this->pageoutput[$n] = array();
8413 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
8414 $this->x = $this->lMargin;
8415 $this->y = $this->margin_header;
8416 $html = str_replace('{PAGENO}',$pnstr,$html);
8417 $html = str_replace($this->aliasNbPgGp,$pntstr,$html ); // {nbpg}
8418 $html = str_replace($this->aliasNbPg,$nb,$html ); // {nb}
8419 $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', array($this, 'date_callback'),$html ); // mPDF 5.7
8420
8421 $this->HTMLheaderPageLinks = array();
8422 $this->HTMLheaderPageAnnots = array();
8423 $this->HTMLheaderPageForms = array();
8424 $this->pageBackgrounds = array();
8425
8426 $this->writingHTMLheader = true;
8427 $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
8428 $this->writingHTMLheader = false;
8429 $this->Reset();
8430 $this->pageoutput[$n] = array();
8431
8432 $s = $this->PrintPageBackgrounds();
8433 $this->headerbuffer = $s . $this->headerbuffer;
8434 $os = '';
8435 if ($rotate) {
8436 $os .= sprintf('q 0 -1 1 0 0 %.3F cm ',($this->w*_MPDFK));
8437 // To rotate the other way i.e. Header to left of page:
8438 //$os .= sprintf('q 0 1 -1 0 %.3F %.3F cm ',($this->h*_MPDFK), (($this->rMargin - $this->lMargin )*_MPDFK));
8439 }
8440 $os .= $this->headerbuffer ;
8441 if ($rotate) {
8442 $os .= ' Q' . "\n";
8443 }
8444
8445 // Writes over the page background but behind any other output on page
8446 $os = preg_replace('/\\\\/','\\\\\\\\',$os);
8447 $this->pages[$n] = preg_replace('/(___HEADER___MARKER'.$this->uniqstr.')/', "\n".$os."\n".'\\1', $this->pages[$n]);
8448
8449 $lks = $this->HTMLheaderPageLinks;
8450 foreach($lks AS $lk) {
8451 if ($rotate) {
8452 $lw = $lk[2];
8453 $lh = $lk[3];
8454 $lk[2] = $lh;
8455 $lk[3] = $lw; // swap width and height
8456 $ax = $lk[0]/_MPDFK;
8457 $ay = $lk[1]/_MPDFK;
8458 $bx = $ay-($lh/_MPDFK);
8459 $by = $this->w-$ax;
8460 $lk[0] = $bx*_MPDFK;
8461 $lk[1] = ($this->h-$by)*_MPDFK - $lw;
8462 }
8463 $this->PageLinks[$n][]=$lk;
8464 }
8465 /*-- FORMS --*/
8466 foreach($this->HTMLheaderPageForms AS $f) {
8467 $this->mpdfform->forms[$f['n']] = $f;
8468 }
8469 /*-- END FORMS --*/
8470
8471
8472 }
8473 if (isset($this->saveHTMLFooter[$n][$OE])) {
8474 $html = $this->saveHTMLFooter[$this->page][$OE]['html'];
8475 $this->lMargin = $this->saveHTMLFooter[$n][$OE]['ml'];
8476 $this->rMargin = $this->saveHTMLFooter[$n][$OE]['mr'];
8477 $this->tMargin = $this->saveHTMLFooter[$n][$OE]['mh'];
8478 $this->bMargin = $this->saveHTMLFooter[$n][$OE]['mf'];
8479 $this->margin_header = $this->saveHTMLFooter[$n][$OE]['mh'];
8480 $this->margin_footer = $this->saveHTMLFooter[$n][$OE]['mf'];
8481 $this->w = $this->saveHTMLFooter[$n][$OE]['pw'];
8482 $this->h = $this->saveHTMLFooter[$n][$OE]['ph'];
8483 $rotate = (isset($this->saveHTMLFooter[$n][$OE]['rotate']) ? $this->saveHTMLFooter[$n][$OE]['rotate'] : null);
8484 $this->Reset();
8485 $this->pageoutput[$n] = array();
8486 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
8487 $this->x = $this->lMargin;
8488 $top_y = $this->y = $this->h - $this->margin_footer;
8489
8490 // if bottom-margin==0, corrects to avoid division by zero
8491 if ($this->y == $this->h) { $top_y = $this->y = ($this->h - 0.1); }
8492 $html = str_replace('{PAGENO}',$pnstr,$html);
8493 $html = str_replace($this->aliasNbPgGp,$pntstr,$html ); // {nbpg}
8494 $html = str_replace($this->aliasNbPg,$nb,$html ); // {nb}
8495 $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', array($this, 'date_callback'),$html ); // mPDF 5.7
8496
8497
8498 $this->HTMLheaderPageLinks = array();
8499 $this->HTMLheaderPageAnnots = array();
8500 $this->HTMLheaderPageForms = array();
8501 $this->pageBackgrounds = array();
8502
8503 $this->writingHTMLfooter = true;
8504 $this->InFooter = true;
8505 $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
8506 $this->InFooter = false;
8507 $this->Reset();
8508 $this->pageoutput[$n] = array();
8509
8510 $fheight = $this->y - $top_y;
8511 $adj = -$fheight;
8512
8513 $s = $this->PrintPageBackgrounds(-$adj);
8514 $this->headerbuffer = $s . $this->headerbuffer;
8515 $this->writingHTMLfooter = false; // mPDF 5.7.3 (moved after PrintPageBackgrounds so can adjust position of images in footer)
8516
8517 $os = '';
8518 $os .= $this->StartTransform(true)."\n";
8519 if ($rotate) {
8520 $os .= sprintf('q 0 -1 1 0 0 %.3F cm ',($this->w*_MPDFK));
8521 // To rotate the other way i.e. Header to left of page:
8522 //$os .= sprintf('q 0 1 -1 0 %.3F %.3F cm ',($this->h*_MPDFK), (($this->rMargin - $this->lMargin )*_MPDFK));
8523 }
8524 $os .= $this->transformTranslate(0, $adj, true)."\n";
8525 $os .= $this->headerbuffer ;
8526 if ($rotate) {
8527 $os .= ' Q' . "\n";
8528 }
8529 $os .= $this->StopTransform(true)."\n";
8530 // Writes over the page background but behind any other output on page
8531 $os = preg_replace('/\\\\/','\\\\\\\\',$os);
8532 $this->pages[$n] = preg_replace('/(___HEADER___MARKER'.$this->uniqstr.')/', "\n".$os."\n".'\\1', $this->pages[$n]);
8533
8534 $lks = $this->HTMLheaderPageLinks;
8535 foreach($lks AS $lk) {
8536 $lk[1] -= $adj*_MPDFK;
8537 if ($rotate) {
8538 $lw = $lk[2];
8539 $lh = $lk[3];
8540 $lk[2] = $lh;
8541 $lk[3] = $lw; // swap width and height
8542
8543 $ax = $lk[0]/_MPDFK;
8544 $ay = $lk[1]/_MPDFK;
8545 $bx = $ay-($lh/_MPDFK);
8546 $by = $this->w-$ax;
8547 $lk[0] = $bx*_MPDFK;
8548 $lk[1] = ($this->h-$by)*_MPDFK - $lw;
8549 }
8550 $this->PageLinks[$n][]=$lk;
8551 }
8552 /*-- FORMS --*/
8553 foreach($this->HTMLheaderPageForms AS $f) {
8554 $f['y'] += $adj;
8555 $this->mpdfform->forms[$f['n']] = $f;
8556 }
8557 /*-- END FORMS --*/
8558 }
8559 }
8560 $this->page=$nb;
8561 $this->state=1;
8562 }
8563
8564
8565
8566 function _putpages()
8567 {
8568 $nb=$this->page;
8569 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
8570
8571 if($this->DefOrientation=='P') {
8572 $defwPt=$this->fwPt;
8573 $defhPt=$this->fhPt;
8574 }
8575 else {
8576 $defwPt=$this->fhPt;
8577 $defhPt=$this->fwPt;
8578 }
8579 $annotid=(3+2*$nb);
8580
8581 // Active Forms
8582 $totaladdnum = 0;
8583 for($n=1;$n<=$nb;$n++) {
8584 if (isset($this->PageLinks[$n])) { $totaladdnum += count($this->PageLinks[$n]); }
8585 /*-- ANNOTATIONS --*/
8586 if (isset($this->PageAnnots[$n])) {
8587 foreach ($this->PageAnnots[$n] as $k => $pl) {
8588 if (!empty($pl['opt']['popup']) || !empty($pl['opt']['file'])) { $totaladdnum += 2 ; }
8589 else { $totaladdnum++; }
8590 }
8591 }
8592 /*-- END ANNOTATIONS --*/
8593
8594 /*-- FORMS --*/
8595 if ( count($this->mpdfform->forms) > 0 ) {
8596 $this->mpdfform->countPageForms($n, $totaladdnum);
8597 }
8598 /*-- END FORMS --*/
8599 }
8600 /*-- FORMS --*/
8601 // Make a note in the radio button group of the obj_id it will have
8602 $ctr = 0;
8603 if (count($this->mpdfform->form_radio_groups)) {
8604 foreach($this->mpdfform->form_radio_groups AS $name=>$frg) {
8605 $this->mpdfform->form_radio_groups[$name]['obj_id'] = $annotid + $totaladdnum + $ctr;
8606 $ctr++;
8607 }
8608 }
8609 /*-- END FORMS --*/
8610
8611 // Select unused fonts (usually default font)
8612 $unused = array();
8613 foreach($this->fonts as $fk=>$font) {
8614 if (isset($font['type']) && $font['type']=='TTF' && !$font['used']) {
8615 $unused[] = $fk;
8616 }
8617 }
8618
8619
8620 for($n=1;$n<=$nb;$n++)
8621 {
8622 $thispage = $this->pages[$n];
8623 if(isset($this->OrientationChanges[$n])) {
8624 $hPt=$this->pageDim[$n]['w']*_MPDFK;
8625 $wPt=$this->pageDim[$n]['h']*_MPDFK;
8626 $owidthPt_LR = $this->pageDim[$n]['outer_width_TB']*_MPDFK;
8627 $owidthPt_TB = $this->pageDim[$n]['outer_width_LR']*_MPDFK;
8628 }
8629 else {
8630 $wPt=$this->pageDim[$n]['w']*_MPDFK;
8631 $hPt=$this->pageDim[$n]['h']*_MPDFK;
8632 $owidthPt_LR = $this->pageDim[$n]['outer_width_LR']*_MPDFK;
8633 $owidthPt_TB = $this->pageDim[$n]['outer_width_TB']*_MPDFK;
8634 }
8635 // Remove references to unused fonts (usually default font)
8636 foreach($unused as $fk) {
8637 if ($this->fonts[$fk]['sip'] || $this->fonts[$fk]['smp']) {
8638 foreach($this->fonts[$fk]['subsetfontids'] AS $k => $fid) {
8639 $thispage = preg_replace('/\s\/F'.$fid.' \d[\d.]* Tf\s/is',' ',$thispage);
8640 }
8641 }
8642 else {
8643 $thispage = preg_replace('/\s\/F'.$this->fonts[$fk]['i'].' \d[\d.]* Tf\s/is',' ',$thispage);
8644 }
8645 }
8646 // Clean up repeated /GS1 gs statements
8647 // For some reason using + for repetition instead of {2,20} crashes PHP Script Interpreter ???
8648 $thispage = preg_replace('/(\/GS1 gs\n){2,20}/', "/GS1 gs\n", $thispage);
8649
8650 $thispage = preg_replace('/(\s*___BACKGROUND___PATTERNS'.$this->uniqstr.'\s*)/', " ", $thispage);
8651 $thispage = preg_replace('/(\s*___HEADER___MARKER'.$this->uniqstr.'\s*)/', " ", $thispage);
8652 $thispage = preg_replace('/(\s*___PAGE___START'.$this->uniqstr.'\s*)/', " ", $thispage);
8653 $thispage = preg_replace('/(\s*___TABLE___BACKGROUNDS'.$this->uniqstr.'\s*)/', " ", $thispage);
8654 // mPDF 5.7.3 TRANSFORMS
8655 while (preg_match('/(\% BTR(.*?)\% ETR)/is', $thispage, $m)) {
8656 $thispage = preg_replace('/(\% BTR.*?\% ETR)/is', '', $thispage, 1)."\n".$m[2];
8657 }
8658
8659 //Page
8660 $this->_newobj();
8661 $this->_out('<</Type /Page');
8662 $this->_out('/Parent 1 0 R');
8663 if(isset($this->OrientationChanges[$n])) {
8664 $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$hPt,$wPt));
8665 //If BleedBox is defined, it must be larger than the TrimBox, but smaller than the MediaBox
8666 $bleedMargin = $this->pageDim[$n]['bleedMargin']*_MPDFK;
8667 if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) {
8668 $x0 = $owidthPt_TB-$bleedMargin;
8669 $y0 = $owidthPt_LR-$bleedMargin;
8670 $x1 = $hPt-$owidthPt_TB+$bleedMargin;
8671 $y1 = $wPt-$owidthPt_LR+$bleedMargin;
8672 $this->_out(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1));
8673 }
8674 $this->_out(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_TB, $owidthPt_LR, ($hPt-$owidthPt_TB), ($wPt-$owidthPt_LR)));
8675 if (isset($this->OrientationChanges[$n]) && $this->displayDefaultOrientation) {
8676 if ($this->DefOrientation=='P') { $this->_out('/Rotate 270'); }
8677 else { $this->_out('/Rotate 90'); }
8678 }
8679 }
8680 //else if($wPt != $defwPt || $hPt != $defhPt) {
8681 else {
8682 $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$wPt,$hPt));
8683 $bleedMargin = $this->pageDim[$n]['bleedMargin']*_MPDFK;
8684 if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) {
8685 $x0 = $owidthPt_LR-$bleedMargin;
8686 $y0 = $owidthPt_TB-$bleedMargin;
8687 $x1 = $wPt-$owidthPt_LR+$bleedMargin;
8688 $y1 = $hPt-$owidthPt_TB+$bleedMargin;
8689 $this->_out(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1));
8690 }
8691 $this->_out(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_LR, $owidthPt_TB, ($wPt-$owidthPt_LR), ($hPt-$owidthPt_TB)));
8692 }
8693 $this->_out('/Resources 2 0 R');
8694
8695 // Important to keep in RGB colorSpace when using transparency
8696 if (!$this->PDFA && !$this->PDFX) {
8697 if ($this->restrictColorSpace == 3)
8698 $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceCMYK >> ');
8699 else if ($this->restrictColorSpace == 1)
8700 $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceGray >> ');
8701 else
8702 $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceRGB >> ');
8703 }
8704
8705 $annotsnum = 0;
8706 $embeddedfiles = array(); // mPDF 5.7.2 /EmbeddedFiles
8707
8708 if (isset($this->PageLinks[$n])) { $annotsnum += count($this->PageLinks[$n]); }
8709 /*-- ANNOTATIONS --*/
8710 if (isset($this->PageAnnots[$n])) {
8711 foreach ($this->PageAnnots[$n] as $k => $pl) {
8712 if (!empty($pl['opt']['file'])) { $embeddedfiles[$annotsnum+1] = true ; } // mPDF 5.7.2 /EmbeddedFiles
8713 if (!empty($pl['opt']['popup']) || !empty($pl['opt']['file'])) { $annotsnum += 2 ; }
8714 else { $annotsnum++; }
8715 $this->PageAnnots[$n][$k]['pageobj'] = $this->n;
8716 }
8717 }
8718 /*-- END ANNOTATIONS --*/
8719
8720 /*-- FORMS --*/
8721 // Active Forms
8722 $formsnum = 0;
8723 if ( count($this->mpdfform->forms) > 0 ) {
8724 foreach( $this->mpdfform->forms as $val ) {
8725 if ( $val['page'] == $n )
8726 $formsnum++;
8727 }
8728 }
8729 /*-- END FORMS --*/
8730 if ($annotsnum || $formsnum) {
8731 $s = '/Annots [ ';
8732 for($i=0;$i<$annotsnum;$i++) {
8733 if (!isset($embeddedfiles[$i])) { $s .= ($annotid + $i) . ' 0 R '; } // mPDF 5.7.2 /EmbeddedFiles
8734 }
8735 $annotid += $annotsnum;
8736 /*-- FORMS --*/
8737 if ( count($this->mpdfform->forms) > 0 ) {
8738 $this->mpdfform->addFormIds($n, $s, $annotid);
8739 }
8740 /*-- END FORMS --*/
8741 $s .= '] ';
8742 $this->_out($s);
8743 }
8744
8745 $this->_out('/Contents '.($this->n+1).' 0 R>>');
8746 $this->_out('endobj');
8747
8748 //Page content
8749 $this->_newobj();
8750 $p=($this->compress) ? gzcompress($thispage) : $thispage;
8751 $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
8752 $this->_putstream($p);
8753 $this->_out('endobj');
8754 }
8755 $this->_putannots(); // mPDF 5.7.2
8756
8757 //Pages root
8758 $this->offsets[1]=strlen($this->buffer);
8759 $this->_out('1 0 obj');
8760 $this->_out('<</Type /Pages');
8761 $kids='/Kids [';
8762 for($i=0;$i<$nb;$i++)
8763 $kids.=(3+2*$i).' 0 R ';
8764 $this->_out($kids.']');
8765 $this->_out('/Count '.$nb);
8766 $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$defwPt,$defhPt));
8767 $this->_out('>>');
8768 $this->_out('endobj');
8769 }
8770
8771
8772 function _putannots() { // mPDF 5.7.2
8773 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
8774 $nb=$this->page;
8775 for($n=1;$n<=$nb;$n++)
8776 {
8777 $annotobjs = array();
8778 if(isset($this->PageLinks[$n]) || isset($this->PageAnnots[$n]) || count($this->mpdfform->forms) > 0 ) {
8779 $wPt=$this->pageDim[$n]['w']*_MPDFK;
8780 $hPt=$this->pageDim[$n]['h']*_MPDFK;
8781
8782 //Links
8783 if(isset($this->PageLinks[$n])) {
8784 foreach($this->PageLinks[$n] as $key => $pl) {
8785 $this->_newobj();
8786 $annot='';
8787 $rect=sprintf('%.3F %.3F %.3F %.3F',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
8788 $annot .= '<</Type /Annot /Subtype /Link /Rect ['.$rect.']';
8789 $annot .= ' /Contents '.$this->_UTF16BEtextstring($pl[4]);
8790 $annot .= ' /NM '.$this->_textstring(sprintf('%04u-%04u', $n, $key));
8791 $annot .= ' /M '.$this->_textstring('D:'.date('YmdHis'));
8792 $annot .= ' /Border [0 0 0]';
8793 // Use this (instead of /Border) to specify border around link
8794 // $annot .= ' /BS <</W 1'; // Width on points; 0 = no line
8795 // $annot .= ' /S /D'; // style - [S]olid, [D]ashed, [B]eveled, [I]nset, [U]nderline
8796 // $annot .= ' /D [3 2]'; // Dash array - if dashed
8797 // $annot .= ' >>';
8798 // $annot .= ' /C [1 0 0]'; // Color RGB
8799
8800 if ($this->PDFA || $this->PDFX) { $annot .= ' /F 28'; }
8801 if (strpos($pl[4],'@')===0) {
8802 $p=substr($pl[4],1);
8803 // $h=isset($this->OrientationChanges[$p]) ? $wPt : $hPt;
8804 $htarg=$this->pageDim[$p]['h']*_MPDFK;
8805 $annot.=sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>',1+2*$p,$htarg);
8806 }
8807 else if(is_string($pl[4])) {
8808 $annot .= ' /A <</S /URI /URI '.$this->_textstring($pl[4]).'>> >>';
8809 }
8810 else {
8811 $l=$this->links[$pl[4]];
8812 // may not be set if #link points to non-existent target
8813 if (isset($this->pageDim[$l[0]]['h'])) { $htarg=$this->pageDim[$l[0]]['h']*_MPDFK; }
8814 else { $htarg=$this->h*_MPDFK; } // doesn't really matter
8815 $annot.=sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>',1+2*$l[0],$htarg-$l[1]*_MPDFK);
8816 }
8817 $this->_out($annot);
8818 $this->_out('endobj');
8819 }
8820 }
8821
8822
8823 /*-- ANNOTATIONS --*/
8824 if(isset($this->PageAnnots[$n])) {
8825 foreach ($this->PageAnnots[$n] as $key => $pl) {
8826 if ($pl['opt']['file']) { $FileAttachment=true; }
8827 else { $FileAttachment=false; }
8828 $this->_newobj();
8829 $annot='';
8830 $pl['opt'] = array_change_key_case($pl['opt'], CASE_LOWER);
8831 $x = $pl['x'];
8832 if ($this->annotMargin <> 0 || $x==0 || $x<0) { // Odd page
8833 $x = ($wPt/_MPDFK) - $this->annotMargin;
8834 }
8835 $w = $h = 0;
8836 $a = $x * _MPDFK;
8837 $b = $hPt - ($pl['y'] * _MPDFK);
8838 $annot .= '<</Type /Annot ';
8839 if ($FileAttachment) {
8840 $annot .= '/Subtype /FileAttachment ';
8841 // Need to set a size for FileAttachment icons
8842 if ($pl['opt']['icon']=='Paperclip') { $w=8.235; $h=20; } // 7,17
8843 else if ($pl['opt']['icon']=='Tag') { $w=20; $h=16; }
8844 else if ($pl['opt']['icon']=='Graph') { $w=20; $h=20; }
8845 else { $w=14; $h=20; } // PushPin
8846 $f = $pl['opt']['file'];
8847 $f = preg_replace('/^.*\//', '', $f);
8848 $f = preg_replace('/[^a-zA-Z0-9._]/', '', $f);
8849 $annot .= '/FS <</Type /Filespec /F ('.$f.')';
8850 $annot .= '/EF <</F '.($this->n+1).' 0 R>>';
8851 $annot .= '>>';
8852 }
8853 else {
8854 $annot .= '/Subtype /Text';
8855 $w=20; $h=20; // mPDF 6
8856 }
8857 $rect = sprintf('%.3F %.3F %.3F %.3F', $a, $b-$h, $a+$w, $b);
8858 $annot .= ' /Rect ['.$rect.']';
8859
8860 // contents = description of file in free text
8861 $annot .= ' /Contents '.$this->_UTF16BEtextstring($pl['txt']);
8862
8863 $annot .= ' /NM '.$this->_textstring(sprintf('%04u-%04u', $n, (2000 + $key)));
8864 $annot .= ' /M '.$this->_textstring('D:'.date('YmdHis'));
8865 $annot .= ' /CreationDate '.$this->_textstring('D:'.date('YmdHis'));
8866 $annot .= ' /Border [0 0 0]';
8867 if ($this->PDFA || $this->PDFX) {
8868 $annot .= ' /F 28';
8869 $annot .= ' /CA 1';
8870 }
8871 else if ($pl['opt']['ca']>0) { $annot .= ' /CA '.$pl['opt']['ca']; }
8872
8873 $annotcolor = ' /C [';
8874 if (isset($pl['opt']['c']) AND $pl['opt']['c']) {
8875 $col = $pl['opt']['c'];
8876 if ($col{0}==3 || $col{0}==5) { $annotcolor .= sprintf("%.3F %.3F %.3F", ord($col{1})/255,ord($col{2})/255,ord($col{3})/255); }
8877 else if ($col{0}==1) { $annotcolor .= sprintf("%.3F", ord($col{1})/255); }
8878 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); }
8879 else { $annotcolor .= '1 1 0'; }
8880 }
8881 else { $annotcolor .= '1 1 0'; }
8882 $annotcolor .= ']';
8883 $annot .= $annotcolor;
8884 // Usually Author
8885 // Use as Title for fileattachment
8886 if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) {
8887 $annot .= ' /T '.$this->_UTF16BEtextstring($pl['opt']['t']);
8888 }
8889 if ($FileAttachment) {
8890 $iconsapp = array('Paperclip', 'Graph', 'PushPin', 'Tag');
8891 }
8892 else { $iconsapp = array('Comment', 'Help', 'Insert', 'Key', 'NewParagraph', 'Note', 'Paragraph'); }
8893 if (isset($pl['opt']['icon']) AND in_array($pl['opt']['icon'], $iconsapp)) {
8894 $annot .= ' /Name /'.$pl['opt']['icon'];
8895 }
8896 else if ($FileAttachment) { $annot .= ' /Name /PushPin'; }
8897 else { $annot .= ' /Name /Note'; }
8898 if (!$FileAttachment) {
8899 // /Subj is PDF 1.5 spec.
8900 if (isset($pl['opt']['subj']) && !$this->PDFA && !$this->PDFX) {
8901 $annot .= ' /Subj '.$this->_UTF16BEtextstring($pl['opt']['subj']);
8902 }
8903 if (!empty($pl['opt']['popup'])) {
8904 $annot .= ' /Open true';
8905 $annot .= ' /Popup '.($this->n+1).' 0 R';
8906 }
8907 else { $annot .= ' /Open false'; }
8908 }
8909 $annot .= ' /P '.$pl['pageobj'].' 0 R';
8910 $annot .= '>>';
8911 $this->_out($annot);
8912 $this->_out('endobj');
8913
8914 if ($FileAttachment) {
8915 $file = @file_get_contents($pl['opt']['file']) or die('mPDF Error: Cannot access file attachment - '.$pl['opt']['file']);
8916 $filestream = gzcompress($file);
8917 $this->_newobj();
8918 $this->_out('<</Type /EmbeddedFile');
8919 $this->_out('/Length '.strlen($filestream));
8920 $this->_out('/Filter /FlateDecode');
8921 $this->_out('>>');
8922 $this->_putstream($filestream);
8923 $this->_out('endobj');
8924 }
8925 else if (!empty($pl['opt']['popup'])) {
8926 $this->_newobj();
8927 $annot='';
8928 if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][0])) { $x = $pl['opt']['popup'][0] * _MPDFK; }
8929 else { $x = $pl['x'] * _MPDFK; }
8930 if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][1])) { $y = $hPt - ($pl['opt']['popup'][1] * _MPDFK); }
8931 else { $y = $hPt - ($pl['y'] * _MPDFK); }
8932 if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][2])) { $w = $pl['opt']['popup'][2] * _MPDFK; }
8933 else { $w = 180; }
8934 if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][3])) { $h = $pl['opt']['popup'][3] * _MPDFK; }
8935 else { $h = 120; }
8936 $rect = sprintf('%.3F %.3F %.3F %.3F', $x, $y-$h, $x+$w, $y);
8937 $annot .= '<</Type /Annot /Subtype /Popup /Rect ['.$rect.']';
8938 $annot .= ' /M '.$this->_textstring('D:'.date('YmdHis'));
8939 if ($this->PDFA || $this->PDFX) { $annot .= ' /F 28'; }
8940 $annot .= ' /Parent '.($this->n-1).' 0 R';
8941 $annot .= '>>';
8942 $this->_out($annot);
8943 $this->_out('endobj');
8944 }
8945
8946 }
8947 }
8948 /*-- END ANNOTATIONS --*/
8949
8950 /*-- FORMS --*/
8951 // Active Forms
8952 if ( count($this->mpdfform->forms) > 0 ) {
8953 $this->mpdfform->_putFormItems($n, $hPt);
8954 }
8955 /*-- END FORMS --*/
8956 }
8957 }
8958 /*-- FORMS --*/
8959 // Active Forms - Radio Button Group entries
8960 // Output Radio Button Group form entries (radio_on_obj_id already determined)
8961 if (count($this->mpdfform->form_radio_groups)) {
8962 $this->mpdfform->_putRadioItems($n);
8963 }
8964 /*-- END FORMS --*/
8965 }
8966
8967
8968 /*-- ANNOTATIONS --*/
8969 function Annotation($text, $x=0, $y=0, $icon='Note', $author='', $subject='', $opacity=0, $colarray=false, $popup='', $file='') {
8970 if (is_array($colarray) && count($colarray)==3) { $colarray = $this->ConvertColor('rgb('.$colarray[0].','.$colarray[1].','.$colarray[2].')'); }
8971 if ($colarray === false) { $colarray = $this->ConvertColor('yellow'); }
8972 if ($x==0) { $x = $this->x; }
8973 if ($y==0) { $y = $this->y; }
8974 $page = $this->page;
8975 if ($page < 1) { // Document has not been started - assume it's for first page
8976 $page = 1;
8977 if ($x==0) { $x = $this->lMargin; }
8978 if ($y==0) { $y = $this->tMargin; }
8979 }
8980
8981 if ($this->PDFA || $this->PDFX) {
8982 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)"; }
8983 $x = ($this->w) - $this->rMargin*0.66;
8984 }
8985 if (!$this->annotMargin) { $y -= $this->FontSize / 2; }
8986
8987 if (!$opacity && $this->annotMargin) { $opacity = 1; }
8988 else if (!$opacity) { $opacity = $this->annotOpacity; }
8989
8990 $an = array('txt' => $text, 'x' => $x, 'y' => $y, 'opt' => array('Icon'=>$icon, 'T'=>$author, 'Subj'=>$subject, 'C'=>$colarray, 'CA'=>$opacity, 'popup'=>$popup, 'file'=>$file));
8991
8992 if ($this->keep_block_together) { // don't write yet
8993 return;
8994 }
8995 else if ($this->table_rotate) {
8996 $this->tbrot_Annots[$this->page][]= $an;
8997 return;
8998 }
8999 else if ($this->kwt) {
9000 $this->kwt_Annots[$this->page][]= $an;
9001 return;
9002 }
9003 if ($this->writingHTMLheader || $this->writingHTMLfooter) {
9004 $this->HTMLheaderPageAnnots[]= $an;
9005 return;
9006 }
9007 //Put an Annotation on the page
9008 $this->PageAnnots[$page][] = $an;
9009 /*-- COLUMNS --*/
9010 // Save cross-reference to Column buffer
9011 $ref = count($this->PageAnnots[$this->page])-1;
9012 $this->columnAnnots[$this->CurrCol][INTVAL($this->x)][INTVAL($this->y)] = $ref;
9013 /*-- END COLUMNS --*/
9014 }
9015 /*-- END ANNOTATIONS --*/
9016
9017
9018 function _putfonts() {
9019 $nf=$this->n;
9020 foreach($this->FontFiles as $fontkey=>$info) {
9021 // TrueType embedded
9022 if (isset($info['type']) && $info['type']=='TTF' && !$info['sip'] && !$info['smp']) {
9023 $used = true;
9024 $asSubset = false;
9025 foreach($this->fonts AS $k=>$f) {
9026 if (isset($f['fontkey']) && $f['fontkey'] == $fontkey && $f['type']=='TTF') {
9027 $used = $f['used'];
9028 if ($used) {
9029 $nChars = (ord($f['cw'][0]) << 8) + ord($f['cw'][1]);
9030 $usage = intval(count($f['subset'])*100 / $nChars);
9031 $fsize = $info['length1'];
9032 // Always subset the very large TTF files
9033 if ($fsize > ($this->maxTTFFilesize *1024)) { $asSubset = true; }
9034 else if ($usage < $this->percentSubset) { $asSubset = true; }
9035 }
9036 if ($this->PDFA || $this->PDFX) $asSubset = false;
9037 $this->fonts[$k]['asSubset'] = $asSubset;
9038 break;
9039 }
9040 }
9041 if ($used && !$asSubset) {
9042 //Font file embedding
9043 $this->_newobj();
9044 $this->FontFiles[$fontkey]['n']=$this->n;
9045 $font='';
9046 $originalsize = $info['length1'];
9047 if ($this->repackageTTF || $this->fonts[$fontkey]['TTCfontID']>0 || $this->fonts[$fontkey]['useOTL']>0) { // mPDF 5.7.1
9048 // First see if there is a cached compressed file
9049 if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z')) {
9050 $f=fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z','rb');
9051 if(!$f) { $this->Error('Font file .ps.z not found'); }
9052 while(!feof($f)) { $font .= fread($f, 2048); }
9053 fclose($f);
9054 include(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.php'); // sets $originalsize (of repackaged font)
9055 }
9056 else {
9057 if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
9058 $ttf = new TTFontFile();
9059 $font = $ttf->repackageTTF($this->FontFiles[$fontkey]['ttffile'], $this->fonts[$fontkey]['TTCfontID'], $this->debugfonts, $this->fonts[$fontkey]['useOTL']); // mPDF 5.7.1
9060
9061 $originalsize = strlen($font);
9062 $font = gzcompress($font);
9063 unset($ttf);
9064 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
9065 $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z',"wb");
9066 fwrite($fh,$font,strlen($font));
9067 fclose($fh);
9068 $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.php',"wb");
9069 $len = "<?php \n";
9070 $len.='$originalsize='.$originalsize.";\n";
9071 $len.="?>";
9072 fwrite($fh,$len,strlen($len));
9073 fclose($fh);
9074 }
9075 }
9076 }
9077 else {
9078 // First see if there is a cached compressed file
9079 if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.z')) {
9080 $f=fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.z','rb');
9081 if(!$f) { $this->Error('Font file not found'); }
9082 while(!feof($f)) { $font .= fread($f, 2048); }
9083 fclose($f);
9084 }
9085 else {
9086 $f=fopen($this->FontFiles[$fontkey]['ttffile'],'rb');
9087 if(!$f) { $this->Error('Font file not found'); }
9088 while(!feof($f)) { $font .= fread($f, 2048); }
9089 fclose($f);
9090 $font = gzcompress($font);
9091 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
9092 $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.z',"wb");
9093 fwrite($fh,$font,strlen($font));
9094 fclose($fh);
9095 }
9096 }
9097 }
9098
9099 $this->_out('<</Length '.strlen($font));
9100 $this->_out('/Filter /FlateDecode');
9101 $this->_out('/Length1 '.$originalsize);
9102 $this->_out('>>');
9103 $this->_putstream($font);
9104 $this->_out('endobj');
9105 }
9106 }
9107 }
9108
9109 $nfonts = count($this->fonts);
9110 $fctr = 1;
9111 foreach($this->fonts as $k=>$font) {
9112 //Font objects
9113 $type=$font['type'];
9114 $name=$font['name'];
9115 if ((!isset($font['used']) || !$font['used']) && $type=='TTF') { continue; }
9116 if ($this->progressBar) { $this->UpdateProgressBar(2,intval($fctr*100/$nfonts),'Writing Fonts'); $fctr++; } // *PROGRESS-BAR*
9117 if (isset($font['asSubset'])) { $asSubset = $font['asSubset']; }
9118 else { $asSubset = ''; }
9119 /*-- CJK-FONTS --*/
9120 if($type=='Type0') { // = Adobe CJK Fonts
9121 $this->fonts[$k]['n']=$this->n+1;
9122 $this->_newobj();
9123 $this->_out('<</Type /Font');
9124 $this->_putType0($font);
9125 }
9126 else
9127 /*-- END CJK-FONTS --*/
9128 if($type=='core') {
9129 //Standard font
9130 $this->fonts[$k]['n']=$this->n+1;
9131 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.)'); }
9132 $this->_newobj();
9133 $this->_out('<</Type /Font');
9134 $this->_out('/BaseFont /'.$name);
9135 $this->_out('/Subtype /Type1');
9136 if($name!='Symbol' && $name!='ZapfDingbats') {
9137 $this->_out('/Encoding /WinAnsiEncoding');
9138 }
9139 $this->_out('>>');
9140 $this->_out('endobj');
9141 }
9142 // TrueType embedded SUBSETS for SIP (CJK extB containing Supplementary Ideographic Plane 2)
9143 // Or Unicode Plane 1 - Supplementary Multilingual Plane
9144 else if ($type=='TTF' && ($font['sip'] || $font['smp'])) {
9145 if (!$font['used']) { continue; }
9146 $ssfaid="AA";
9147 if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
9148 $ttf = new TTFontFile();
9149 for($sfid=0;$sfid<count($font['subsetfontids']);$sfid++) {
9150 $this->fonts[$k]['n'][$sfid]=$this->n+1; // NB an array for subset
9151 $subsetname = 'MPDF'.$ssfaid.'+'.$font['name'];
9152 $ssfaid++;
9153
9154 /* For some strange reason a subset ($sfid > 0) containing less than 97 characters causes an error
9155 so fill up the array */
9156 for($j=count($font['subsets'][$sfid]);$j<98;$j++) {
9157 $font['subsets'][$sfid][$j]=0;
9158 }
9159
9160 $subset = $font['subsets'][$sfid];
9161 unset($subset[0]);
9162 $ttfontstream = $ttf->makeSubsetSIP($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts, $font['useOTL']); // mPDF 5.7.1
9163 $ttfontsize = strlen($ttfontstream);
9164 $fontstream = gzcompress($ttfontstream);
9165 $widthstring = '';
9166 $toUnistring = '';
9167
9168
9169 foreach($font['subsets'][$sfid] AS $cp=>$u) {
9170 $w = $this->_getCharWidth($font['cw'], $u);
9171 if ($w !== false) {
9172 $widthstring .= $w.' ';
9173 }
9174 else {
9175 $widthstring .= round($ttf->defaultWidth).' ';
9176 }
9177 if ($u > 65535) {
9178 $utf8 = chr(($u>>18)+240).chr((($u>>12)&63)+128).chr((($u>>6)&63)+128) .chr(($u&63)+128);
9179 $utf16 = mb_convert_encoding($utf8, 'UTF-16BE', 'UTF-8');
9180 $l1 = ord($utf16[0]);
9181 $h1 = ord($utf16[1]);
9182 $l2 = ord($utf16[2]);
9183 $h2 = ord($utf16[3]);
9184 $toUnistring .= sprintf("<%02s> <%02s%02s%02s%02s>\n", strtoupper(dechex($cp)), strtoupper(dechex($l1)), strtoupper(dechex($h1)), strtoupper(dechex($l2)), strtoupper(dechex($h2)));
9185 }
9186 else {
9187 $toUnistring .= sprintf("<%02s> <%04s>\n", strtoupper(dechex($cp)), strtoupper(dechex($u)));
9188 }
9189 }
9190
9191 //Additional Type1 or TrueType font
9192 $this->_newobj();
9193 $this->_out('<</Type /Font');
9194 $this->_out('/BaseFont /'.$subsetname);
9195 $this->_out('/Subtype /TrueType');
9196 $this->_out('/FirstChar 0 /LastChar '.(count($font['subsets'][$sfid])-1));
9197 $this->_out('/Widths '.($this->n+1).' 0 R');
9198 $this->_out('/FontDescriptor '.($this->n+2).' 0 R');
9199 $this->_out('/ToUnicode '.($this->n + 3).' 0 R');
9200 $this->_out('>>');
9201 $this->_out('endobj');
9202
9203 //Widths
9204 $this->_newobj();
9205 $this->_out('['.$widthstring.']');
9206 $this->_out('endobj');
9207
9208 //Descriptor
9209 $this->_newobj();
9210 $s='<</Type /FontDescriptor /FontName /'.$subsetname."\n";
9211 foreach($font['desc'] as $kd=>$v) {
9212 if ($kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag
9213 $s.=' /'.$kd.' '.$v."\n";
9214 }
9215 $s.='/FontFile2 '.($this->n + 2).' 0 R';
9216 $this->_out($s.'>>');
9217 $this->_out('endobj');
9218
9219 // ToUnicode
9220 $this->_newobj();
9221 $toUni = "/CIDInit /ProcSet findresource begin\n";
9222 $toUni .= "12 dict begin\n";
9223 $toUni .= "begincmap\n";
9224 $toUni .= "/CIDSystemInfo\n";
9225 $toUni .= "<</Registry (Adobe)\n";
9226 $toUni .= "/Ordering (UCS)\n";
9227 $toUni .= "/Supplement 0\n";
9228 $toUni .= ">> def\n";
9229 $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
9230 $toUni .= "/CMapType 2 def\n";
9231 $toUni .= "1 begincodespacerange\n";
9232 $toUni .= "<00> <FF>\n";
9233 //$toUni .= sprintf("<00> <%02s>\n", strtoupper(dechex(count($font['subsets'][$sfid])-1)));
9234 $toUni .= "endcodespacerange\n";
9235 $toUni .= count($font['subsets'][$sfid])." beginbfchar\n";
9236 $toUni .= $toUnistring;
9237 $toUni .= "endbfchar\n";
9238 $toUni .= "endcmap\n";
9239 $toUni .= "CMapName currentdict /CMap defineresource pop\n";
9240 $toUni .= "end\n";
9241 $toUni .= "end\n";
9242 $this->_out('<</Length '.(strlen($toUni)).'>>');
9243 $this->_putstream($toUni);
9244 $this->_out('endobj');
9245
9246 //Font file
9247 $this->_newobj();
9248 $this->_out('<</Length '.strlen($fontstream));
9249 $this->_out('/Filter /FlateDecode');
9250 $this->_out('/Length1 '.$ttfontsize);
9251 $this->_out('>>');
9252 $this->_putstream($fontstream);
9253 $this->_out('endobj');
9254 } // foreach subset
9255 unset($ttf);
9256 }
9257 // TrueType embedded SUBSETS or FULL
9258 else if ($type=='TTF') {
9259 $this->fonts[$k]['n']=$this->n+1;
9260 if ($asSubset ) {
9261 $ssfaid="A";
9262 if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
9263 $ttf = new TTFontFile();
9264 $fontname = 'MPDFA'.$ssfaid.'+'.$font['name'];
9265 $subset = $font['subset'];
9266 unset($subset[0]);
9267 $ttfontstream = $ttf->makeSubset($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts, $font['useOTL']);
9268 $ttfontsize = strlen($ttfontstream);
9269 $fontstream = gzcompress($ttfontstream);
9270 $codeToGlyph = $ttf->codeToGlyph;
9271 unset($codeToGlyph[0]);
9272 }
9273 else { $fontname = $font['name']; }
9274 // Type0 Font
9275 // A composite font - a font composed of other fonts, organized hierarchically
9276 $this->_newobj();
9277 $this->_out('<</Type /Font');
9278 $this->_out('/Subtype /Type0');
9279 $this->_out('/BaseFont /'.$fontname.'');
9280 $this->_out('/Encoding /Identity-H');
9281 $this->_out('/DescendantFonts ['.($this->n + 1).' 0 R]');
9282 $this->_out('/ToUnicode '.($this->n + 2).' 0 R');
9283 $this->_out('>>');
9284 $this->_out('endobj');
9285
9286 // CIDFontType2
9287 // A CIDFont whose glyph descriptions are based on TrueType font technology
9288 $this->_newobj();
9289 $this->_out('<</Type /Font');
9290 $this->_out('/Subtype /CIDFontType2');
9291 $this->_out('/BaseFont /'.$fontname.'');
9292 $this->_out('/CIDSystemInfo '.($this->n + 2).' 0 R');
9293 $this->_out('/FontDescriptor '.($this->n + 3).' 0 R');
9294 if (isset($font['desc']['MissingWidth'])){
9295 $this->_out('/DW '.$font['desc']['MissingWidth'].'');
9296 }
9297
9298 if (!$asSubset && file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw')) {
9299 $w = '';
9300 $w=file_get_contents(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw');
9301 $this->_out($w);
9302 }
9303 else {
9304 $this->_putTTfontwidths($font, $asSubset, ($asSubset ? $ttf->maxUni : 0));
9305 }
9306
9307 $this->_out('/CIDToGIDMap '.($this->n + 4).' 0 R');
9308 $this->_out('>>');
9309 $this->_out('endobj');
9310
9311 // ToUnicode
9312 $this->_newobj();
9313 $toUni = "/CIDInit /ProcSet findresource begin\n";
9314 $toUni .= "12 dict begin\n";
9315 $toUni .= "begincmap\n";
9316 $toUni .= "/CIDSystemInfo\n";
9317 $toUni .= "<</Registry (Adobe)\n";
9318 $toUni .= "/Ordering (UCS)\n";
9319 $toUni .= "/Supplement 0\n";
9320 $toUni .= ">> def\n";
9321 $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
9322 $toUni .= "/CMapType 2 def\n";
9323 $toUni .= "1 begincodespacerange\n";
9324 $toUni .= "<0000> <FFFF>\n";
9325 $toUni .= "endcodespacerange\n";
9326 $toUni .= "1 beginbfrange\n";
9327 $toUni .= "<0000> <FFFF> <0000>\n";
9328 $toUni .= "endbfrange\n";
9329 $toUni .= "endcmap\n";
9330 $toUni .= "CMapName currentdict /CMap defineresource pop\n";
9331 $toUni .= "end\n";
9332 $toUni .= "end\n";
9333 $this->_out('<</Length '.(strlen($toUni)).'>>');
9334 $this->_putstream($toUni);
9335 $this->_out('endobj');
9336
9337
9338 // CIDSystemInfo dictionary
9339 $this->_newobj();
9340 $this->_out('<</Registry (Adobe)');
9341 $this->_out('/Ordering (UCS)');
9342 $this->_out('/Supplement 0');
9343 $this->_out('>>');
9344 $this->_out('endobj');
9345
9346 // Font descriptor
9347 $this->_newobj();
9348 $this->_out('<</Type /FontDescriptor');
9349 $this->_out('/FontName /'.$fontname);
9350 foreach($font['desc'] as $kd=>$v) {
9351 if ($asSubset && $kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag
9352 $this->_out(' /'.$kd.' '.$v);
9353 }
9354 if ($font['panose']) {
9355 $this->_out(' /Style << /Panose <'.$font['panose'].'> >>');
9356 }
9357 if ($asSubset ) {
9358 $this->_out('/FontFile2 '.($this->n + 2).' 0 R');
9359 }
9360 else if ($font['fontkey']) {
9361 // obj ID of a stream containing a TrueType font program
9362 $this->_out('/FontFile2 '.$this->FontFiles[$font['fontkey']]['n'].' 0 R');
9363 }
9364 $this->_out('>>');
9365 $this->_out('endobj');
9366
9367 // Embed CIDToGIDMap
9368 // A specification of the mapping from CIDs to glyph indices
9369 if ($asSubset ) {
9370 $cidtogidmap = '';
9371 $cidtogidmap = str_pad('', 256*256*2, "\x00");
9372 foreach($codeToGlyph as $cc=>$glyph) {
9373 $cidtogidmap[$cc*2] = chr($glyph >> 8);
9374 $cidtogidmap[$cc*2 + 1] = chr($glyph & 0xFF);
9375 }
9376 $cidtogidmap = gzcompress($cidtogidmap);
9377 }
9378 else {
9379 // First see if there is a cached CIDToGIDMapfile
9380 $cidtogidmap = '';
9381 if (file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm')) {
9382 $f=fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm','rb');
9383 while(!feof($f)) { $cidtogidmap .= fread($f, 2048); }
9384 fclose($f);
9385 }
9386 else {
9387 if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
9388 $ttf = new TTFontFile();
9389 $charToGlyph = $ttf->getCTG($font['ttffile'], $font['TTCfontID'], $this->debugfonts, $font['useOTL']);
9390 $cidtogidmap = str_pad('', 256*256*2, "\x00");
9391 foreach($charToGlyph as $cc=>$glyph) {
9392 $cidtogidmap[$cc*2] = chr($glyph >> 8);
9393 $cidtogidmap[$cc*2 + 1] = chr($glyph & 0xFF);
9394 }
9395 unset($ttf);
9396 $cidtogidmap = gzcompress($cidtogidmap);
9397 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
9398 $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm',"wb");
9399 fwrite($fh,$cidtogidmap,strlen($cidtogidmap));
9400 fclose($fh);
9401 }
9402 }
9403 }
9404 $this->_newobj();
9405 $this->_out('<</Length '.strlen($cidtogidmap).'');
9406 $this->_out('/Filter /FlateDecode');
9407 $this->_out('>>');
9408 $this->_putstream($cidtogidmap);
9409 $this->_out('endobj');
9410
9411 //Font file
9412 if ($asSubset ) {
9413 $this->_newobj();
9414 $this->_out('<</Length '.strlen($fontstream));
9415 $this->_out('/Filter /FlateDecode');
9416 $this->_out('/Length1 '.$ttfontsize);
9417 $this->_out('>>');
9418 $this->_putstream($fontstream);
9419 $this->_out('endobj');
9420 unset($ttf);
9421 }
9422 }
9423 else { $this->Error('Unsupported font type: '.$type.' ('.$name.')'); }
9424 }
9425 }
9426
9427
9428
9429 function _putTTfontwidths(&$font, $asSubset, $maxUni) {
9430 if ($asSubset && file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php')) {
9431 include(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php') ;
9432 $startcid = 128;
9433 }
9434 else {
9435 $rangeid = 0;
9436 $range = array();
9437 $prevcid = -2;
9438 $prevwidth = -1;
9439 $interval = false;
9440 $startcid = 1;
9441 }
9442 if ($asSubset) { $cwlen = $maxUni + 1; }
9443 else { $cwlen = (strlen($font['cw'])/2); }
9444
9445 // for each character
9446 for ($cid=$startcid; $cid<$cwlen; $cid++) {
9447 if ($cid==128 && $asSubset && (!file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php'))) {
9448 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
9449 $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php',"wb");
9450 $cw127='<?php'."\n";
9451 $cw127.='$rangeid='.$rangeid.";\n";
9452 $cw127.='$prevcid='.$prevcid.";\n";
9453 $cw127.='$prevwidth='.$prevwidth.";\n";
9454 if ($interval) { $cw127.='$interval=true'.";\n"; }
9455 else { $cw127.='$interval=false'.";\n"; }
9456 $cw127.='$range='.var_export($range,true).";\n";
9457 $cw127.="?>";
9458 fwrite($fh,$cw127,strlen($cw127));
9459 fclose($fh);
9460 }
9461 }
9462 if ($font['cw'][$cid*2] == "\00" && $font['cw'][$cid*2+1] == "\00") { continue; }
9463 $width = (ord($font['cw'][$cid*2]) << 8) + ord($font['cw'][$cid*2+1]);
9464 if ($width == 65535) { $width = 0; }
9465 if ($asSubset && $cid > 255 && (!isset($font['subset'][$cid]) || !$font['subset'][$cid])) {
9466 continue;
9467 }
9468 if ($asSubset && $cid > 0xFFFF) { continue; } // mPDF 6
9469 if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
9470 if ($cid == ($prevcid + 1)) {
9471 // consecutive CID
9472 if ($width == $prevwidth) {
9473 if ($width == $range[$rangeid][0]) {
9474 $range[$rangeid][] = $width;
9475 } else {
9476 array_pop($range[$rangeid]);
9477 // new range
9478 $rangeid = $prevcid;
9479 $range[$rangeid] = array();
9480 $range[$rangeid][] = $prevwidth;
9481 $range[$rangeid][] = $width;
9482 }
9483 $interval = true;
9484 $range[$rangeid]['interval'] = true;
9485 } else {
9486 if ($interval) {
9487 // new range
9488 $rangeid = $cid;
9489 $range[$rangeid] = array();
9490 $range[$rangeid][] = $width;
9491 } else {
9492 $range[$rangeid][] = $width;
9493 }
9494 $interval = false;
9495 }
9496 } else {
9497 // new range
9498 $rangeid = $cid;
9499 $range[$rangeid] = array();
9500 $range[$rangeid][] = $width;
9501 $interval = false;
9502 }
9503 $prevcid = $cid;
9504 $prevwidth = $width;
9505 }
9506 }
9507 $w = $this->_putfontranges($range);
9508 $this->_out($w);
9509 if (!$asSubset) {
9510 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
9511 $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw',"wb");
9512 fwrite($fh,$w,strlen($w));
9513 fclose($fh);
9514 }
9515 }
9516 }
9517
9518 function _putfontranges(&$range) {
9519 // optimize ranges
9520 $prevk = -1;
9521 $nextk = -1;
9522 $prevint = false;
9523 foreach ($range as $k => $ws) {
9524 $cws = count($ws);
9525 if (($k == $nextk) AND (!$prevint) AND ((!isset($ws['interval'])) OR ($cws < 4))) {
9526 if (isset($range[$k]['interval'])) {
9527 unset($range[$k]['interval']);
9528 }
9529 $range[$prevk] = array_merge($range[$prevk], $range[$k]);
9530 unset($range[$k]);
9531 } else {
9532 $prevk = $k;
9533 }
9534 $nextk = $k + $cws;
9535 if (isset($ws['interval'])) {
9536 if ($cws > 3) {
9537 $prevint = true;
9538 } else {
9539 $prevint = false;
9540 }
9541 unset($range[$k]['interval']);
9542 --$nextk;
9543 } else {
9544 $prevint = false;
9545 }
9546 }
9547 // output data
9548 $w = '';
9549 foreach ($range as $k => $ws) {
9550 if (count(array_count_values($ws)) == 1) {
9551 // interval mode is more compact
9552 $w .= ' '.$k.' '.($k + count($ws) - 1).' '.$ws[0];
9553 } else {
9554 // range mode
9555 $w .= ' '.$k.' [ '.implode(' ', $ws).' ]' . "\n";
9556 }
9557 }
9558 return '/W ['.$w.' ]';
9559 }
9560
9561
9562 function _putfontwidths(&$font, $cidoffset=0) {
9563 ksort($font['cw']);
9564 unset($font['cw'][65535]);
9565 $rangeid = 0;
9566 $range = array();
9567 $prevcid = -2;
9568 $prevwidth = -1;
9569 $interval = false;
9570 // for each character
9571 foreach ($font['cw'] as $cid => $width) {
9572 $cid -= $cidoffset;
9573 if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
9574 if ($cid == ($prevcid + 1)) {
9575 // consecutive CID
9576 if ($width == $prevwidth) {
9577 if ($width == $range[$rangeid][0]) {
9578 $range[$rangeid][] = $width;
9579 } else {
9580 array_pop($range[$rangeid]);
9581 // new range
9582 $rangeid = $prevcid;
9583 $range[$rangeid] = array();
9584 $range[$rangeid][] = $prevwidth;
9585 $range[$rangeid][] = $width;
9586 }
9587 $interval = true;
9588 $range[$rangeid]['interval'] = true;
9589 } else {
9590 if ($interval) {
9591 // new range
9592 $rangeid = $cid;
9593 $range[$rangeid] = array();
9594 $range[$rangeid][] = $width;
9595 } else {
9596 $range[$rangeid][] = $width;
9597 }
9598 $interval = false;
9599 }
9600 } else {
9601 // new range
9602 $rangeid = $cid;
9603 $range[$rangeid] = array();
9604 $range[$rangeid][] = $width;
9605 $interval = false;
9606 }
9607 $prevcid = $cid;
9608 $prevwidth = $width;
9609 }
9610 }
9611 $this->_out($this->_putfontranges($range));
9612 }
9613
9614
9615 /*-- CJK-FONTS --*/
9616
9617 // from class PDF_Chinese CJK EXTENSIONS
9618 function _putType0(&$font)
9619 {
9620 //Type0
9621 $this->_out('/Subtype /Type0');
9622 $this->_out('/BaseFont /'.$font['name'].'-'.$font['CMap']);
9623 $this->_out('/Encoding /'.$font['CMap']);
9624 $this->_out('/DescendantFonts ['.($this->n+1).' 0 R]');
9625 $this->_out('>>');
9626 $this->_out('endobj');
9627 //CIDFont
9628 $this->_newobj();
9629 $this->_out('<</Type /Font');
9630 $this->_out('/Subtype /CIDFontType0');
9631 $this->_out('/BaseFont /'.$font['name']);
9632
9633 $cidinfo = '/Registry '.$this->_textstring('Adobe');
9634 $cidinfo .= ' /Ordering '.$this->_textstring($font['registry']['ordering']);
9635 $cidinfo .= ' /Supplement '.$font['registry']['supplement'];
9636 $this->_out('/CIDSystemInfo <<'.$cidinfo.'>>');
9637
9638 $this->_out('/FontDescriptor '.($this->n+1).' 0 R');
9639 if (isset($font['MissingWidth'])){
9640 $this->_out('/DW '.$font['MissingWidth'].'');
9641 }
9642 $this->_putfontwidths($font, 31);
9643 $this->_out('>>');
9644 $this->_out('endobj');
9645
9646 //Font descriptor
9647 $this->_newobj();
9648 $s = '<</Type /FontDescriptor /FontName /'.$font['name'];
9649 foreach ($font['desc'] as $k => $v) {
9650 if ($k != 'Style') {
9651 $s .= ' /'.$k.' '.$v.'';
9652 }
9653 }
9654 $this->_out($s.'>>');
9655 $this->_out('endobj');
9656 }
9657 /*-- END CJK-FONTS --*/
9658
9659
9660
9661 function _putimages()
9662 {
9663 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
9664 reset($this->images);
9665 while(list($file,$info)=each($this->images)) {
9666 $this->_newobj();
9667 $this->images[$file]['n']=$this->n;
9668 $this->_out('<</Type /XObject');
9669 $this->_out('/Subtype /Image');
9670 $this->_out('/Width '.$info['w']);
9671 $this->_out('/Height '.$info['h']);
9672 if (isset($info['interpolation']) && $info['interpolation']) {
9673 $this->_out('/Interpolate true'); // mPDF 6 - image interpolation shall be performed by a conforming reader
9674 }
9675 if (isset($info['masked'])) {
9676 $this->_out('/SMask '.($this->n - 1).' 0 R');
9677 }
9678 // set color space
9679 $icc = false;
9680 if (isset($info['icc']) AND ($info['icc'] !== false)) {
9681 // ICC Colour Space
9682 $icc = true;
9683 $this->_out('/ColorSpace [/ICCBased '.($this->n + 1).' 0 R]');
9684 }
9685 else if($info['cs']=='Indexed') {
9686 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.")."); }
9687 $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
9688 }
9689 else {
9690 $this->_out('/ColorSpace /'.$info['cs']);
9691 if($info['cs']=='DeviceCMYK') {
9692 if ($this->PDFA && $this->restrictColorSpace!=3) { $this->Error("PDFA1-b does not permit Images using mixed colour space (".$file.")."); }
9693 if($info['type']=='jpg') { $this->_out('/Decode [1 0 1 0 1 0 1 0]'); }
9694 }
9695 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.")."); }
9696 }
9697 $this->_out('/BitsPerComponent '.$info['bpc']);
9698 if (isset($info['f']) && $info['f']) { $this->_out('/Filter /'.$info['f']); }
9699 if(isset($info['parms'])) { $this->_out($info['parms']); }
9700 if(isset($info['trns']) and is_array($info['trns'])) {
9701 $trns='';
9702 for($i=0;$i<count($info['trns']);$i++)
9703 $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
9704 $this->_out('/Mask ['.$trns.']');
9705 }
9706 $this->_out('/Length '.strlen($info['data']).'>>');
9707 $this->_putstream($info['data']);
9708 unset($this->images[$file]['data']);
9709 $this->_out('endobj');
9710
9711 // ICC colour profile
9712 if ($icc) {
9713 $this->_newobj();
9714 $icc = ($this->compress) ? gzcompress($info['icc']) : $info['icc'];
9715 $this->_out('<</N '.$info['ch'].' '.$filter.'/Length '.strlen($icc).'>>');
9716 $this->_putstream($icc);
9717 $this->_out('endobj');
9718 }
9719 //Palette
9720 else if($info['cs']=='Indexed') {
9721 $this->_newobj();
9722 $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
9723 $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
9724 $this->_putstream($pal);
9725 $this->_out('endobj');
9726 }
9727 }
9728 }
9729
9730 function _putinfo()
9731 {
9732 $this->_out('/Producer '.$this->_UTF16BEtextstring('mPDF '.mPDF_VERSION));
9733 if(!empty($this->title))
9734 $this->_out('/Title '.$this->_UTF16BEtextstring($this->title));
9735 if(!empty($this->subject))
9736 $this->_out('/Subject '.$this->_UTF16BEtextstring($this->subject));
9737 if(!empty($this->author))
9738 $this->_out('/Author '.$this->_UTF16BEtextstring($this->author));
9739 if(!empty($this->keywords))
9740 $this->_out('/Keywords '.$this->_UTF16BEtextstring($this->keywords));
9741 if(!empty($this->creator))
9742 $this->_out('/Creator '.$this->_UTF16BEtextstring($this->creator));
9743
9744 $z = date('O'); // +0200
9745 $offset = substr($z,0,3)."'".substr($z,3,2)."'";
9746 $this->_out('/CreationDate '.$this->_textstring(date('YmdHis').$offset));
9747 $this->_out('/ModDate '.$this->_textstring(date('YmdHis').$offset));
9748 if ($this->PDFX) {
9749 $this->_out('/Trapped/False');
9750 $this->_out('/GTS_PDFXVersion(PDF/X-1a:2003)');
9751 }
9752 }
9753
9754 function _putmetadata() {
9755 $this->_newobj();
9756 $this->MetadataRoot = $this->n;
9757 $Producer = 'mPDF '.mPDF_VERSION;
9758 $z = date('O'); // +0200
9759 $offset = substr($z,0,3).':'.substr($z,3,2);
9760 $CreationDate = date('Y-m-d\TH:i:s').$offset; // 2006-03-10T10:47:26-05:00 2006-06-19T09:05:17Z
9761 $uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff),
9762 mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000,
9763 mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) );
9764
9765
9766 $m = '<?xpacket begin="'.chr(239).chr(187).chr(191).'" id="W5M0MpCehiHzreSzNTczkc9d"?>'."\n"; // begin = FEFF BOM
9767 $m .= ' <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="3.1-701">'."\n";
9768 $m .= ' <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">'."\n";
9769 $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">'."\n";
9770 $m .= ' <pdf:Producer>'.$Producer.'</pdf:Producer>'."\n";
9771 if(!empty($this->keywords)) { $m .= ' <pdf:Keywords>'.$this->keywords.'</pdf:Keywords>'."\n"; }
9772 $m .= ' </rdf:Description>'."\n";
9773
9774 $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:xmp="http://ns.adobe.com/xap/1.0/">'."\n";
9775 $m .= ' <xmp:CreateDate>'.$CreationDate.'</xmp:CreateDate>'."\n";
9776 $m .= ' <xmp:ModifyDate>'.$CreationDate.'</xmp:ModifyDate>'."\n";
9777 $m .= ' <xmp:MetadataDate>'.$CreationDate.'</xmp:MetadataDate>'."\n";
9778 if(!empty($this->creator)) { $m .= ' <xmp:CreatorTool>'.$this->creator.'</xmp:CreatorTool>'."\n"; }
9779 $m .= ' </rdf:Description>'."\n";
9780
9781 // DC elements
9782 $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:dc="http://purl.org/dc/elements/1.1/">'."\n";
9783 $m .= ' <dc:format>application/pdf</dc:format>'."\n";
9784 if(!empty($this->title)) {
9785 $m .= ' <dc:title>
9786 <rdf:Alt>
9787 <rdf:li xml:lang="x-default">'.$this->title.'</rdf:li>
9788 </rdf:Alt>
9789 </dc:title>'."\n";
9790 }
9791 if(!empty($this->keywords)) {
9792 $m .= ' <dc:subject>
9793 <rdf:Bag>
9794 <rdf:li>'.$this->keywords.'</rdf:li>
9795 </rdf:Bag>
9796 </dc:subject>'."\n";
9797 }
9798 if(!empty($this->subject)) {
9799 $m .= ' <dc:description>
9800 <rdf:Alt>
9801 <rdf:li xml:lang="x-default">'.$this->subject.'</rdf:li>
9802 </rdf:Alt>
9803 </dc:description>'."\n";
9804 }
9805 if(!empty($this->author)) {
9806 $m .= ' <dc:creator>
9807 <rdf:Seq>
9808 <rdf:li>'.$this->author.'</rdf:li>
9809 </rdf:Seq>
9810 </dc:creator>'."\n";
9811 }
9812 $m .= ' </rdf:Description>'."\n";
9813
9814
9815 // This bit is specific to PDFX-1a
9816 if ($this->PDFX) {
9817 $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";
9818 }
9819
9820 // This bit is specific to PDFA-1b
9821 else if ($this->PDFA) {
9822 $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/" >'."\n";
9823 $m .= ' <pdfaid:part>1</pdfaid:part>'."\n";
9824 $m .= ' <pdfaid:conformance>B</pdfaid:conformance>'."\n";
9825 $m .= ' <pdfaid:amd>2005</pdfaid:amd>'."\n";
9826 $m .= ' </rdf:Description>'."\n";
9827 }
9828
9829 $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">'."\n";
9830 $m .= ' <xmpMM:DocumentID>uuid:'.$uuid.'</xmpMM:DocumentID>'."\n";
9831 $m .= ' </rdf:Description>'."\n";
9832 $m .= ' </rdf:RDF>'."\n";
9833 $m .= ' </x:xmpmeta>'."\n";
9834 $m .= str_repeat(str_repeat(' ',100)."\n",20); // 2-4kB whitespace padding required
9835 $m .= '<?xpacket end="w"?>'; // "r" read only
9836 $this->_out('<</Type/Metadata/Subtype/XML/Length '.strlen($m).'>>');
9837 $this->_putstream($m);
9838 $this->_out('endobj');
9839 }
9840
9841 function _putoutputintent() {
9842 $this->_newobj();
9843 $this->OutputIntentRoot = $this->n;
9844 $this->_out('<</Type /OutputIntent');
9845
9846 if ($this->PDFA) {
9847 $this->_out('/S /GTS_PDFA1');
9848 if ($this->ICCProfile) {
9849 $this->_out('/Info ('.preg_replace('/_/',' ',$this->ICCProfile).')');
9850 $this->_out('/OutputConditionIdentifier (Custom)');
9851 $this->_out('/OutputCondition ()');
9852 }
9853 else {
9854 $this->_out('/Info (sRGB IEC61966-2.1)');
9855 $this->_out('/OutputConditionIdentifier (sRGB IEC61966-2.1)');
9856 $this->_out('/OutputCondition ()');
9857 }
9858 $this->_out('/DestOutputProfile '.($this->n+1).' 0 R');
9859 }
9860 else if ($this->PDFX) { // always a CMYK profile
9861 $this->_out('/S /GTS_PDFX');
9862 if ($this->ICCProfile) {
9863 $this->_out('/Info ('.preg_replace('/_/',' ',$this->ICCProfile).')');
9864 $this->_out('/OutputConditionIdentifier (Custom)');
9865 $this->_out('/OutputCondition ()');
9866 $this->_out('/DestOutputProfile '.($this->n+1).' 0 R');
9867 }
9868 else {
9869 $this->_out('/Info (CGATS TR 001)');
9870 $this->_out('/OutputConditionIdentifier (CGATS TR 001)');
9871 $this->_out('/OutputCondition (CGATS TR 001 (SWOP))');
9872 $this->_out('/RegistryName (http://www.color.org)');
9873 }
9874 }
9875 $this->_out('>>');
9876 $this->_out('endobj');
9877
9878 if ($this->PDFX && !$this->ICCProfile) { return; } // no ICCProfile embedded
9879
9880 $this->_newobj();
9881 if ($this->ICCProfile)
9882 $s = file_get_contents(_MPDF_PATH.'iccprofiles/'.$this->ICCProfile.'.icc');
9883 else
9884 $s = file_get_contents(_MPDF_PATH.'iccprofiles/sRGB_IEC61966-2-1.icc');
9885 if ($this->compress) { $s = gzcompress($s); }
9886 $this->_out('<<');
9887 if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace == 3)) { $this->_out('/N 4'); }
9888 else { $this->_out('/N 3'); }
9889 if ($this->compress)
9890 $this->_out('/Filter /FlateDecode ');
9891 $this->_out('/Length '.strlen($s).'>>');
9892 $this->_putstream($s);
9893 $this->_out('endobj');
9894 }
9895
9896
9897 function _putcatalog() {
9898 $this->_out('/Type /Catalog');
9899 $this->_out('/Pages 1 0 R');
9900 if($this->ZoomMode=='fullpage') $this->_out('/OpenAction [3 0 R /Fit]');
9901 elseif($this->ZoomMode=='fullwidth') $this->_out('/OpenAction [3 0 R /FitH null]');
9902 elseif($this->ZoomMode=='real') $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
9903 elseif(!is_string($this->ZoomMode)) $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode/100).']');
9904 else $this->_out('/OpenAction [3 0 R /XYZ null null null]');
9905 if($this->LayoutMode=='single') $this->_out('/PageLayout /SinglePage');
9906 elseif($this->LayoutMode=='continuous') $this->_out('/PageLayout /OneColumn');
9907 elseif($this->LayoutMode=='twoleft') $this->_out('/PageLayout /TwoColumnLeft');
9908 elseif($this->LayoutMode=='tworight') $this->_out('/PageLayout /TwoColumnRight');
9909 elseif($this->LayoutMode=='two') {
9910 if ($this->mirrorMargins) { $this->_out('/PageLayout /TwoColumnRight'); }
9911 else { $this->_out('/PageLayout /TwoColumnLeft'); }
9912 }
9913
9914 /*-- BOOKMARKS --*/
9915 if(count($this->BMoutlines)>0) {
9916 $this->_out('/Outlines '.$this->OutlineRoot.' 0 R');
9917 $this->_out('/PageMode /UseOutlines');
9918 }
9919 /*-- END BOOKMARKS --*/
9920 if(is_int(strpos($this->DisplayPreferences,'FullScreen'))) $this->_out('/PageMode /FullScreen');
9921
9922 // Metadata
9923 if ($this->PDFA || $this->PDFX) {
9924 $this->_out('/Metadata '.$this->MetadataRoot.' 0 R');
9925 }
9926 // OutputIntents
9927 if ($this->PDFA || $this->PDFX || $this->ICCProfile) {
9928 $this->_out('/OutputIntents ['.$this->OutputIntentRoot.' 0 R]');
9929 }
9930
9931 /*-- FORMS --*/
9932 if (count($this->mpdfform->forms)>0) {
9933 $this->mpdfform->_putFormsCatalog();
9934 }
9935 /*-- END FORMS --*/
9936 if ( isset($this->js) ) {
9937 $this->_out('/Names << /JavaScript '.($this->n_js).' 0 R >> ');
9938 }
9939
9940 if($this->DisplayPreferences || $this->directionality == 'rtl' || $this->mirrorMargins) {
9941 $this->_out('/ViewerPreferences<<');
9942 if(is_int(strpos($this->DisplayPreferences,'HideMenubar'))) $this->_out('/HideMenubar true');
9943 if(is_int(strpos($this->DisplayPreferences,'HideToolbar'))) $this->_out('/HideToolbar true');
9944 if(is_int(strpos($this->DisplayPreferences,'HideWindowUI'))) $this->_out('/HideWindowUI true');
9945 if(is_int(strpos($this->DisplayPreferences,'DisplayDocTitle'))) $this->_out('/DisplayDocTitle true');
9946 if(is_int(strpos($this->DisplayPreferences,'CenterWindow'))) $this->_out('/CenterWindow true');
9947 if(is_int(strpos($this->DisplayPreferences,'FitWindow'))) $this->_out('/FitWindow true');
9948 // /PrintScaling is PDF 1.6 spec.
9949 if(is_int(strpos($this->DisplayPreferences,'NoPrintScaling')) && !$this->PDFA && !$this->PDFX)
9950 $this->_out('/PrintScaling /None');
9951 if($this->directionality == 'rtl') $this->_out('/Direction /R2L');
9952 // /Duplex is PDF 1.7 spec.
9953 if($this->mirrorMargins && !$this->PDFA && !$this->PDFX) {
9954 // if ($this->DefOrientation=='P') $this->_out('/Duplex /DuplexFlipShortEdge');
9955 $this->_out('/Duplex /DuplexFlipLongEdge'); // PDF v1.7+
9956 }
9957 $this->_out('>>');
9958 }
9959 if($this->open_layer_pane && ($this->hasOC || count($this->layers)))
9960 $this->_out('/PageMode /UseOC');
9961
9962 if ($this->hasOC || count($this->layers)) {
9963 $p = $v = $h = $l = $loff = $lall = $as = '';
9964 if ($this->hasOC) {
9965 if (($this->hasOC & 1) == 1) $p=$this->n_ocg_print.' 0 R';
9966 if (($this->hasOC & 2) == 2) $v=$this->n_ocg_view.' 0 R';
9967 if (($this->hasOC & 4) == 4) $h=$this->n_ocg_hidden.' 0 R';
9968 $as="<</Event /Print /OCGs [$p $v $h] /Category [/Print]>> <</Event /View /OCGs [$p $v $h] /Category [/View]>>";
9969 }
9970
9971 if(count($this->layers)) {
9972 foreach($this->layers as $k=>$layer) {
9973 if (strtolower($this->layerDetails[$k]['state'])=='hidden') { $loff .= $layer['n'].' 0 R '; }
9974 else { $l .= $layer['n'].' 0 R '; }
9975 $lall .= $layer['n'].' 0 R ';
9976 }
9977 }
9978 $this->_out("/OCProperties <</OCGs [$p $v $h $lall] /D <</ON [$p $l] /OFF [$v $h $loff] ");
9979 $this->_out("/Order [$v $p $h $lall] ");
9980 if ($as) $this->_out("/AS [$as] ");
9981 $this->_out(">>>>");
9982
9983 }
9984
9985 }
9986
9987 // Inactive function left for backwards compatability
9988 function SetUserRights($enable=true, $annots="", $form="", $signature="") {
9989 // Does nothing
9990 }
9991
9992 function _enddoc() {
9993 if ($this->progressBar) { $this->UpdateProgressBar(2,'10','Writing Headers & Footers'); } // *PROGRESS-BAR*
9994 $this->_puthtmlheaders();
9995 if ($this->progressBar) { $this->UpdateProgressBar(2,'20','Writing Pages'); } // *PROGRESS-BAR*
9996
9997 // Remove references to unused fonts (usually default font)
9998 foreach($this->fonts as $fk=>$font) {
9999 if (isset($font['type']) && $font['type']=='TTF' && !$font['used']) {
10000 if ($font['sip'] || $font['smp']) {
10001 foreach($font['subsetfontids'] AS $k => $fid) {
10002 foreach($this->pages AS $pn=>$page) {
10003 $this->pages[$pn] = preg_replace('/\s\/F'.$fid.' \d[\d.]* Tf\s/is',' ',$this->pages[$pn]);
10004 }
10005 }
10006 }
10007 else {
10008 foreach($this->pages AS $pn=>$page) {
10009 $this->pages[$pn] = preg_replace('/\s\/F'.$font['i'].' \d[\d.]* Tf\s/is',' ',$this->pages[$pn]);
10010 }
10011 }
10012 }
10013 }
10014
10015 if (count($this->layers)) {
10016 foreach($this->pages AS $pn=>$page) {
10017 preg_match_all('/\/OCZ-index \/ZI(\d+) BDC(.*?)(EMCZ)-index/is',$this->pages[$pn],$m1);
10018 preg_match_all('/\/OCBZ-index \/ZI(\d+) BDC(.*?)(EMCBZ)-index/is',$this->pages[$pn],$m2);
10019 preg_match_all('/\/OCGZ-index \/ZI(\d+) BDC(.*?)(EMCGZ)-index/is',$this->pages[$pn],$m3);
10020 $m = array();
10021 for ($i=0;$i<4;$i++) {
10022 $m[$i] = array_merge($m1[$i],$m2[$i],$m3[$i]);
10023 }
10024 if (count($m[0])) {
10025 $sortarr = array();
10026 for($i=0;$i<count($m[0]);$i++) {
10027 $key = $m[1][$i]*2;
10028 if ($m[3][$i]=='EMCZ') $key +=2; // background first then gradient then normal
10029 else if ($m[3][$i]=='EMCGZ') $key +=1;
10030 $sortarr[$i] = $key;
10031 }
10032 asort($sortarr);
10033 foreach($sortarr AS $i=>$k) {
10034 $this->pages[$pn] = str_replace($m[0][$i],'',$this->pages[$pn] );
10035 $this->pages[$pn] .= "\n".$m[0][$i]."\n";
10036 }
10037 $this->pages[$pn] = preg_replace('/\/OC[BG]{0,1}Z-index \/ZI(\d+) BDC/is','/OC /ZI\\1 BDC ',$this->pages[$pn]);
10038 $this->pages[$pn] = preg_replace('/EMC[BG]{0,1}Z-index/is','EMC',$this->pages[$pn]);
10039 }
10040 }
10041 }
10042
10043 $this->_putpages();
10044 if ($this->progressBar) { $this->UpdateProgressBar(2,'30','Writing document resources'); } // *PROGRESS-BAR*
10045
10046 $this->_putresources();
10047 //Info
10048 $this->_newobj();
10049 $this->InfoRoot = $this->n;
10050 $this->_out('<<');
10051 if ($this->progressBar) { $this->UpdateProgressBar(2,'80','Writing document info'); } // *PROGRESS-BAR*
10052 $this->_putinfo();
10053 $this->_out('>>');
10054 $this->_out('endobj');
10055
10056 // METADATA
10057 if ($this->PDFA || $this->PDFX) { $this->_putmetadata(); }
10058 // OUTPUTINTENT
10059 if ($this->PDFA || $this->PDFX || $this->ICCProfile) { $this->_putoutputintent(); }
10060
10061 //Catalog
10062 $this->_newobj();
10063 $this->_out('<<');
10064 if ($this->progressBar) { $this->UpdateProgressBar(2,'90','Writing document catalog'); } // *PROGRESS-BAR*
10065 $this->_putcatalog();
10066 $this->_out('>>');
10067 $this->_out('endobj');
10068 //Cross-ref
10069 $o=strlen($this->buffer);
10070 $this->_out('xref');
10071 $this->_out('0 '.($this->n+1));
10072 $this->_out('0000000000 65535 f ');
10073 for($i=1; $i <= $this->n ; $i++)
10074 $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i]));
10075 //Trailer
10076 $this->_out('trailer');
10077 $this->_out('<<');
10078 $this->_puttrailer();
10079 $this->_out('>>');
10080 $this->_out('startxref');
10081 $this->_out($o);
10082
10083 $this->buffer .= '%%EOF';
10084 $this->state=3;
10085 /*-- IMPORTS --*/
10086
10087 if ($this->enableImports && count($this->parsers) > 0) {
10088 foreach ($this->parsers as $k => $_){
10089 $this->parsers[$k]->closeFile();
10090 $this->parsers[$k] = null;
10091 unset($this->parsers[$k]);
10092 }
10093 }
10094 /*-- END IMPORTS --*/
10095 }
10096
10097 function _beginpage($orientation,$mgl='',$mgr='',$mgt='',$mgb='',$mgh='',$mgf='',$ohname='',$ehname='',$ofname='',$efname='',$ohvalue=0,$ehvalue=0,$ofvalue=0,$efvalue=0,$pagesel='',$newformat='') {
10098 if (!($pagesel && $this->page==1 && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->tMargin)))) {
10099 $this->page++;
10100 $this->pages[$this->page]='';
10101 }
10102 $this->state=2;
10103 $resetHTMLHeadersrequired = false;
10104
10105 if ($newformat) { $this->_setPageSize($newformat, $orientation); }
10106 /*-- CSS-PAGE --*/
10107 // Paged media (page-box)
10108 if ($pagesel || (isset($this->page_box['using']) && $this->page_box['using'])) {
10109 if ($pagesel || $this->page==1) { $first = true; }
10110 else { $first = false; }
10111 if ($this->mirrorMargins && ($this->page % 2==0)) { $oddEven = 'E'; }
10112 else { $oddEven = 'O'; }
10113 if ($pagesel) { $psel = $pagesel; }
10114 else if ($this->page_box['current']) { $psel = $this->page_box['current']; }
10115 else { $psel = ''; }
10116 list($orientation,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS($psel, $first, $oddEven);
10117 if ($this->mirrorMargins && ($this->page % 2==0)) {
10118 if ($hname) { $ehvalue = 1; $ehname = $hname; } else { $ehvalue = -1; }
10119 if ($fname) { $efvalue = 1; $efname = $fname; } else { $efvalue = -1; }
10120 }
10121 else {
10122 if ($hname) { $ohvalue = 1; $ohname = $hname; } else { $ohvalue = -1; }
10123 if ($fname) { $ofvalue = 1; $ofname = $fname; } else { $ofvalue = -1; }
10124 }
10125 if ($resetpagenum || $pagenumstyle || $suppress) {
10126 $this->PageNumSubstitutions[] = array('from'=>($this->page), 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=>$suppress);
10127 }
10128 // PAGED MEDIA - CROP / CROSS MARKS from @PAGE
10129 $this->show_marks = $marks;
10130
10131 // Background color
10132 if (isset($bg['BACKGROUND-COLOR'])) {
10133 $cor = $this->ConvertColor($bg['BACKGROUND-COLOR']);
10134 if ($cor) {
10135 $this->bodyBackgroundColor = $cor;
10136 }
10137 }
10138 else { $this->bodyBackgroundColor = false; }
10139
10140 /*-- BACKGROUNDS --*/
10141 if (isset($bg['BACKGROUND-GRADIENT'])) {
10142 $this->bodyBackgroundGradient = $bg['BACKGROUND-GRADIENT'];
10143 }
10144 else { $this->bodyBackgroundGradient = false; }
10145
10146 // Tiling Patterns
10147 if (isset($bg['BACKGROUND-IMAGE']) && $bg['BACKGROUND-IMAGE']) {
10148 $ret = $this->SetBackground($bg, $this->pgwidth);
10149 if ($ret) { $this->bodyBackgroundImage = $ret; }
10150 }
10151 else { $this->bodyBackgroundImage = false; }
10152 /*-- END BACKGROUNDS --*/
10153
10154 $this->page_box['current'] = $psel;
10155 $this->page_box['using'] = true;
10156 }
10157 /*-- END CSS-PAGE --*/
10158
10159 //Page orientation
10160 if(!$orientation)
10161 $orientation=$this->DefOrientation;
10162 else {
10163 $orientation=strtoupper(substr($orientation,0,1));
10164 if($orientation!=$this->DefOrientation)
10165 $this->OrientationChanges[$this->page]=true;
10166 }
10167 if($orientation!=$this->CurOrientation || $newformat) {
10168
10169 //Change orientation
10170 if($orientation=='P') {
10171 $this->wPt=$this->fwPt;
10172 $this->hPt=$this->fhPt;
10173 $this->w=$this->fw;
10174 $this->h=$this->fh;
10175 if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P') {
10176 $this->tMargin = $this->orig_tMargin;
10177 $this->bMargin = $this->orig_bMargin;
10178 $this->DeflMargin = $this->orig_lMargin;
10179 $this->DefrMargin = $this->orig_rMargin;
10180 $this->margin_header = $this->orig_hMargin;
10181 $this->margin_footer = $this->orig_fMargin;
10182 }
10183 else { $resetHTMLHeadersrequired = true; }
10184 }
10185 else {
10186 $this->wPt=$this->fhPt;
10187 $this->hPt=$this->fwPt;
10188 $this->w=$this->fh;
10189 $this->h=$this->fw;
10190 if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P') {
10191 $this->tMargin = $this->orig_lMargin;
10192 $this->bMargin = $this->orig_rMargin;
10193 $this->DeflMargin = $this->orig_bMargin;
10194 $this->DefrMargin = $this->orig_tMargin;
10195 $this->margin_header = $this->orig_hMargin;
10196 $this->margin_footer = $this->orig_fMargin;
10197 }
10198 else { $resetHTMLHeadersrequired = true; }
10199
10200 }
10201 $this->CurOrientation=$orientation;
10202 $this->ResetMargins();
10203 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
10204 $this->PageBreakTrigger=$this->h-$this->bMargin;
10205 }
10206
10207 $this->pageDim[$this->page]['w']=$this->w ;
10208 $this->pageDim[$this->page]['h']=$this->h ;
10209
10210 $this->pageDim[$this->page]['outer_width_LR'] = isset($this->page_box['outer_width_LR']) ? $this->page_box['outer_width_LR'] : 0;
10211 $this->pageDim[$this->page]['outer_width_TB'] = isset($this->page_box['outer_width_TB']) ? $this->page_box['outer_width_TB'] : 0;
10212 if (!isset($this->page_box['outer_width_LR']) && !isset($this->page_box['outer_width_TB'])) {
10213 $this->pageDim[$this->page]['bleedMargin'] = 0;
10214 }
10215 else if ($this->bleedMargin <= $this->page_box['outer_width_LR'] && $this->bleedMargin <= $this->page_box['outer_width_TB']) {
10216 $this->pageDim[$this->page]['bleedMargin'] = $this->bleedMargin;
10217 }
10218 else {
10219 $this->pageDim[$this->page]['bleedMargin'] = min($this->page_box['outer_width_LR'], $this->page_box['outer_width_TB'])-0.01;
10220 }
10221
10222 // If Page Margins are re-defined
10223 // strlen()>0 is used to pick up (integer) 0, (string) '0', or set value
10224 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)) {
10225 if (strlen($mgl)>0) $this->DeflMargin = $mgl;
10226 if (strlen($mgr)>0) $this->DefrMargin = $mgr;
10227 if (strlen($mgt)>0) $this->tMargin = $mgt;
10228 if (strlen($mgb)>0) $this->bMargin = $mgb;
10229 if (strlen($mgh)>0) $this->margin_header=$mgh;
10230 if (strlen($mgf)>0) $this->margin_footer=$mgf;
10231 $this->ResetMargins();
10232 $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
10233 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
10234 $resetHTMLHeadersrequired = true;
10235 }
10236
10237 $this->ResetMargins();
10238 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
10239 $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
10240
10241 // Reset column top margin
10242 $this->y0 = $this->tMargin;
10243
10244 $this->x=$this->lMargin;
10245 $this->y=$this->tMargin;
10246 $this->FontFamily='';
10247
10248 // HEADERS AND FOOTERS // mPDF 6
10249 if ($ohvalue<0 || strtoupper($ohvalue)=='OFF') {
10250 $this->HTMLHeader = '';
10251 $resetHTMLHeadersrequired = true;
10252 }
10253 else if ($ohname && $ohvalue>0) {
10254 if (preg_match('/^html_(.*)$/i',$ohname,$n)) { $name = $n[1]; }
10255 else { $name = $ohname; }
10256 if (isset($this->pageHTMLheaders[$name])) { $this->HTMLHeader = $this->pageHTMLheaders[$name]; }
10257 else { $this->HTMLHeader = ''; }
10258 $resetHTMLHeadersrequired = true;
10259 }
10260
10261 if ($ehvalue<0 || strtoupper($ehvalue)=='OFF') {
10262 $this->HTMLHeaderE = '';
10263 $resetHTMLHeadersrequired = true;
10264 }
10265 else if ($ehname && $ehvalue>0) {
10266 if (preg_match('/^html_(.*)$/i',$ehname,$n)) { $name = $n[1]; }
10267 else { $name = $ehname; }
10268 if (isset($this->pageHTMLheaders[$name])) { $this->HTMLHeaderE = $this->pageHTMLheaders[$name]; }
10269 else { $this->HTMLHeaderE = ''; }
10270 $resetHTMLHeadersrequired = true;
10271 }
10272
10273 if ($ofvalue<0 || strtoupper($ofvalue)=='OFF') {
10274 $this->HTMLFooter = '';
10275 $resetHTMLHeadersrequired = true;
10276 }
10277 else if ($ofname && $ofvalue>0) {
10278 if (preg_match('/^html_(.*)$/i',$ofname,$n)) { $name = $n[1]; }
10279 else { $name = $ofname; }
10280 if (isset($this->pageHTMLfooters[$name])) { $this->HTMLFooter = $this->pageHTMLfooters[$name]; }
10281 else { $this->HTMLFooter = ''; }
10282 $resetHTMLHeadersrequired = true;
10283 }
10284
10285 if ($efvalue<0 || strtoupper($efvalue)=='OFF') {
10286 $this->HTMLFooterE = '';
10287 $resetHTMLHeadersrequired = true;
10288 }
10289 else if ($efname && $efvalue>0) {
10290 if (preg_match('/^html_(.*)$/i',$efname,$n)) { $name = $n[1]; }
10291 else { $name = $efname; }
10292 if (isset($this->pageHTMLfooters[$name])) { $this->HTMLFooterE = $this->pageHTMLfooters[$name]; }
10293 else { $this->HTMLFooterE = ''; }
10294 $resetHTMLHeadersrequired = true;
10295 }
10296 if ($resetHTMLHeadersrequired) {
10297 $this->SetHTMLHeader($this->HTMLHeader );
10298 $this->SetHTMLHeader($this->HTMLHeaderE ,'E');
10299 $this->SetHTMLFooter($this->HTMLFooter );
10300 $this->SetHTMLFooter($this->HTMLFooterE ,'E');
10301 }
10302
10303
10304 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
10305 $this->_setAutoHeaderHeight($this->HTMLHeaderE);
10306 $this->_setAutoFooterHeight($this->HTMLFooterE);
10307 }
10308 else { // ODD or DEFAULT
10309 $this->_setAutoHeaderHeight($this->HTMLHeader);
10310 $this->_setAutoFooterHeight($this->HTMLFooter);
10311 }
10312 // Reset column top margin
10313 $this->y0 = $this->tMargin;
10314
10315 $this->x=$this->lMargin;
10316 $this->y=$this->tMargin;
10317 }
10318
10319
10320 // mPDF 6
10321 function _setAutoHeaderHeight(&$htmlh) {
10322 if ($this->setAutoTopMargin=='pad') {
10323 if (isset($htmlh['h']) && $htmlh['h']) { $h = $htmlh['h']; } // 5.7.3
10324 else { $h = 0; }
10325 $this->tMargin = $this->margin_header + $h + $this->orig_tMargin;
10326 }
10327 else if ($this->setAutoTopMargin=='stretch') {
10328 if (isset($htmlh['h']) && $htmlh['h']) { $h = $htmlh['h']; } // 5.7.3
10329 else { $h = 0; }
10330 $this->tMargin = max($this->orig_tMargin, $this->margin_header + $h + $this->autoMarginPadding);
10331 }
10332 }
10333
10334
10335 // mPDF 6
10336 function _setAutoFooterHeight(&$htmlf) {
10337 if ($this->setAutoBottomMargin=='pad') {
10338 if (isset($htmlf['h']) && $htmlf['h']) { $h = $htmlf['h']; } // 5.7.3
10339 else { $h = 0; }
10340 $this->bMargin = $this->margin_footer + $h + $this->orig_bMargin;
10341 $this->PageBreakTrigger=$this->h-$this->bMargin ;
10342 }
10343 else if ($this->setAutoBottomMargin=='stretch') {
10344 if (isset($htmlf['h']) && $htmlf['h']) { $h = $htmlf['h']; } // 5.7.3
10345 else { $h = 0; }
10346 $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $h + $this->autoMarginPadding);
10347 $this->PageBreakTrigger=$this->h-$this->bMargin ;
10348 }
10349 }
10350
10351
10352 function _endpage() {
10353 /*-- CSS-IMAGE-FLOAT --*/
10354 $this->printfloatbuffer();
10355 /*-- END CSS-IMAGE-FLOAT --*/
10356
10357 if($this->visibility!='visible')
10358 $this->SetVisibility('visible');
10359 $this->EndLayer();
10360 //End of page contents
10361 $this->state=1;
10362 }
10363
10364 function _newobj($obj_id=false,$onlynewobj=false) {
10365 if (!$obj_id) {
10366 $obj_id = ++$this->n;
10367 }
10368 //Begin a new object
10369 if (!$onlynewobj) {
10370 $this->offsets[$obj_id] = strlen($this->buffer);
10371 $this->_out($obj_id.' 0 obj');
10372 $this->_current_obj_id = $obj_id; // for later use with encryption
10373 }
10374 }
10375
10376 function _dounderline($x,$y,$txt,$OTLdata=false,$textvar=0) {
10377 // Now print line exactly where $y secifies - called from Text() and Cell() - adjust position there
10378 // WORD SPACING
10379 $w =($this->GetStringWidth($txt,false,$OTLdata,$textvar)*_MPDFK) + ($this->charspacing * mb_strlen( $txt, $this->mb_enc ))
10380 + ( $this->ws * mb_substr_count( $txt, ' ', $this->mb_enc ));
10381 //Draw a line
10382 return sprintf('%.3F %.3F m %.3F %.3F l S',$x*_MPDFK,($this->h-$y)*_MPDFK,($x*_MPDFK)+$w,($this->h-$y)*_MPDFK);
10383 }
10384
10385
10386 function _imageError($file, $firsttime, $msg) {
10387 // Save re-trying image URL's which have already failed
10388 $this->failedimages[$file] = true;
10389 if ($firsttime && ($this->showImageErrors || $this->debug)) {
10390 $this->Error("IMAGE Error (".$file."): ".$msg);
10391 }
10392 return false;
10393 }
10394
10395
10396 function _getImage(&$file, $firsttime=true, $allowvector=true, $orig_srcpath=false, $interpolation=false) { // mPDF 6
10397 // firsttime i.e. whether to add to this->images - use false when calling iteratively
10398 // Image Data passed directly as var:varname
10399 if (preg_match('/var:\s*(.*)/',$file, $v)) {
10400 $data = $this->$v[1];
10401 $file = md5($data);
10402 }
10403 if (preg_match('/data:image\/(gif|jpeg|png);base64,(.*)/',$file, $v)) {
10404 $type = $v[1];
10405 $data = base64_decode($v[2]);
10406 $file = md5($data);
10407 }
10408
10409 // mPDF 5.7.4 URLs
10410 if ($firsttime && $file && substr($file,0,5)!='data:') { $file = str_replace(" ","%20",$file ); }
10411 if ($firsttime && $orig_srcpath) {
10412 // If orig_srcpath is a relative file path (and not a URL), then it needs to be URL decoded
10413 if (substr($orig_srcpath,0,5)!='data:') { $orig_srcpath = str_replace(" ","%20",$orig_srcpath); }
10414 if (!preg_match('/^(http|ftp)/',$orig_srcpath)) { $orig_srcpath = urldecode_parts($orig_srcpath ); }
10415 }
10416
10417 $ppUx = 0;
10418 if ($orig_srcpath && isset($this->images[$orig_srcpath])) { $file=$orig_srcpath; return $this->images[$orig_srcpath]; }
10419 if (isset($this->images[$file])) { return $this->images[$file]; }
10420 else if ($orig_srcpath && isset($this->formobjects[$orig_srcpath])) { $file=$orig_srcpath; return $this->formobjects[$file]; }
10421 else if (isset($this->formobjects[$file])) { return $this->formobjects[$file]; }
10422 // Save re-trying image URL's which have already failed
10423 else if ($firsttime && isset($this->failedimages[$file])) { return $this->_imageError($file, $firsttime, ''); }
10424 if (empty($data)) {
10425 $type = '';
10426 $data = '';
10427
10428 if ($orig_srcpath && $this->basepathIsLocal && $check = @fopen($orig_srcpath,"rb")) {
10429 fclose($check);
10430 $file=$orig_srcpath;
10431 $data = file_get_contents($file);
10432 $type = $this->_imageTypeFromString($data);
10433 }
10434 if (!$data && $check = @fopen($file,"rb")) {
10435 fclose($check);
10436 $data = file_get_contents($file);
10437 $type = $this->_imageTypeFromString($data);
10438 }
10439 if ((!$data || !$type) && !ini_get('allow_url_fopen') ) { // only worth trying if remote file and !ini_get('allow_url_fopen')
10440 $this->file_get_contents_by_socket($file, $data); // needs full url?? even on local (never needed for local)
10441 if ($data) { $type = $this->_imageTypeFromString($data); }
10442 }
10443 if ((!$data || !$type) && function_exists("curl_init")) { // mPDF 5.7.4
10444 $this->file_get_contents_by_curl($file, $data); // needs full url?? even on local (never needed for local)
10445 if ($data) { $type = $this->_imageTypeFromString($data); }
10446 }
10447
10448 }
10449 if (!$data) { return $this->_imageError($file, $firsttime, 'Could not find image file'); }
10450 if (empty($type)) { $type = $this->_imageTypeFromString($data); }
10451 if (($type == 'wmf' || $type == 'svg') && !$allowvector) { return $this->_imageError($file, $firsttime, 'WMF or SVG image file not supported in this context'); }
10452
10453 // SVG
10454 if ($type == 'svg') {
10455 if (!class_exists('SVG', false)) { include(_MPDF_PATH .'classes/svg.php'); }
10456 $svg = new SVG($this);
10457 $family=$this->FontFamily;
10458 $style=$this->FontStyle;
10459 $size=$this->FontSizePt;
10460 $info = $svg->ImageSVG($data);
10461 //Restore font
10462 if($family) $this->SetFont($family,$style,$size,false);
10463 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing SVG file'); }
10464 $info['type']='svg';
10465 $info['i']=count($this->formobjects)+1;
10466 $this->formobjects[$file]=$info;
10467 return $info;
10468 }
10469
10470 // JPEG
10471 if ($type == 'jpeg' || $type == 'jpg') {
10472 $hdr = $this->_jpgHeaderFromString($data);
10473 if (!$hdr) { return $this->_imageError($file, $firsttime, 'Error parsing JPG header'); }
10474 $a = $this->_jpgDataFromHeader($hdr);
10475 $channels = intval($a[4]);
10476 $j = strpos($data,'JFIF');
10477 if ($j) {
10478 //Read resolution
10479 $unitSp=ord(substr($data,($j+7),1));
10480 if ($unitSp > 0) {
10481 $ppUx=$this->_twobytes2int(substr($data,($j+8),2)); // horizontal pixels per meter, usually set to zero
10482 if ($unitSp == 2) { // = dots per cm (if == 1 set as dpi)
10483 $ppUx=round($ppUx/10 *25.4);
10484 }
10485 }
10486 }
10487 if ($a[2] == 'DeviceCMYK' && (($this->PDFA && $this->restrictColorSpace!=3) || $this->restrictColorSpace==2)) {
10488 // convert to RGB image
10489 if (!function_exists("gd_info")) { $this->Error("JPG image may not use CMYK color space (".$file.")."); }
10490 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.)"; }
10491 $im = @imagecreatefromstring($data);
10492 if ($im) {
10493 $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.md5($file).RAND(1,10000).'.png';
10494 imageinterlace($im, false);
10495 $check = @imagepng($im, $tempfile);
10496 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse JPG(CMYK) image'); }
10497 $info = $this->_getImage($tempfile, false);
10498 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse JPG(CMYK) image'); }
10499 imagedestroy($im);
10500 unlink($tempfile);
10501 $info['type']='jpg';
10502 if ($firsttime) {
10503 $info['i']=count($this->images)+1;
10504 $info['interpolation']=$interpolation; // mPDF 6
10505 $this->images[$file]=$info;
10506 }
10507 return $info;
10508 }
10509 else { return $this->_imageError($file, $firsttime, 'Error creating GD image file from JPG(CMYK) image'); }
10510 }
10511 else if ($a[2] == 'DeviceRGB' && ($this->PDFX || $this->restrictColorSpace==3)) {
10512 // Convert to CMYK image stream - nominally returned as type='png'
10513 $info = $this->_convImage($data, $a[2], 'DeviceCMYK', $a[0], $a[1], $ppUx, false);
10514 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.)"; }
10515 }
10516 else if (($a[2] == 'DeviceRGB' || $a[2] == 'DeviceCMYK') && $this->restrictColorSpace==1) {
10517 // Convert to Grayscale image stream - nominally returned as type='png'
10518 $info = $this->_convImage($data, $a[2], 'DeviceGray', $a[0], $a[1], $ppUx, false);
10519 }
10520 else {
10521
10522 // mPDF 6 Detect Adobe APP14 Tag
10523 //$pos = strpos($data, "\xFF\xEE\x00\x0EAdobe\0");
10524 //if ($pos !== false) {
10525 //}
10526
10527 // mPDF 6 ICC profile
10528 $offset = 0;
10529 $icc = array();
10530 while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) {
10531 // get ICC sequence length
10532 $length = $this->_twobytes2int(substr($data, ($pos - 2),2)) - 16;
10533 $sn = max(1, ord($data[($pos + 12)]));
10534 $nom = max(1, ord($data[($pos + 13)]));
10535 $icc[($sn - 1)] = substr($data, ($pos + 14), $length);
10536 $offset = ($pos + 14 + $length);
10537 }
10538 // order and compact ICC segments
10539 if (count($icc) > 0) {
10540 ksort($icc);
10541 $icc = implode('', $icc);
10542 if (substr($icc, 36, 4) != 'acsp') {
10543 // invalid ICC profile
10544 $icc = false;
10545 }
10546 $input = substr($icc, 16, 4);
10547 $output = substr($icc, 20, 4);
10548 // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
10549 if ($input != 'RGB ' || $output != 'XYZ ') { $icc = false; }
10550 }
10551 else { $icc = false; }
10552
10553 $info = array('w'=>$a[0],'h'=>$a[1],'cs'=>$a[2],'bpc'=>$a[3],'f'=>'DCTDecode','data'=>$data, 'type'=>'jpg', 'ch' => $channels, 'icc' => $icc);
10554 if ($ppUx) { $info['set-dpi'] = $ppUx; }
10555 }
10556 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing or converting JPG image'); }
10557 if ($firsttime) {
10558 $info['i']=count($this->images)+1;
10559 $info['interpolation']=$interpolation; // mPDF 6
10560 $this->images[$file]=$info;
10561 }
10562 return $info;
10563 }
10564
10565 // PNG
10566 else if ($type == 'png') {
10567 //Check signature
10568 if(substr($data,0,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
10569 return $this->_imageError($file, $firsttime, 'Error parsing PNG identifier');
10570 }
10571 //Read header chunk
10572 if(substr($data,12,4)!='IHDR') {
10573 return $this->_imageError($file, $firsttime, 'Incorrect PNG file (no IHDR block found)');
10574 }
10575
10576 $w=$this->_fourbytes2int(substr($data,16,4));
10577 $h=$this->_fourbytes2int(substr($data,20,4));
10578 $bpc=ord(substr($data,24,1));
10579 $errpng = false;
10580 $pngalpha = false;
10581 $channels = 0;
10582
10583 // if($bpc>8) { $errpng = 'not 8-bit depth'; } // mPDF 6 Allow through to be handled as native PNG
10584
10585 $ct=ord(substr($data,25,1));
10586 if($ct==0) { $colspace='DeviceGray'; $channels = 1; }
10587 elseif($ct==2) { $colspace='DeviceRGB'; $channels = 3; }
10588 elseif($ct==3) { $colspace='Indexed'; $channels = 1; }
10589 elseif($ct==4) { $colspace='DeviceGray'; $channels = 1; $errpng = 'alpha channel'; $pngalpha = true; }
10590 else { $colspace='DeviceRGB'; $channels = 3; $errpng = 'alpha channel'; $pngalpha = true; }
10591
10592 if ($ct < 4 && strpos($data,'tRNS')!==false) { $errpng = 'transparency'; $pngalpha = true; } // mPDF 6
10593
10594 if ($ct == 3 && strpos($data,'iCCP')!==false) { $errpng = 'indexed plus ICC'; } // mPDF 6
10595
10596 // $pngalpha is used as a FLAG of any kind of transparency which COULD be tranferred to an alpha channel
10597 // incl. single-color tarnsparency, depending which type of handling occurs later
10598
10599 if(ord(substr($data,26,1))!=0) { $errpng = 'compression method'; } // only 0 should be specified
10600 if(ord(substr($data,27,1))!=0) { $errpng = 'filter method'; } // only 0 should be specified
10601 if(ord(substr($data,28,1))!=0) { $errpng = 'interlaced file'; }
10602
10603 $j = strpos($data,'pHYs');
10604 if ($j) {
10605 //Read resolution
10606 $unitSp=ord(substr($data,($j+12),1));
10607 if ($unitSp == 1) {
10608 $ppUx=$this->_fourbytes2int(substr($data,($j+4),4)); // horizontal pixels per meter, usually set to zero
10609 $ppUx=round($ppUx/1000 *25.4);
10610 }
10611 }
10612
10613 // mPDF 6 Gamma correction
10614 $gamma_correction = 0;
10615 $gAMA = 0;
10616 $j = strpos($data,'gAMA');
10617 if ($j && strpos($data,'sRGB')===false) { // sRGB colorspace - overrides gAMA
10618 $gAMA=$this->_fourbytes2int(substr($data,($j+4),4)); // Gamma value times 100000
10619 $gAMA /= 100000;
10620
10621 // http://www.libpng.org/pub/png/spec/1.2/PNG-Encoders.html
10622 // "If the source file's gamma value is greater than 1.0, it is probably a display system exponent,..."
10623 // ("..and you should use its reciprocal for the PNG gamma.")
10624 //if ($gAMA > 1) { $gAMA = 1/$gAMA; }
10625 // (Some) Applications seem to ignore it... appearing how it was probably intended
10626 // Test Case - image(s) on http://www.w3.org/TR/CSS21/intro.html - PNG has gAMA set as 1.45454
10627 // Probably unintentional as mentioned above and should be 0.45454 which is 1 / 2.2
10628 // Tested on Windows PC
10629 // Firefox and Opera display gray as 234 (correct, but looks wrong)
10630 // IE9 and Safari display gray as 193 (incorrect but looks right)
10631 // See test different gamma chunks at http://www.libpng.org/pub/png/pngsuite-all-good.html
10632 }
10633
10634 if ($gAMA) { $gamma_correction = 1/$gAMA; }
10635
10636 // Don't need to apply gamma correction if == default i.e. 2.2
10637 if ($gamma_correction > 2.15 && $gamma_correction < 2.25) { $gamma_correction = 0; }
10638
10639 // NOT supported at present
10640 //$j = strpos($data,'sRGB'); // sRGB colorspace - overrides gAMA
10641 //$j = strpos($data,'cHRM'); // Chromaticity and Whitepoint
10642
10643 // $firsttime added mPDF 6 so when PNG Grayscale with alpha using resrtictcolorspace to CMYK
10644 // the alpha channel is sent through as secondtime as Indexed and should not be converted to CMYK
10645 if ($firsttime && ($colspace == 'DeviceRGB' || $colspace == 'Indexed') && ($this->PDFX || $this->restrictColorSpace==3)) {
10646 // Convert to CMYK image stream - nominally returned as type='png'
10647 $info = $this->_convImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha, $gamma_correction, $ct); // mPDF 5.7.2 Gamma correction
10648 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.)"; }
10649 }
10650 // $firsttime added mPDF 6 so when PNG Grayscale with alpha using resrtictcolorspace to CMYK
10651 // the alpha channel is sent through as secondtime as Indexed and should not be converted to CMYK
10652 else if ($firsttime && ($colspace == 'DeviceRGB' || $colspace == 'Indexed') && $this->restrictColorSpace==1) {
10653 // Convert to Grayscale image stream - nominally returned as type='png'
10654 $info = $this->_convImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha, $gamma_correction, $ct); // mPDF 5.7.2 Gamma correction
10655 }
10656 else if (($this->PDFA || $this->PDFX) && $pngalpha) {
10657
10658 // Remove alpha channel
10659 if ($this->restrictColorSpace==1) { // Grayscale
10660 $info = $this->_convImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha, $gamma_correction, $ct); // mPDF 5.7.2 Gamma correction
10661 }
10662 else if ($this->restrictColorSpace==3) { // CMYK
10663 $info = $this->_convImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha, $gamma_correction, $ct); // mPDF 5.7.2 Gamma correction
10664 }
10665 else if ($this->PDFA ) { // RGB
10666 $info = $this->_convImage($data, $colspace, 'DeviceRGB', $w, $h, $ppUx, $pngalpha, $gamma_correction, $ct); // mPDF 5.7.2 Gamma correction
10667 }
10668 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.)"; }
10669 }
10670 else if ($firsttime && ($errpng || $pngalpha || $gamma_correction)) { // mPDF 5.7.2 Gamma correction
10671 if (function_exists('gd_info')) { $gd = gd_info(); }
10672 else {$gd = array(); }
10673 if (!isset($gd['PNG Support'])) { return $this->_imageError($file, $firsttime, 'GD library required for PNG image ('.$errpng.')'); }
10674 $im = imagecreatefromstring($data);
10675
10676 if (!$im) { return $this->_imageError($file, $firsttime, 'Error creating GD image from PNG file ('.$errpng.')'); }
10677 $w = imagesx($im);
10678 $h = imagesy($im);
10679 if ($im) {
10680 $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.md5($file).RAND(1,10000).'.png';
10681
10682 // Alpha channel set (including using tRNS for Paletted images)
10683 if ($pngalpha) {
10684 if ($this->PDFA) { $this->Error("PDFA1-b does not permit images with alpha channel transparency (".$file.")."); }
10685
10686 $imgalpha = imagecreate($w, $h);
10687 // generate gray scale pallete
10688 for ($c = 0; $c < 256; ++$c) { imagecolorallocate($imgalpha, $c, $c, $c); }
10689
10690 // mPDF 6
10691 if ($colspace=='Indexed') { // generate Alpha channel values from tRNS
10692 //Read transparency info
10693 $transparency = '';
10694 $p = strpos($data,'tRNS');
10695 if ($p) {
10696 $n=$this->_fourbytes2int(substr($data,($p-4),4));
10697 $transparency = substr($data,($p+4),$n);
10698 // ord($transparency{$index}) = the alpha value for that index
10699 // generate alpha channel
10700 for ($ypx = 0; $ypx < $h; ++$ypx) {
10701 for ($xpx = 0; $xpx < $w; ++$xpx) {
10702 $colorindex = imagecolorat($im, $xpx, $ypx);
10703 if ($colorindex >= $n) { $alpha = 255; }
10704 else { $alpha = ord($transparency{$colorindex}); } // 0-255
10705 if ($alpha > 0) {
10706 imagesetpixel($imgalpha, $xpx, $ypx, $alpha);
10707 }
10708 }
10709 }
10710 }
10711 }
10712 else if ($ct===0 || $ct==2) { // generate Alpha channel values from tRNS
10713 // Get transparency as array of RGB
10714 $p = strpos($data,'tRNS');
10715 if ($p) {
10716 $trns = '';
10717 $n=$this->_fourbytes2int(substr($data,($p-4),4));
10718 $t = substr($data,($p+4),$n);
10719 if ($colspace=='DeviceGray') { // ct===0
10720 $trns=array($this->_trnsvalue(substr($t,0,2), $bpc));
10721 }
10722 else /* $colspace=='DeviceRGB' */ { // ct==2
10723 $trns=array();
10724 $trns[0]=$this->_trnsvalue(substr($t,0,2), $bpc);
10725 $trns[1]=$this->_trnsvalue(substr($t,2,2), $bpc);
10726 $trns[2]=$this->_trnsvalue(substr($t,4,2), $bpc);
10727 }
10728
10729 // generate alpha channel
10730 for ($ypx = 0; $ypx < $h; ++$ypx) {
10731 for ($xpx = 0; $xpx < $w; ++$xpx) {
10732 $rgb = imagecolorat($im, $xpx, $ypx);
10733 $r = ($rgb >> 16) & 0xFF;
10734 $g = ($rgb >> 8) & 0xFF;
10735 $b = $rgb & 0xFF;
10736 if ($colspace=='DeviceGray' && $b==$trns[0]) { $alpha = 0; }
10737 else if ($r==$trns[0] && $g==$trns[1] && $b==$trns[2]) { $alpha = 0; } // ct==2
10738 else { $alpha = 255; }
10739 if ($alpha > 0) {
10740 imagesetpixel($imgalpha, $xpx, $ypx, $alpha);
10741 }
10742 }
10743 }
10744 }
10745 }
10746 else {
10747 // extract alpha channel
10748 for ($ypx = 0; $ypx < $h; ++$ypx) {
10749 for ($xpx = 0; $xpx < $w; ++$xpx) {
10750 $alpha = (imagecolorat($im, $xpx, $ypx) & 0x7F000000) >> 24;
10751 if ($alpha < 127) {
10752 imagesetpixel($imgalpha, $xpx, $ypx, (255-($alpha * 2)));
10753 }
10754 }
10755 }
10756 }
10757
10758
10759 // NB This must happen after the Alpha channel is extracted
10760 // imagegammacorrect() removes the alpha channel data in $im - (I think this is a bug in PHP)
10761 if ($gamma_correction) { imagegammacorrect($im, $gamma_correction, 2.2); } // mPDF 6 Gamma correction
10762
10763 // create temp alpha file
10764 $tempfile_alpha = _MPDF_TEMP_PATH.'_tempMskPNG'.md5($file).RAND(1,10000).'.png';
10765 if (!is_writable(_MPDF_TEMP_PATH)) { // mPDF 5.7.2
10766 ob_start();
10767 $check = @imagepng($imgalpha);
10768 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
10769 imagedestroy($imgalpha);
10770 $this->_tempimg = ob_get_contents();
10771 $this->_tempimglnk = 'var:_tempimg';
10772 ob_end_clean();
10773 // extract image without alpha channel
10774 $imgplain = imagecreatetruecolor($w, $h);
10775 imagealphablending( $imgplain, false ); // mPDF 5.7.2
10776 imagecopy($imgplain, $im, 0, 0, 0, 0, $w, $h);
10777 // create temp image file
10778 $minfo = $this->_getImage($this->_tempimglnk, false);
10779 if (!$minfo) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
10780 ob_start();
10781 $check = @imagepng($imgplain);
10782 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
10783 $this->_tempimg = ob_get_contents();
10784 $this->_tempimglnk = 'var:_tempimg';
10785 ob_end_clean();
10786 $info = $this->_getImage($this->_tempimglnk, false);
10787 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
10788 imagedestroy($imgplain);
10789 $imgmask = count($this->images)+1;
10790 $minfo['cs'] = 'DeviceGray';
10791 $minfo['i']=$imgmask ;
10792 $this->images[$tempfile_alpha] = $minfo;
10793 }
10794 else {
10795 $check = @imagepng($imgalpha, $tempfile_alpha);
10796 if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile_alpha.') parsing PNG image with alpha channel ('.$errpng.')'); }
10797 imagedestroy($imgalpha);
10798 // extract image without alpha channel
10799 $imgplain = imagecreatetruecolor($w, $h);
10800 imagealphablending( $imgplain, false ); // mPDF 5.7.2
10801 imagecopy($imgplain, $im, 0, 0, 0, 0, $w, $h);
10802
10803 // create temp image file
10804 $check = @imagepng($imgplain, $tempfile);
10805 if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile.') parsing PNG image with alpha channel ('.$errpng.')'); }
10806 imagedestroy($imgplain);
10807 // embed mask image
10808 $minfo = $this->_getImage($tempfile_alpha, false);
10809 unlink($tempfile_alpha);
10810 if (!$minfo) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile_alpha.') created with GD library to parse PNG image'); }
10811 $imgmask = count($this->images)+1;
10812 $minfo['cs'] = 'DeviceGray';
10813 $minfo['i']=$imgmask ;
10814 $this->images[$tempfile_alpha] = $minfo;
10815 // embed image, masked with previously embedded mask
10816 $info = $this->_getImage($tempfile, false);
10817 unlink($tempfile);
10818 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse PNG image'); }
10819
10820 }
10821 $info['masked'] = $imgmask;
10822 if ($ppUx) { $info['set-dpi'] = $ppUx; }
10823 $info['type']='png';
10824 if ($firsttime) {
10825 $info['i']=count($this->images)+1;
10826 $info['interpolation']=$interpolation; // mPDF 6
10827 $this->images[$file]=$info;
10828 }
10829
10830 return $info;
10831 }
10832 else { // No alpha/transparency set (but cannot read directly because e.g. bit-depth != 8, interlaced etc)
10833
10834 // ICC profile
10835 $icc = false;
10836 $p = strpos($data,'iCCP');
10837 if ($p && $colspace=="Indexed") { // Cannot have ICC profile and Indexed together
10838 $p += 4;
10839 $n=$this->_fourbytes2int(substr($data,($p-8),4));
10840 $nullsep = strpos(substr($data,$p,80), chr(0));
10841 $icc = substr($data, ($p+$nullsep+2), ($n-($nullsep+2)) );
10842 $icc = @gzuncompress($icc); // Ignored if fails
10843 if ($icc) {
10844 if (substr($icc, 36, 4) != 'acsp') { $icc = false; } // invalid ICC profile
10845 else {
10846 $input = substr($icc, 16, 4);
10847 $output = substr($icc, 20, 4);
10848 // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
10849 if ($input != 'RGB ' || $output != 'XYZ ') { $icc = false; }
10850 }
10851 }
10852 // Convert to RGB colorspace so can use ICC Profile
10853 if ($icc) { imagepalettetotruecolor($im); $colspace = 'DeviceRGB'; $channels = 3;}
10854 }
10855
10856 if ($gamma_correction) { imagegammacorrect($im, $gamma_correction, 2.2); } // mPDF 6 Gamma correction
10857 imagealphablending($im, false);
10858 imagesavealpha($im, false);
10859 imageinterlace($im, false);
10860 if (!is_writable(_MPDF_TEMP_PATH)) { // mPDF 5.7.2
10861 ob_start();
10862 $check = @imagepng($im);
10863 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
10864 $this->_tempimg = ob_get_contents();
10865 $this->_tempimglnk = 'var:_tempimg';
10866 ob_end_clean();
10867 $info = $this->_getImage($this->_tempimglnk, false);
10868 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
10869 imagedestroy($im);
10870 }
10871 else {
10872 $check = @imagepng($im, $tempfile );
10873 if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile.') parsing PNG image ('.$errpng.')'); }
10874 imagedestroy($im);
10875 $info = $this->_getImage($tempfile, false) ;
10876 unlink($tempfile );
10877 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse PNG image'); }
10878 }
10879 if ($ppUx) { $info['set-dpi'] = $ppUx; }
10880 $info['type']='png';
10881 if ($firsttime) {
10882 $info['i']=count($this->images)+1;
10883 $info['interpolation']=$interpolation; // mPDF 6
10884 if ($icc) { $info['ch'] = $channels; $info['icc'] = $icc; }
10885 $this->images[$file]=$info;
10886 }
10887 return $info;
10888 }
10889 }
10890 }
10891
10892 else { // PNG image with no need to convert alph channels, bpc <> 8 etc.
10893 $parms='/DecodeParms <</Predictor 15 /Colors '.$channels.' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
10894 //Scan chunks looking for palette, transparency and image data
10895 $pal='';
10896 $trns='';
10897 $pngdata='';
10898 $icc = false;
10899 $p = 33;
10900 do {
10901 $n=$this->_fourbytes2int(substr($data,$p,4)); $p += 4;
10902 $type=substr($data,$p,4); $p += 4;
10903 if ($type=='PLTE') {
10904 //Read palette
10905 $pal=substr($data,$p,$n); $p += $n;
10906 $p += 4;
10907 }
10908 else if($type=='tRNS') {
10909 //Read transparency info
10910 $t=substr($data,$p,$n); $p += $n;
10911 if ($ct==0) $trns=array(ord(substr($t,1,1)));
10912 else if ($ct==2) $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
10913 else {
10914 $pos=strpos($t,chr(0));
10915 if(is_int($pos)) $trns=array($pos);
10916 }
10917 $p += 4;
10918 }
10919 else if ($type=='IDAT') {
10920 $pngdata.=substr($data,$p,$n); $p += $n;
10921 $p += 4;
10922 }
10923 else if ($type=='iCCP') {
10924 $nullsep = strpos(substr($data,$p,80), chr(0));
10925 $icc = substr($data, ($p+$nullsep+2), ($n-($nullsep+2)) );
10926 $icc = @gzuncompress($icc); // Ignored if fails
10927 if ($icc) {
10928 if (substr($icc, 36, 4) != 'acsp') { $icc = false; } // invalid ICC profile
10929 else {
10930 $input = substr($icc, 16, 4);
10931 $output = substr($icc, 20, 4);
10932 // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
10933 if ($input != 'RGB ' || $output != 'XYZ ') { $icc = false; }
10934 }
10935 }
10936 $p += $n;
10937 $p += 4;
10938 }
10939 else if($type=='IEND') { break; }
10940 else if (preg_match('/[a-zA-Z]{4}/',$type)) { $p += $n+4; }
10941 else { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data'); }
10942 }
10943 while($n);
10944 if (!$pngdata) { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data - no IDAT data found'); }
10945 if ($colspace=='Indexed' && empty($pal)) { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data - missing colour palette'); }
10946
10947 if ($colspace=='Indexed' && $icc) { $icc = false; } // mPDF 6 cannot have ICC profile and Indexed in a PDF document as both use the colorspace tag.
10948
10949 $info = array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$pngdata, 'ch' => $channels, 'icc' => $icc);
10950 $info['type']='png';
10951 if ($ppUx) { $info['set-dpi'] = $ppUx; }
10952 }
10953
10954 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing or converting PNG image'); }
10955
10956 if ($firsttime) {
10957 $info['i']=count($this->images)+1;
10958 $info['interpolation']=$interpolation; // mPDF 6
10959 $this->images[$file]=$info;
10960 }
10961 return $info;
10962 }
10963
10964 // GIF
10965 else if ($type == 'gif') {
10966 if (function_exists('gd_info')) { $gd = gd_info(); }
10967 else {$gd = array(); }
10968 if (isset($gd['GIF Read Support']) && $gd['GIF Read Support']) {
10969 $im = @imagecreatefromstring($data);
10970 if ($im) {
10971 $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.md5($file).RAND(1,10000).'.png';
10972 imagealphablending($im, false);
10973 imagesavealpha($im, false);
10974 imageinterlace($im, false);
10975 if (!is_writable($tempfile)) {
10976 ob_start();
10977 $check = @imagepng($im);
10978 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse GIF image'); }
10979 $this->_tempimg = ob_get_contents();
10980 $this->_tempimglnk = 'var:_tempimg';
10981 ob_end_clean();
10982 $info = $this->_getImage($this->_tempimglnk, false);
10983 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse GIF image'); }
10984 imagedestroy($im);
10985 }
10986 else {
10987 $check = @imagepng($im, $tempfile);
10988 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse GIF image'); }
10989 $info = $this->_getImage($tempfile, false);
10990 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse GIF image'); }
10991 imagedestroy($im);
10992 unlink($tempfile);
10993 }
10994 $info['type']='gif';
10995 if ($firsttime) {
10996 $info['i']=count($this->images)+1;
10997 $info['interpolation']=$interpolation; // mPDF 6
10998 $this->images[$file]=$info;
10999 }
11000 return $info;
11001 }
11002 else { return $this->_imageError($file, $firsttime, 'Error creating GD image file from GIF image'); }
11003 }
11004
11005 if (!class_exists('gif', false)) {
11006 include_once(_MPDF_PATH.'classes/gif.php');
11007 }
11008 $gif=new CGIF();
11009
11010 $h=0;
11011 $w=0;
11012 $gif->loadFile($data, 0);
11013
11014 if(isset($gif->m_img->m_gih->m_bLocalClr) && $gif->m_img->m_gih->m_bLocalClr) {
11015 $nColors = $gif->m_img->m_gih->m_nTableSize;
11016 $pal = $gif->m_img->m_gih->m_colorTable->toString();
11017 if((isset($bgColor)) and $bgColor != -1) { // mPDF 5.7.3
11018 $bgColor = $gif->m_img->m_gih->m_colorTable->colorIndex($bgColor);
11019 }
11020 $colspace='Indexed';
11021 } elseif(isset($gif->m_gfh->m_bGlobalClr) && $gif->m_gfh->m_bGlobalClr) {
11022 $nColors = $gif->m_gfh->m_nTableSize;
11023 $pal = $gif->m_gfh->m_colorTable->toString();
11024 if((isset($bgColor)) and $bgColor != -1) {
11025 $bgColor = $gif->m_gfh->m_colorTable->colorIndex($bgColor);
11026 }
11027 $colspace='Indexed';
11028 } else {
11029 $nColors = 0;
11030 $bgColor = -1;
11031 $colspace='DeviceGray';
11032 $pal='';
11033 }
11034
11035 $trns='';
11036 if(isset($gif->m_img->m_bTrans) && $gif->m_img->m_bTrans && ($nColors > 0)) {
11037 $trns=array($gif->m_img->m_nTrans);
11038 }
11039 $gifdata=$gif->m_img->m_data;
11040 $w=$gif->m_gfh->m_nWidth;
11041 $h=$gif->m_gfh->m_nHeight;
11042 $gif->ClearData();
11043
11044 if($colspace=='Indexed' and empty($pal)) {
11045 return $this->_imageError($file, $firsttime, 'Error parsing GIF image - missing colour palette');
11046 }
11047 if ($this->compress) {
11048 $gifdata=gzcompress($gifdata);
11049 $info = array( 'w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>8, 'f'=>'FlateDecode', 'pal'=>$pal, 'trns'=>$trns, 'data'=>$gifdata);
11050 }
11051 else {
11052 $info = array( 'w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>8, 'pal'=>$pal, 'trns'=>$trns, 'data'=>$gifdata);
11053 }
11054 $info['type']='gif';
11055 if ($firsttime) {
11056 $info['i']=count($this->images)+1;
11057 $info['interpolation']=$interpolation; // mPDF 6
11058 $this->images[$file]=$info;
11059 }
11060 return $info;
11061 }
11062
11063 /*-- IMAGES-BMP --*/
11064 // BMP (Windows Bitmap)
11065 else if ($type == 'bmp') {
11066 if (!class_exists('bmp', false)) { include(_MPDF_PATH.'classes/bmp.php'); }
11067 if (empty($this->bmp)) { $this->bmp = new bmp($this); }
11068 $info = $this->bmp->_getBMPimage($data, $file);
11069 if (isset($info['error'])) {
11070 return $this->_imageError($file, $firsttime, $info['error']);
11071 }
11072 if ($firsttime) {
11073 $info['i']=count($this->images)+1;
11074 $info['interpolation']=$interpolation; // mPDF 6
11075 $this->images[$file]=$info;
11076 }
11077 return $info;
11078 }
11079 /*-- END IMAGES-BMP --*/
11080 /*-- IMAGES-WMF --*/
11081 // WMF
11082 else if ($type == 'wmf') {
11083 if (!class_exists('wmf', false)) { include(_MPDF_PATH.'classes/wmf.php'); }
11084 if (empty($this->wmf)) { $this->wmf = new wmf($this); }
11085 $wmfres = $this->wmf->_getWMFimage($data);
11086 if ($wmfres[0]==0) {
11087 if ($wmfres[1]) { return $this->_imageError($file, $firsttime, $wmfres[1]); }
11088 return $this->_imageError($file, $firsttime, 'Error parsing WMF image');
11089 }
11090 $info = array('x'=>$wmfres[2][0],'y'=>$wmfres[2][1],'w'=>$wmfres[3][0],'h'=>$wmfres[3][1],'data'=>$wmfres[1]);
11091 $info['i']=count($this->formobjects)+1;
11092 $info['type']='wmf';
11093 $this->formobjects[$file]=$info;
11094 return $info;
11095 }
11096 /*-- END IMAGES-WMF --*/
11097
11098 // UNKNOWN TYPE - try GD imagecreatefromstring
11099 else {
11100 if (function_exists('gd_info')) { $gd = gd_info(); }
11101 else {$gd = array(); }
11102 if (isset($gd['PNG Support']) && $gd['PNG Support']) {
11103 $im = @imagecreatefromstring($data);
11104 if (!$im) { return $this->_imageError($file, $firsttime, 'Error parsing image file - image type not recognised, and not supported by GD imagecreate'); }
11105 $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.md5($file).RAND(1,10000).'.png';
11106 imagealphablending($im, false);
11107 imagesavealpha($im, false);
11108 imageinterlace($im, false);
11109 $check = @imagepng($im, $tempfile);
11110 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse unknown image type'); }
11111 $info = $this->_getImage($tempfile, false);
11112 imagedestroy($im);
11113 unlink($tempfile);
11114 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse unknown image type'); }
11115 $info['type']='png';
11116 if ($firsttime) {
11117 $info['i']=count($this->images)+1;
11118 $info['interpolation']=$interpolation; // mPDF 6
11119 $this->images[$file]=$info;
11120 }
11121 return $info;
11122 }
11123 }
11124
11125 return $this->_imageError($file, $firsttime, 'Error parsing image file - image type not recognised');
11126 }
11127 //==============================================================
11128 function _convImage(&$data, $colspace, $targetcs, $w, $h, $dpi, $mask, $gamma_correction=false, $pngcolortype=false) { // mPDF 5.7.2 Gamma correction
11129 if ($this->PDFA || $this->PDFX) { $mask=false; }
11130 $im = @imagecreatefromstring($data);
11131 $info = array();
11132 $bpc=ord(substr($data,24,1));
11133 if ($im) {
11134
11135 $imgdata = '';
11136 $mimgdata = '';
11137 $minfo = array();
11138
11139 // mPDF 6 Gamma correction
11140 // Need to extract alpha channel info before imagegammacorrect (which loses the data)
11141 if ($mask) { // i.e. $pngalpha for PNG
11142 // mPDF 6
11143 if ($colspace=='Indexed') { // generate Alpha channel values from tRNS - only from PNG
11144 //Read transparency info
11145 $transparency = '';
11146 $p = strpos($data,'tRNS');
11147 if ($p) {
11148 $n=$this->_fourbytes2int(substr($data,($p-4),4));
11149 $transparency = substr($data,($p+4),$n);
11150 // ord($transparency{$index}) = the alpha value for that index
11151 // generate alpha channel
11152 for ($ypx = 0; $ypx < $h; ++$ypx) {
11153 for ($xpx = 0; $xpx < $w; ++$xpx) {
11154 $colorindex = imagecolorat($im, $xpx, $ypx);
11155 if ($colorindex >= $n) { $alpha = 255; }
11156 else { $alpha = ord($transparency{$colorindex}); } // 0-255
11157 $mimgdata .= chr($alpha);
11158 }
11159 }
11160 }
11161 }
11162 else if ($pngcolortype===0 || $pngcolortype==2) { // generate Alpha channel values from tRNS
11163 // Get transparency as array of RGB
11164 $p = strpos($data,'tRNS');
11165 if ($p) {
11166 $trns = '';
11167 $n=$this->_fourbytes2int(substr($data,($p-4),4));
11168 $t = substr($data,($p+4),$n);
11169 if ($colspace=='DeviceGray') { // ct===0
11170 $trns=array($this->_trnsvalue(substr($t,0,2), $bpc));
11171 }
11172 else /* $colspace=='DeviceRGB' */ { // ct==2
11173 $trns=array();
11174 $trns[0]=$this->_trnsvalue(substr($t,0,2), $bpc);
11175 $trns[1]=$this->_trnsvalue(substr($t,2,2), $bpc);
11176 $trns[2]=$this->_trnsvalue(substr($t,4,2), $bpc);
11177 }
11178
11179 // generate alpha channel
11180 for ($ypx = 0; $ypx < $h; ++$ypx) {
11181 for ($xpx = 0; $xpx < $w; ++$xpx) {
11182 $rgb = imagecolorat($im, $xpx, $ypx);
11183 $r = ($rgb >> 16) & 0xFF;
11184 $g = ($rgb >> 8) & 0xFF;
11185 $b = $rgb & 0xFF;
11186 if ($colspace=='DeviceGray' && $b==$trns[0]) { $alpha = 0; }
11187 else if ($r==$trns[0] && $g==$trns[1] && $b==$trns[2]) { $alpha = 0; } // ct==2
11188 else { $alpha = 255; }
11189 $mimgdata .= chr($alpha);
11190 }
11191 }
11192 }
11193 }
11194 else {
11195 for ($i = 0; $i < $h; $i++) {
11196 for ($j = 0; $j < $w; $j++) {
11197 $rgb = imagecolorat($im, $j, $i);
11198 $alpha = ($rgb & 0x7F000000) >> 24;
11199 if ($alpha < 127) { $mimgdata .= chr(255-($alpha * 2)); }
11200 else { $mimgdata .= chr(0); }
11201 }
11202 }
11203 }
11204 }
11205
11206 if ($gamma_correction) { imagegammacorrect($im, $gamma_correction, 2.2); } // mPDF 6 Gamma correction
11207
11208 //Read transparency info
11209 $trns=array();
11210 $trnsrgb = false;
11211 if (!$this->PDFA && !$this->PDFX && !$mask) { // mPDF 6 added NOT mask
11212 $p = strpos($data,'tRNS');
11213 if ($p) {
11214 $n=$this->_fourbytes2int(substr($data,($p-4),4));
11215 $t = substr($data,($p+4),$n);
11216 if ($colspace=='DeviceGray') { // ct===0
11217 $trns=array($this->_trnsvalue(substr($t,0,2), $bpc));
11218 }
11219 else if ($colspace=='DeviceRGB') { // ct==2
11220 $trns[0]=$this->_trnsvalue(substr($t,0,2), $bpc);
11221 $trns[1]=$this->_trnsvalue(substr($t,2,2), $bpc);
11222 $trns[2]=$this->_trnsvalue(substr($t,4,2), $bpc);
11223 $trnsrgb = $trns;
11224 if ($targetcs=='DeviceCMYK') {
11225 $col = $this->rgb2cmyk(array(3,$trns[0],$trns[1],$trns[2]));
11226 $c1 = intval($col[1]*2.55);
11227 $c2 = intval($col[2]*2.55);
11228 $c3 = intval($col[3]*2.55);
11229 $c4 = intval($col[4]*2.55);
11230 $trns = array($c1,$c2,$c3,$c4);
11231 }
11232 else if ($targetcs=='DeviceGray') {
11233 $c = intval(($trns[0] * .21) + ($trns[1] * .71) + ($trns[2] * .07));
11234 $trns = array($c);
11235 }
11236 }
11237 else { // Indexed
11238 $pos = strpos($t,chr(0));
11239 if (is_int($pos)) {
11240 $pal = imagecolorsforindex($im, $pos);
11241 $r = $pal['red'];
11242 $g = $pal['green'];
11243 $b = $pal['blue'];
11244 $trns=array($r,$g,$b); // ****
11245 $trnsrgb = $trns;
11246 if ($targetcs=='DeviceCMYK') {
11247 $col = $this->rgb2cmyk(array(3,$r,$g,$b));
11248 $c1 = intval($col[1]*2.55);
11249 $c2 = intval($col[2]*2.55);
11250 $c3 = intval($col[3]*2.55);
11251 $c4 = intval($col[4]*2.55);
11252 $trns = array($c1,$c2,$c3,$c4);
11253 }
11254 else if ($targetcs=='DeviceGray') {
11255 $c = intval(($r * .21) + ($g * .71) + ($b * .07));
11256 $trns = array($c);
11257 }
11258 }
11259 }
11260 }
11261 }
11262 for ($i = 0; $i < $h; $i++) {
11263 for ($j = 0; $j < $w; $j++) {
11264 $rgb = imagecolorat($im, $j, $i);
11265 $r = ($rgb >> 16) & 0xFF;
11266 $g = ($rgb >> 8) & 0xFF;
11267 $b = $rgb & 0xFF;
11268 if ($colspace=='Indexed') {
11269 $pal = imagecolorsforindex($im, $rgb);
11270 $r = $pal['red'];
11271 $g = $pal['green'];
11272 $b = $pal['blue'];
11273 }
11274
11275 if ($targetcs=='DeviceCMYK') {
11276 $col = $this->rgb2cmyk(array(3,$r,$g,$b));
11277 $c1 = intval($col[1]*2.55);
11278 $c2 = intval($col[2]*2.55);
11279 $c3 = intval($col[3]*2.55);
11280 $c4 = intval($col[4]*2.55);
11281 if ($trnsrgb) {
11282 // original pixel was not set as transparent but processed color does match
11283 if ($trnsrgb!=array($r,$g,$b) && $trns==array($c1,$c2,$c3,$c4)) {
11284 if ($c4==0) { $c4=1; } else { $c4--; }
11285 }
11286 }
11287 $imgdata .= chr($c1).chr($c2).chr($c3).chr($c4);
11288 }
11289 else if ($targetcs=='DeviceGray') {
11290 $c = intval(($r * .21) + ($g * .71) + ($b * .07));
11291 if ($trnsrgb) {
11292 // original pixel was not set as transparent but processed color does match
11293 if ($trnsrgb!=array($r,$g,$b) && $trns==array($c)) {
11294 if ($c==0) { $c=1; } else { $c--; }
11295 }
11296 }
11297 $imgdata .= chr($c);
11298 }
11299 else if ($targetcs=='DeviceRGB') {
11300 $imgdata .= chr($r).chr($g).chr($b);
11301 }
11302 }
11303 }
11304
11305 if ($targetcs=='DeviceGray') { $ncols = 1; }
11306 else if ($targetcs=='DeviceRGB') { $ncols = 3; }
11307 else if ($targetcs=='DeviceCMYK') { $ncols = 4; }
11308
11309 $imgdata = gzcompress($imgdata);
11310 $info = array('w'=>$w,'h'=>$h,'cs'=>$targetcs,'bpc'=>8,'f'=>'FlateDecode','data'=>$imgdata, 'type'=>'png',
11311 'parms'=>'/DecodeParms <</Colors '.$ncols.' /BitsPerComponent 8 /Columns '.$w.'>>');
11312 if ($dpi) { $info['set-dpi'] = $dpi; }
11313 if ($mask) {
11314 $mimgdata = gzcompress($mimgdata);
11315 $minfo = array('w'=>$w,'h'=>$h,'cs'=>'DeviceGray','bpc'=>8,'f'=>'FlateDecode','data'=>$mimgdata, 'type'=>'png',
11316 'parms'=>'/DecodeParms <</Colors '.$ncols.' /BitsPerComponent 8 /Columns '.$w.'>>');
11317 if ($dpi) { $minfo['set-dpi'] = $dpi; }
11318 $tempfile = '_tempImgPNG'.md5($data).RAND(1,10000).'.png';
11319 $imgmask = count($this->images)+1;
11320 $minfo['i']=$imgmask ;
11321 $this->images[$tempfile] = $minfo;
11322 $info['masked'] = $imgmask;
11323 }
11324 else if ($trns) { $info['trns'] = $trns; }
11325 imagedestroy($im);
11326 }
11327 return $info;
11328 }
11329
11330
11331 function _trnsvalue($s, $bpc) {
11332 // Corrects 2-byte integer to 8-bit depth value
11333 // If original image is bpc != 8, tRNS will be in this bpc
11334 // $im from imagecreatefromstring will always be in bpc=8
11335 // So why do we only need to correct 16-bit tRNS and NOT 2 or 4-bit???
11336 $n=$this->_twobytes2int($s);
11337 if ($bpc==16) { $n = ($n >> 8); }
11338 //else if ($bpc==4) { $n = ($n << 2); }
11339 //else if ($bpc==2) { $n = ($n << 4); }
11340 return $n;
11341 }
11342
11343
11344 function _fourbytes2int($s) {
11345 //Read a 4-byte integer from string
11346 return (ord($s[0])<<24) + (ord($s[1])<<16) + (ord($s[2])<<8) + ord($s[3]);
11347 }
11348
11349 function _twobytes2int($s) { // equivalent to _get_ushort
11350 //Read a 2-byte integer from string
11351 return (ord(substr($s, 0, 1))<<8) + ord(substr($s, 1, 1));
11352 }
11353
11354 function _jpgHeaderFromString(&$data) {
11355 $p = 4;
11356 $p += $this->_twobytes2int(substr($data, $p, 2)); // Length of initial marker block
11357 $marker = substr($data, $p, 2);
11358 while($marker != chr(255).chr(192) && $marker != chr(255).chr(194) && $p<strlen($data)) {
11359 // Start of frame marker (FFC0) or (FFC2) mPDF 4.4.004
11360 $p += ($this->_twobytes2int(substr($data, $p+2, 2))) + 2; // Length of marker block
11361 $marker = substr($data, $p, 2);
11362 }
11363 if ($marker != chr(255).chr(192) && $marker != chr(255).chr(194)) { return false; }
11364 return substr($data, $p+2, 10);
11365 }
11366
11367 function _jpgDataFromHeader($hdr) {
11368 $bpc = ord(substr($hdr, 2, 1));
11369 if (!$bpc) { $bpc = 8; }
11370 $h = $this->_twobytes2int(substr($hdr, 3, 2));
11371 $w = $this->_twobytes2int(substr($hdr, 5, 2));
11372 $channels = ord(substr($hdr, 7, 1));
11373 if ($channels==3) { $colspace='DeviceRGB'; }
11374 elseif($channels==4) { $colspace='DeviceCMYK'; }
11375 else { $colspace='DeviceGray'; }
11376 return array($w, $h, $colspace, $bpc, $channels);
11377 }
11378
11379 function file_get_contents_by_curl($url, &$data) {
11380 $timeout = 5;
11381 $ch = curl_init($url);
11382 curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1'); // mPDF 5.7.4
11383 curl_setopt($ch, CURLOPT_HEADER, 0);
11384 curl_setopt($ch, CURLOPT_NOBODY, 0);
11385 curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 );
11386 curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , $timeout );
11387 $data = curl_exec($ch);
11388 curl_close($ch);
11389 }
11390
11391
11392 function file_get_contents_by_socket($url, &$data) {
11393 // mPDF 5.7.3
11394 $timeout = 1;
11395 $p = parse_url($url);
11396 $file = $p['path'];
11397 if ($p['scheme']=='https') {
11398 $prefix = 'ssl://';
11399 $port = ($p['port'] ? $p['port'] : 443);
11400 }
11401 else {
11402 $prefix = '';
11403 $port = ($p['port'] ? $p['port'] : 80);
11404 }
11405 if ($p['query']) { $file .= '?'.$p['query']; }
11406 if(!($fh = @fsockopen($prefix.$p['host'], $port, $errno, $errstr, $timeout))) { return false; }
11407
11408 $getstring =
11409 "GET ".$file." HTTP/1.0 \r\n" .
11410 "Host: ".$p['host']." \r\n" .
11411 "Connection: close\r\n\r\n";
11412 fwrite($fh, $getstring);
11413 // Get rid of HTTP header
11414 $s = fgets($fh, 1024);
11415 if (!$s) { return false; }
11416 $httpheader .= $s;
11417 while (!feof($fh)) {
11418 $s = fgets($fh, 1024);
11419 if ( $s == "\r\n" ) { break; }
11420 }
11421 $data = '';
11422 while (!feof($fh)) {
11423 $data .= fgets($fh, 1024);
11424 }
11425 fclose($fh);
11426 }
11427
11428 //==============================================================
11429
11430 function _imageTypeFromString(&$data) {
11431 $type = '';
11432 if (substr($data, 6, 4)== 'JFIF' || substr($data, 6, 4)== 'Exif' || substr($data, 0, 2)== chr(255).chr(216)) { // 0xFF 0xD8 // mpDF 5.7.2
11433 $type = 'jpeg';
11434 }
11435 else if (substr($data, 0, 6)== "GIF87a" || substr($data, 0, 6)== "GIF89a") {
11436 $type = 'gif';
11437 }
11438 else if (substr($data, 0, 8)== chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
11439 $type = 'png';
11440 }
11441 /*-- IMAGES-WMF --*/
11442 else if (substr($data, 0, 4)== chr(215).chr(205).chr(198).chr(154)) {
11443 $type = 'wmf';
11444 }
11445 /*-- END IMAGES-WMF --*/
11446 else if (preg_match('/<svg.*<\/svg>/is',$data)) {
11447 $type = 'svg';
11448 }
11449 // BMP images
11450 else if (substr($data, 0, 2)== "BM") {
11451 $type = 'bmp';
11452 }
11453 return $type;
11454 }
11455 //==============================================================
11456
11457 // Moved outside WMF as also needed for SVG
11458 function _putformobjects() {
11459 reset($this->formobjects);
11460 while(list($file,$info)=each($this->formobjects)) {
11461 $this->_newobj();
11462 $this->formobjects[$file]['n']=$this->n;
11463 $this->_out('<</Type /XObject');
11464 $this->_out('/Subtype /Form');
11465 $this->_out('/Group '.($this->n+1).' 0 R');
11466 $this->_out('/BBox ['.$info['x'].' '.$info['y'].' '.($info['w']+$info['x']).' '.($info['h']+$info['y']).']');
11467 if ($this->compress)
11468 $this->_out('/Filter /FlateDecode');
11469 $data=($this->compress) ? gzcompress($info['data']) : $info['data'];
11470 $this->_out('/Length '.strlen($data).'>>');
11471 $this->_putstream($data);
11472 unset($this->formobjects[$file]['data']);
11473 $this->_out('endobj');
11474 // Required for SVG transparency (opacity) to work
11475 $this->_newobj();
11476 $this->_out('<</Type /Group');
11477 $this->_out('/S /Transparency');
11478 $this->_out('>>');
11479 $this->_out('endobj');
11480 }
11481 }
11482
11483 function _freadint($f)
11484 {
11485 //Read a 4-byte integer from file
11486 $i=ord(fread($f,1))<<24;
11487 $i+=ord(fread($f,1))<<16;
11488 $i+=ord(fread($f,1))<<8;
11489 $i+=ord(fread($f,1));
11490 return $i;
11491 }
11492
11493 function _UTF16BEtextstring($s) {
11494 $s = $this->UTF8ToUTF16BE($s, true);
11495 /*-- ENCRYPTION --*/
11496 if ($this->encrypted) {
11497 $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
11498 }
11499 /*-- END ENCRYPTION --*/
11500 return '('. $this->_escape($s).')';
11501 }
11502
11503 function _textstring($s) {
11504 /*-- ENCRYPTION --*/
11505 if ($this->encrypted) {
11506 $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
11507 }
11508 /*-- END ENCRYPTION --*/
11509 return '('. $this->_escape($s).')';
11510 }
11511
11512
11513 function _escape($s)
11514 {
11515 // the chr(13) substitution fixes the Bugs item #1421290.
11516 return strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r'));
11517 }
11518
11519 function _putstream($s) {
11520 /*-- ENCRYPTION --*/
11521 if ($this->encrypted) {
11522 $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
11523 }
11524 /*-- END ENCRYPTION --*/
11525 $this->_out('stream');
11526 $this->_out($s);
11527 $this->_out('endstream');
11528 }
11529
11530
11531 function _out($s,$ln=true) {
11532 if($this->state==2) {
11533 if ($this->bufferoutput) {
11534 $this->headerbuffer.= $s."\n";
11535 }
11536 /*-- COLUMNS --*/
11537 else if (($this->ColActive) && !$this->processingHeader && !$this->processingFooter) {
11538 // Captures everything in buffer for columns; Almost everything is sent from fn. Cell() except:
11539 // Images sent from Image() or
11540 // later sent as _out($textto) in printbuffer
11541 // Line()
11542 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
11543 $h = ($m[1]/_MPDFK);
11544 // Update/overwrite the lowest bottom of printing y value for a column
11545 $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y+$h;
11546 }
11547 /*-- TABLES --*/
11548 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
11549 $h = ($m[1]/_MPDFK);
11550 // Update/overwrite the lowest bottom of printing y value for a column
11551 $this->ColDetails[$this->CurrCol]['bottom_margin'] = max($this->ColDetails[$this->CurrCol]['bottom_margin'],($this->y+$h));
11552 }
11553 /*-- END TABLES --*/
11554 else { // Td Text Set in Cell()
11555 if (isset($this->ColDetails[$this->CurrCol]['bottom_margin'])) { $h = $this->ColDetails[$this->CurrCol]['bottom_margin'] - $this->y; }
11556 else { $h = 0; }
11557 }
11558 if ($h < 0) { $h = -$h; }
11559 $this->columnbuffer[] = array(
11560 's' => $s, // Text string to output
11561 'col' => $this->CurrCol, // Column when printed
11562 'x' => $this->x, // x when printed
11563 'y' => $this->y, // this->y when printed (after column break)
11564 'h' => $h // actual y at bottom when printed = y+h
11565 );
11566 }
11567 /*-- END COLUMNS --*/
11568 /*-- TABLES --*/
11569 else if ($this->table_rotate && !$this->processingHeader && !$this->processingFooter) {
11570 // Captures eveything in buffer for rotated tables;
11571 $this->tablebuffer .= $s . "\n";
11572 }
11573 /*-- END TABLES --*/
11574 else if ($this->kwt && !$this->processingHeader && !$this->processingFooter) {
11575 // Captures eveything in buffer for keep-with-table (h1-6);
11576 $this->kwt_buffer[] = array(
11577 's' => $s, // Text string to output
11578 'x' => $this->x, // x when printed
11579 'y' => $this->y, // y when printed
11580 );
11581 }
11582 else if (($this->keep_block_together) && !$this->processingHeader && !$this->processingFooter) {
11583 // do nothing
11584 }
11585 else {
11586 $this->pages[$this->page] .= $s.($ln == true ? "\n" : '');
11587 }
11588
11589 }
11590 else {
11591 $this->buffer .= $s.($ln == true ? "\n" : '');
11592 }
11593 }
11594
11595 /*-- WATERMARK --*/
11596 // add a watermark
11597 function watermark( $texte, $angle=45, $fontsize=96, $alpha=0.2 ) {
11598 if ($this->PDFA || $this->PDFX) { $this->Error('PDFA and PDFX do not permit transparency, so mPDF does not allow Watermarks!'); }
11599 if (!$this->watermark_font) { $this->watermark_font = $this->default_font; }
11600 $this->SetFont( $this->watermark_font, "B", $fontsize, false ); // Don't output
11601 $texte= $this->purify_utf8_text($texte);
11602 if ($this->text_input_as_HTML) {
11603 $texte= $this->all_entities_to_utf8($texte);
11604 }
11605 if ($this->usingCoreFont) { $texte = mb_convert_encoding($texte,$this->mb_enc,'UTF-8'); }
11606
11607 // DIRECTIONALITY
11608 if (preg_match("/([".$this->pregRTLchars."])/u", $texte)) { $this->biDirectional = true; } // *OTL*
11609
11610 $textvar = 0;
11611 $save_OTLtags = $this->OTLtags;
11612 $this->OTLtags = array();
11613 if ($this->useKerning) {
11614 if ($this->CurrentFont['haskernGPOS']) { $this->OTLtags['Plus'] .= ' kern'; }
11615 else { $textvar = ($textvar | FC_KERNING); }
11616 }
11617
11618 /*-- OTL --*/
11619 // Use OTL OpenType Table Layout - GSUB & GPOS
11620 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
11621 $texte = $this->otl->applyOTL($texte, $this->CurrentFont['useOTL']);
11622 $OTLdata = $this->otl->OTLdata;
11623 }
11624 /*-- END OTL --*/
11625 $this->OTLtags = $save_OTLtags ;
11626
11627 $this->magic_reverse_dir($texte, $this->directionality, $OTLdata);
11628
11629 $this->SetAlpha($alpha);
11630
11631 $this->SetTColor($this->ConvertColor(0));
11632 $szfont = $fontsize;
11633 $loop = 0;
11634 $maxlen = (min($this->w,$this->h) ); // sets max length of text as 7/8 width/height of page
11635 while ( $loop == 0 )
11636 {
11637 $this->SetFont( $this->watermark_font, "B", $szfont, false ); // Don't output
11638 $offset = ((sin(deg2rad($angle))) * ($szfont/_MPDFK));
11639
11640 $strlen = $this->GetStringWidth($texte, true, $OTLdata, $textvar);
11641 if ( $strlen > $maxlen - $offset )
11642 $szfont --;
11643 else
11644 $loop ++;
11645 }
11646
11647 $this->SetFont( $this->watermark_font, "B", $szfont-0.1, true, true); // Output The -0.1 is because SetFont above is not written to PDF
11648 // Repeating it will not output anything as mPDF thinks it is set
11649 $adj = ((cos(deg2rad($angle))) * ($strlen/2));
11650 $opp = ((sin(deg2rad($angle))) * ($strlen/2));
11651 $wx = ($this->w/2) - $adj + $offset/3;
11652 $wy = ($this->h/2) + $opp;
11653 $this->Rotate($angle,$wx,$wy);
11654 $this->Text($wx,$wy,$texte,$OTLdata,$textvar);
11655 $this->Rotate(0);
11656 $this->SetTColor($this->ConvertColor(0));
11657
11658 $this->SetAlpha(1);
11659
11660 }
11661
11662 function watermarkImg( $src, $alpha=0.2 ) {
11663 if ($this->PDFA || $this->PDFX) { $this->Error('PDFA and PDFX do not permit transparency, so mPDF does not allow Watermarks!'); }
11664 if ($this->watermarkImgBehind) { $this->watermarkImgAlpha = $this->SetAlpha($alpha, 'Normal', true); }
11665 else { $this->SetAlpha($alpha, $this->watermarkImgAlphaBlend); }
11666 $this->Image($src,0,0,0,0,'','', true, true, true);
11667 if (!$this->watermarkImgBehind) { $this->SetAlpha(1); }
11668 }
11669 /*-- END WATERMARK --*/
11670
11671
11672 function Rotate($angle,$x=-1,$y=-1)
11673 {
11674 if($x==-1)
11675 $x=$this->x;
11676 if($y==-1)
11677 $y=$this->y;
11678 if($this->angle!=0)
11679 $this->_out('Q');
11680 $this->angle=$angle;
11681 if($angle!=0)
11682 {
11683 $angle*=M_PI/180;
11684 $c=cos($angle);
11685 $s=sin($angle);
11686 $cx=$x*_MPDFK;
11687 $cy=($this->h-$y)*_MPDFK;
11688 $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));
11689 }
11690 }
11691
11692
11693
11694 function CircularText($x, $y, $r, $text, $align='top', $fontfamily='', $fontsize=0, $fontstyle='', $kerning=120, $fontwidth=100, $divider) {
11695 if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
11696 if (empty($this->directw)) { $this->directw = new directw($this); }
11697 $this->directw->CircularText($x, $y, $r, $text, $align, $fontfamily, $fontsize, $fontstyle, $kerning, $fontwidth, $divider);
11698 }
11699
11700
11701 // From Invoice
11702 function RoundedRect($x, $y, $w, $h, $r, $style = '')
11703 {
11704 $hp = $this->h;
11705 if($style=='F')
11706 $op='f';
11707 elseif($style=='FD' or $style=='DF')
11708 $op='B';
11709 else
11710 $op='S';
11711 $MyArc = 4/3 * (sqrt(2) - 1);
11712 $this->_out(sprintf('%.3F %.3F m',($x+$r)*_MPDFK,($hp-$y)*_MPDFK ));
11713 $xc = $x+$w-$r ;
11714 $yc = $y+$r;
11715 $this->_out(sprintf('%.3F %.3F l', $xc*_MPDFK,($hp-$y)*_MPDFK ));
11716
11717 $this->_Arc($xc + $r*$MyArc, $yc - $r, $xc + $r, $yc - $r*$MyArc, $xc + $r, $yc);
11718 $xc = $x+$w-$r ;
11719 $yc = $y+$h-$r;
11720 $this->_out(sprintf('%.3F %.3F l',($x+$w)*_MPDFK,($hp-$yc)*_MPDFK));
11721 $this->_Arc($xc + $r, $yc + $r*$MyArc, $xc + $r*$MyArc, $yc + $r, $xc, $yc + $r);
11722 $xc = $x+$r ;
11723 $yc = $y+$h-$r;
11724 $this->_out(sprintf('%.3F %.3F l',$xc*_MPDFK,($hp-($y+$h))*_MPDFK));
11725 $this->_Arc($xc - $r*$MyArc, $yc + $r, $xc - $r, $yc + $r*$MyArc, $xc - $r, $yc);
11726 $xc = $x+$r ;
11727 $yc = $y+$r;
11728 $this->_out(sprintf('%.3F %.3F l',($x)*_MPDFK,($hp-$yc)*_MPDFK ));
11729 $this->_Arc($xc - $r, $yc - $r*$MyArc, $xc - $r*$MyArc, $yc - $r, $xc, $yc - $r);
11730 $this->_out($op);
11731 }
11732
11733 function _Arc($x1, $y1, $x2, $y2, $x3, $y3)
11734 {
11735 $h = $this->h;
11736 $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $x1*_MPDFK, ($h-$y1)*_MPDFK,
11737 $x2*_MPDFK, ($h-$y2)*_MPDFK, $x3*_MPDFK, ($h-$y3)*_MPDFK));
11738 }
11739
11740
11741
11742
11743 //====================================================
11744
11745
11746
11747 /*-- DIRECTW --*/
11748 function Shaded_box( $text,$font='',$fontstyle='B',$szfont='',$width='70%',$style='DF',$radius=2.5,$fill='#FFFFFF',$color='#000000',$pad=2 ) {
11749 // F (shading - no line),S (line, no shading),DF (both)
11750 if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
11751 if (empty($this->directw)) { $this->directw = new directw($this); }
11752 $this->directw->Shaded_box( $text,$font,$fontstyle,$szfont,$width,$style,$radius,$fill,$color,$pad);
11753 }
11754 /*-- END DIRECTW --*/
11755
11756
11757 function UTF8StringToArray($str, $addSubset=true) {
11758 $out = array();
11759 $len = strlen($str);
11760 for ($i = 0; $i < $len; $i++) {
11761 $uni = -1;
11762 $h = ord($str[$i]);
11763 if ( $h <= 0x7F )
11764 $uni = $h;
11765 elseif ( $h >= 0xC2 ) {
11766 if ( ($h <= 0xDF) && ($i < $len -1) )
11767 $uni = ($h & 0x1F) << 6 | (ord($str[++$i]) & 0x3F);
11768 elseif ( ($h <= 0xEF) && ($i < $len -2) )
11769 $uni = ($h & 0x0F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
11770 elseif ( ($h <= 0xF4) && ($i < $len -3) )
11771 $uni = ($h & 0x0F) << 18 | (ord($str[++$i]) & 0x3F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
11772 }
11773 if ($uni >= 0) {
11774 $out[] = $uni;
11775 if ($addSubset && isset($this->CurrentFont['subset'])) {
11776 $this->CurrentFont['subset'][$uni] = $uni;
11777 }
11778 }
11779 }
11780 return $out;
11781 }
11782
11783
11784 //Convert utf-8 string to <HHHHHH> for Font Subsets
11785 function UTF8toSubset($str) {
11786 $ret = '<';
11787 //$str = preg_replace('/'.preg_quote($this->aliasNbPg,'/').'/', chr(7), $str ); // mPDF 6 deleted
11788 //$str = preg_replace('/'.preg_quote($this->aliasNbPgGp,'/').'/', chr(8), $str ); // mPDF 6 deleted
11789 $unicode = $this->UTF8StringToArray($str);
11790 $orig_fid = $this->CurrentFont['subsetfontids'][0];
11791 $last_fid = $this->CurrentFont['subsetfontids'][0];
11792 foreach($unicode as $c) {
11793 /* // mPDF 6 deleted
11794 if ($c == 7 || $c == 8) {
11795 if ($orig_fid != $last_fid) {
11796 $ret .= '> Tj /F'.$orig_fid.' '.$this->FontSizePt.' Tf <';
11797 $last_fid = $orig_fid;
11798 }
11799 if ($c == 7) { $ret .= $this->aliasNbPgHex; }
11800 else { $ret .= $this->aliasNbPgGpHex; }
11801 continue;
11802 }
11803 */
11804 if (!$this->_charDefined($this->CurrentFont['cw'], $c)) { $c = 0; } // mPDF 6
11805 for ($i=0; $i<99; $i++) {
11806 // return c as decimal char
11807 $init = array_search($c, $this->CurrentFont['subsets'][$i]);
11808 if ($init!==false) {
11809 if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
11810 $ret .= '> Tj /F'.$this->CurrentFont['subsetfontids'][$i].' '.$this->FontSizePt.' Tf <';
11811 $last_fid = $this->CurrentFont['subsetfontids'][$i];
11812 }
11813 $ret .= sprintf("%02s", strtoupper(dechex($init)));
11814 break;
11815 }
11816 // TrueType embedded SUBSETS
11817 else if (count($this->CurrentFont['subsets'][$i]) < 255) {
11818 $n = count($this->CurrentFont['subsets'][$i]);
11819 $this->CurrentFont['subsets'][$i][$n] = $c;
11820 if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
11821 $ret .= '> Tj /F'.$this->CurrentFont['subsetfontids'][$i].' '.$this->FontSizePt.' Tf <';
11822 $last_fid = $this->CurrentFont['subsetfontids'][$i];
11823 }
11824 $ret .= sprintf("%02s", strtoupper(dechex($n)));
11825 break;
11826 }
11827 else if (!isset($this->CurrentFont['subsets'][($i+1)])) {
11828 // TrueType embedded SUBSETS
11829 $this->CurrentFont['subsets'][($i+1)] = array(0=>0);
11830 $new_fid = count($this->fonts)+$this->extraFontSubsets+1;
11831 $this->CurrentFont['subsetfontids'][($i+1)] = $new_fid;
11832 $this->extraFontSubsets++;
11833 }
11834 }
11835 }
11836 $ret .= '>';
11837 if ($last_fid != $orig_fid) {
11838 $ret .= ' Tj /F'.$orig_fid.' '.$this->FontSizePt.' Tf <> ';
11839 }
11840 return $ret;
11841 }
11842
11843
11844 // Converts UTF-8 strings to UTF16-BE.
11845 function UTF8ToUTF16BE($str, $setbom=true) {
11846 if ($this->checkSIP && preg_match("/([\x{20000}-\x{2FFFF}])/u", $str)) {
11847 if (!in_array($this->currentfontfamily, array('gb','big5','sjis','uhc','gbB','big5B','sjisB','uhcB','gbI','big5I','sjisI','uhcI',
11848 'gbBI','big5BI','sjisBI','uhcBI'))) {
11849 $str = preg_replace("/[\x{20000}-\x{2FFFF}]/u", chr(0), $str);
11850 }
11851 }
11852 if ($this->checkSMP && preg_match("/([\x{10000}-\x{1FFFF}])/u", $str )) {
11853 $str = preg_replace("/[\x{10000}-\x{1FFFF}]/u", chr(0), $str );
11854 }
11855 $outstr = ""; // string to be returned
11856 if ($setbom) {
11857 $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM)
11858 }
11859 $outstr .= mb_convert_encoding($str, 'UTF-16BE', 'UTF-8');
11860 return $outstr;
11861 }
11862
11863
11864
11865
11866
11867 // ====================================================
11868 // ====================================================
11869 /*-- CJK-FONTS --*/
11870
11871 // from class PDF_Chinese CJK EXTENSIONS
11872 function AddCIDFont($family,$style,$name,&$cw,$CMap,$registry,$desc)
11873 {
11874 $fontkey=strtolower($family).strtoupper($style);
11875 if(isset($this->fonts[$fontkey]))
11876 $this->Error("Font already added: $family $style");
11877 $i=count($this->fonts)+$this->extraFontSubsets+1;
11878 $name=str_replace(' ','',$name);
11879 if ($family == 'sjis') { $up = -120; } else { $up = -130; }
11880 // ? 'up' and 'ut' do not seem to be referenced anywhere
11881 $this->fonts[$fontkey]=array('i'=>$i,'type'=>'Type0','name'=>$name,'up'=>$up,'ut'=>40,'cw'=>$cw,'CMap'=>$CMap,'registry'=>$registry,'MissingWidth'=>1000,'desc'=>$desc);
11882 }
11883
11884 function AddCJKFont($family) {
11885
11886 if ($this->PDFA || $this->PDFX) {
11887 $this->Error("Adobe CJK fonts cannot be embedded in mPDF (required for PDFA1-b and PDFX/1-a).");
11888 }
11889 if ($family == 'big5') { $this->AddBig5Font(); }
11890 else if ($family == 'gb') { $this->AddGBFont(); }
11891 else if ($family == 'sjis') { $this->AddSJISFont(); }
11892 else if ($family == 'uhc') { $this->AddUHCFont(); }
11893 }
11894
11895 function AddBig5Font()
11896 {
11897 //Add Big5 font with proportional Latin
11898 $family='big5';
11899 $name='MSungStd-Light-Acro';
11900 $cw=$this->Big5_widths;
11901 $CMap='UniCNS-UTF16-H';
11902 $registry=array('ordering'=>'CNS1','supplement'=>4);
11903 $desc = array(
11904 'Ascent' => 880,
11905 'Descent' => -120,
11906 'CapHeight' => 880,
11907 'Flags' => 6,
11908 'FontBBox' => '[-160 -249 1015 1071]',
11909 'ItalicAngle' => 0,
11910 'StemV' => 93,
11911 );
11912 $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
11913 $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
11914 $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
11915 $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
11916 }
11917
11918
11919 function AddGBFont()
11920 {
11921 //Add GB font with proportional Latin
11922 $family='gb';
11923 $name='STSongStd-Light-Acro';
11924 $cw=$this->GB_widths;
11925 $CMap='UniGB-UTF16-H';
11926 $registry=array('ordering'=>'GB1','supplement'=>4);
11927 $desc = array(
11928 'Ascent' => 880,
11929 'Descent' => -120,
11930 'CapHeight' => 737,
11931 'Flags' => 6,
11932 'FontBBox' => '[-25 -254 1000 880]',
11933 'ItalicAngle' => 0,
11934 'StemV' => 58,
11935 'Style' => '<< /Panose <000000000400000000000000> >>',
11936 );
11937 $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
11938 $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
11939 $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
11940 $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
11941 }
11942
11943
11944 function AddSJISFont()
11945 {
11946 //Add SJIS font with proportional Latin
11947 $family='sjis';
11948 $name='KozMinPro-Regular-Acro';
11949 $cw=$this->SJIS_widths;
11950 $CMap='UniJIS-UTF16-H';
11951 $registry=array('ordering'=>'Japan1','supplement'=>5);
11952 $desc = array(
11953 'Ascent' => 880,
11954 'Descent' => -120,
11955 'CapHeight' => 740,
11956 'Flags' => 6,
11957 'FontBBox' => '[-195 -272 1110 1075]',
11958 'ItalicAngle' => 0,
11959 'StemV' => 86,
11960 'XHeight' => 502,
11961 );
11962 $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
11963 $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
11964 $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
11965 $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
11966 }
11967
11968 function AddUHCFont()
11969 {
11970 //Add UHC font with proportional Latin
11971 $family='uhc';
11972 $name='HYSMyeongJoStd-Medium-Acro';
11973 $cw=$this->UHC_widths;
11974 $CMap='UniKS-UTF16-H';
11975 $registry=array('ordering'=>'Korea1','supplement'=>2);
11976 $desc = array(
11977 'Ascent' => 880,
11978 'Descent' => -120,
11979 'CapHeight' => 720,
11980 'Flags' => 6,
11981 'FontBBox' => '[-28 -148 1001 880]',
11982 'ItalicAngle' => 0,
11983 'StemV' => 60,
11984 'Style' => '<< /Panose <000000000600000000000000> >>',
11985 );
11986 $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
11987 $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
11988 $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
11989 $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
11990 }
11991
11992 /*-- END CJK-FONTS --*/
11993
11994 //////////////////////////////////////////////////////////////////////////////
11995 //////////////////////////////////////////////////////////////////////////////
11996 //////////////////////////////////////////////////////////////////////////////
11997 //////////////////////////////////////////////////////////////////////////////
11998 //////////////////////////////////////////////////////////////////////////////
11999 //////////////////////////////////////////////////////////////////////////////
12000 //////////////////////////////////////////////////////////////////////////////
12001
12002 function SetDefaultFont($font) {
12003 // Disallow embedded fonts to be used as defaults in PDFA
12004 if ($this->PDFA || $this->PDFX) {
12005 if (strtolower($font) == 'ctimes') { $font = 'serif'; }
12006 if (strtolower($font) == 'ccourier') { $font = 'monospace'; }
12007 if (strtolower($font) == 'chelvetica') { $font = 'sans-serif'; }
12008 }
12009 $font = $this->SetFont($font); // returns substituted font if necessary
12010 $this->default_font = $font;
12011 $this->original_default_font = $font;
12012 if (!$this->watermark_font ) { $this->watermark_font = $font; } // *WATERMARK*
12013 $this->defaultCSS['BODY']['FONT-FAMILY'] = $font;
12014 $this->cssmgr->CSS['BODY']['FONT-FAMILY'] = $font;
12015 }
12016
12017 function SetDefaultFontSize($fontsize) {
12018 $this->default_font_size = $fontsize;
12019 $this->original_default_font_size = $fontsize;
12020 $this->SetFontSize($fontsize);
12021 $this->defaultCSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
12022 $this->cssmgr->CSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
12023 }
12024
12025 function SetDefaultBodyCSS($prop, $val) {
12026 if ($prop) {
12027 $this->defaultCSS['BODY'][strtoupper($prop)] = $val;
12028 $this->cssmgr->CSS['BODY'][strtoupper($prop)] = $val;
12029 }
12030 }
12031
12032
12033 function SetDirectionality($dir='ltr') {
12034 /*-- OTL --*/
12035 if (strtolower($dir) == 'rtl') {
12036 if ($this->directionality != 'rtl') {
12037 // Swop L/R Margins so page 1 RTL is an 'even' page
12038 $tmp = $this->DeflMargin;
12039 $this->DeflMargin = $this->DefrMargin;
12040 $this->DefrMargin = $tmp;
12041 $this->orig_lMargin = $this->DeflMargin;
12042 $this->orig_rMargin = $this->DefrMargin;
12043
12044 $this->SetMargins($this->DeflMargin,$this->DefrMargin,$this->tMargin);
12045 }
12046 $this->directionality = 'rtl';
12047 $this->defaultAlign = 'R';
12048 $this->defaultTableAlign = 'R';
12049 }
12050 else {
12051 /*-- END OTL --*/
12052 $this->directionality = 'ltr';
12053 $this->defaultAlign = 'L';
12054 $this->defaultTableAlign = 'L';
12055 } // *OTL*
12056 $this->cssmgr->CSS['BODY']['DIRECTION'] = $this->directionality;
12057 }
12058
12059
12060 // Return either a number (factor) - based on current set fontsize (if % or em) - or exact lineheight (with 'mm' after it)
12061 function fixLineheight($v) {
12062 $lh = false;
12063 if (preg_match('/^[0-9\.,]*$/',$v) && $v >= 0) { return ($v + 0); }
12064 else if (strtoupper($v) == 'NORMAL' || $v == 'N') {
12065 return 'N'; // mPDF 6
12066 }
12067 else {
12068 $tlh = $this->ConvertSize($v,$this->FontSize,$this->FontSize,true);
12069 if ($tlh) { return ($tlh.'mm'); }
12070 }
12071 return $this->normalLineheight;
12072 }
12073
12074
12075 function _getNormalLineheight($desc=false) {
12076 if (!$desc) { $desc = $this->CurrentFont['desc']; }
12077 if ($this->useFixedNormalLineHeight) {
12078 $lh = $this->normalLineheight;
12079 }
12080 else if (isset($desc['Ascent']) && $desc['Ascent']) {
12081 $lh = ($this->adjustFontDescLineheight * ($desc['Ascent'] - $desc['Descent'] + $desc['Leading'])/1000);
12082 }
12083 else {
12084 $lh = $this->normalLineheight;
12085 }
12086 return $lh;
12087 }
12088
12089 // Set a (fixed) lineheight to an actual value - either to named fontsize(pts) or default
12090 function SetLineHeight($FontPt='',$lh = '') {
12091 if (!$FontPt) { $FontPt = $this->FontSizePt; }
12092 $fs = $FontPt/_MPDFK;
12093 $this->lineheight = $this->_computeLineheight($lh, $fs);
12094 }
12095
12096 function _computeLineheight($lh, $fs='') {
12097 if ($this->shrin_k > 1) { $k = $this->shrin_k; }
12098 else { $k = 1; }
12099 if (!$fs) { $fs = $this->FontSize; }
12100 if ($lh == 'N') {
12101 $lh = $this->_getNormalLineheight();
12102 }
12103 if (preg_match('/mm/',$lh)) {
12104 return (($lh + 0.0) / $k); // convert to number
12105 }
12106 else if ($lh > 0) {
12107 return ($fs * $lh);
12108 }
12109 return ($fs * $this->normalLineheight);
12110 }
12111
12112 function _setLineYpos(&$fontsize, &$fontdesc, &$CSSlineheight, $blockYpos=false) {
12113 $ypos['glyphYorigin'] = 0;
12114 $ypos['baseline-shift'] = 0;
12115 $linegap = 0;
12116 $leading = 0;
12117
12118 if (isset($fontdesc['Ascent']) && $fontdesc['Ascent'] && !$this->useFixedTextBaseline) {
12119 // Fontsize uses font metrics - this method seems to produce results compatible with browsers (except IE9)
12120 $ypos['boxtop'] = $fontdesc['Ascent']/1000 * $fontsize;
12121 $ypos['boxbottom'] = $fontdesc['Descent']/1000 * $fontsize;
12122 if (isset($fontdesc['Leading'])) { $linegap = $fontdesc['Leading']/1000 * $fontsize; }
12123 }
12124 // Default if not set - uses baselineC
12125 else {
12126 $ypos['boxtop'] = (0.5 + $this->baselineC) * $fontsize;
12127 $ypos['boxbottom'] = -(0.5 - $this->baselineC) * $fontsize;
12128 }
12129 $fontheight = $ypos['boxtop'] - $ypos['boxbottom'];
12130
12131 if ($this->shrin_k > 1) { $shrin_k = $this->shrin_k; }
12132 else { $shrin_k = 1; }
12133
12134 $leading =0;
12135 if ($CSSlineheight == 'N') {
12136 $lh = $this->_getNormalLineheight($fontdesc);
12137 $lineheight = ($fontsize * $lh);
12138 $leading += $linegap; // specified in hhea or sTypo in OpenType tables ****************************************
12139 }
12140 else if (preg_match('/mm/',$CSSlineheight)) { $lineheight = (($CSSlineheight + 0.0) / $shrin_k); } // convert to number
12141 // ??? If lineheight is a factor e.g. 1.3 ?? use factor x 1em or ? use 'normal' lineheight * factor ******************************
12142 // Could depend on value for $text_height - a draft CSS value as set above for now
12143 else if ($CSSlineheight > 0) { $lineheight = ($fontsize * $CSSlineheight); }
12144 else { $lineheight = ($fontsize * $this->normalLineheight); }
12145
12146 // In general, calculate the "leading" - the difference between the fontheight and the lineheight
12147 // and add half to the top and half to the bottom. BUT
12148 // If an inline element has a font-size less than the block element, and the line-height is set as an em or % value
12149 // it will add too much leading below the font and expand the height of the line - so just use the block element exttop/extbottom:
12150 if (preg_match('/mm/',$CSSlineheight) && $ypos['boxtop'] < $blockYpos['boxtop'] && $ypos['boxbottom'] > $blockYpos['boxbottom']) {
12151 $ypos['exttop'] = $blockYpos['exttop'];
12152 $ypos['extbottom'] = $blockYpos['extbottom'];
12153 }
12154 else {
12155 $leading += ($lineheight - $fontheight);
12156
12157 $ypos['exttop'] = $ypos['boxtop'] + $leading/2;
12158 $ypos['extbottom'] = $ypos['boxbottom'] - $leading/2;
12159 }
12160
12161
12162 // TEMP ONLY FOR DEBUGGING *********************************
12163 //$ypos['lineheight'] = $lineheight;
12164 //$ypos['fontheight'] = $fontheight;
12165 //$ypos['leading'] = $leading;
12166
12167 return $ypos;
12168 }
12169
12170
12171
12172
12173 /* Called from WriteFlowingBlock() and finishFlowingBlock()
12174 Determines the line hieght and glyph/writing position
12175 for each element in the line to be written */
12176 function _setInlineBlockHeights(&$lineBox, &$stackHeight, &$content, &$font, $is_table) {
12177 if ($this->shrin_k > 1) { $shrin_k = $this->shrin_k; }
12178 else { $shrin_k = 1; }
12179
12180 $ypos = array();
12181 $bordypos = array();
12182 $bgypos = array();
12183
12184 if ($is_table) {
12185 // FOR TABLE
12186 $fontsize = $this->FontSize;
12187 $fontkey = $this->FontFamily.$this->FontStyle;
12188 $fontdesc = $this->fonts[$fontkey]['desc'];
12189 $CSSlineheight = $this->cellLineHeight ;
12190 $line_stacking_strategy = $this->cellLineStackingStrategy; // inline-line-height [default] | block-line-height | max-height | grid-height
12191 $line_stacking_shift = $this->cellLineStackingShift; // consider-shifts [default] | disregard-shifts
12192 }
12193 else {
12194 // FOR BLOCK FONT
12195 $fontsize = $this->blk[$this->blklvl]['InlineProperties']['size'];
12196 $fontkey = $this->blk[$this->blklvl]['InlineProperties']['family'].$this->blk[$this->blklvl]['InlineProperties']['style'];
12197 $fontdesc = $this->fonts[$fontkey]['desc'];
12198 $CSSlineheight = $this->blk[$this->blklvl]['line_height'];
12199 // inline-line-height | block-line-height | max-height | grid-height
12200 $line_stacking_strategy = (isset($this->blk[$this->blklvl]['line_stacking_strategy']) ? $this->blk[$this->blklvl]['line_stacking_strategy'] : 'inline-line-height');
12201 // consider-shifts | disregard-shifts
12202 $line_stacking_shift = (isset($this->blk[$this->blklvl]['line_stacking_shift']) ? $this->blk[$this->blklvl]['line_stacking_shift'] : 'consider-shifts');
12203 }
12204 $boxLineHeight = $this->_computeLineheight($CSSlineheight, $fontsize);
12205
12206
12207 // First, set a "strut" using block font at index $lineBox[-1]
12208 $ypos[-1] = $this->_setLineYpos($fontsize, $fontdesc, $CSSlineheight);
12209
12210 // for the block element - always taking the block EXTENDED progression including leading - which may be negative
12211 if ($line_stacking_strategy == 'block-line-height') {
12212 $topy = $ypos[-1]['exttop'];
12213 $bottomy = $ypos[-1]['extbottom'];
12214 }
12215 else {
12216 $topy = 0;
12217 $bottomy = 0;
12218 }
12219
12220 // Get text-middle for aligning images/objects
12221 $midpoint = $ypos[-1]['boxtop'] - (($ypos[-1]['boxtop']-$ypos[-1]['boxbottom'])/2);
12222
12223 // for images / inline objects / replaced elements
12224 $mta = 0; // Maximum top-aligned
12225 $mba = 0; // Maximum bottom-aligned
12226 foreach ( $content as $k => $chunk ) {
12227 if (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]['type'] == 'listmarker') {
12228 $ypos[$k] = $ypos[-1];
12229 // UPDATE Maximums
12230 if ($line_stacking_strategy == 'block-line-height' || $line_stacking_strategy == 'grid-height' || $line_stacking_strategy == 'max-height') { // don't include extended block progression of all inline elements
12231 if ($ypos[$k]['boxtop'] > $topy) $topy = $ypos[$k]['boxtop'];
12232 if ($ypos[$k]['boxbottom'] < $bottomy) $bottomy = $ypos[$k]['boxbottom'];
12233 }
12234 else {
12235 if ($ypos[$k]['exttop'] > $topy) $topy = $ypos[$k]['exttop'];
12236 if ($ypos[$k]['extbottom'] < $bottomy) $bottomy = $ypos[$k]['extbottom'];
12237 }
12238 }
12239 else if (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]['type'] == 'dottab') { // mPDF 6 DOTTAB
12240 $fontsize = $font[$k]['size'];
12241 $fontdesc = $font[$k]['curr']['desc'];
12242 $lh = 1;
12243 $ypos[$k] = $this->_setLineYpos($fontsize, $fontdesc, $lh, $ypos[-1]); // Lineheight=1 fixed
12244 }
12245 else if (isset($this->objectbuffer[$k])) {
12246 $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
12247 $va = $this->objectbuffer[$k]['vertical-align'];
12248
12249 if ($va == 'BS') { // (BASELINE default)
12250 if ($oh > $topy) $topy = $oh;
12251 }
12252 else if ($va == 'M') {
12253 if (($midpoint + $oh/2) > $topy) $topy = $midpoint + $oh/2;
12254 if (($midpoint - $oh/2) < $bottomy) $bottomy = $midpoint - $oh/2;
12255 }
12256 else if ($va == 'TT') {
12257 if (($ypos[-1]['boxtop'] - $oh) < $bottomy) {
12258 $bottomy = $ypos[-1]['boxtop'] - $oh;
12259 $topy = max($topy, $ypos[-1]['boxtop']);
12260 }
12261 }
12262 else if ($va == 'TB') {
12263 if (($ypos[-1]['boxbottom'] + $oh) > $topy) {
12264 $topy = $ypos[-1]['boxbottom'] + $oh;
12265 $bottomy = min($bottomy, $ypos[-1]['boxbottom']);
12266 }
12267 }
12268 else if ($va == 'T') {
12269 if ($oh > $mta) $mta = $oh;
12270 }
12271 else if ($va == 'B') {
12272 if ($oh > $mba) $mba = $oh;
12273 }
12274 }
12275 else if ($content[$k] || $content[$k]==='0') {
12276 // FOR FLOWING BLOCK
12277 $fontsize = $font[$k]['size'];
12278 $fontdesc = $font[$k]['curr']['desc'];
12279 // In future could set CSS line-height from inline elements; for now, use block level:
12280 $ypos[$k] = $this->_setLineYpos($fontsize, $fontdesc, $CSSlineheight, $ypos[-1]);
12281
12282 if (isset($font[$k]['textparam']['text-baseline']) && $font[$k]['textparam']['text-baseline'] != 0) {
12283 $ypos[$k]['baseline-shift'] = $font[$k]['textparam']['text-baseline'];
12284 }
12285
12286 // DO ALIGNMENT FOR BASELINES *******************
12287 // Until most fonts have OpenType BASE tables, this won't work
12288 // $ypos[$k] compared to $ypos[-1] or $ypos[$k-1] using $dominant_baseline and $baseline_table
12289
12290 // UPDATE Maximums
12291 if ($line_stacking_strategy == 'block-line-height' || $line_stacking_strategy == 'grid-height' || $line_stacking_strategy == 'max-height') { // don't include extended block progression of all inline elements
12292 if ($line_stacking_shift == 'disregard-shifts') {
12293 if ($ypos[$k]['boxtop'] > $topy) $topy = $ypos[$k]['boxtop'] ;
12294 if ($ypos[$k]['boxbottom'] < $bottomy) $bottomy = $ypos[$k]['boxbottom'] ;
12295 }
12296 else {
12297 if (($ypos[$k]['boxtop'] + $ypos[$k]['baseline-shift']) > $topy) $topy = $ypos[$k]['boxtop'] + $ypos[$k]['baseline-shift'] ;
12298 if (($ypos[$k]['boxbottom'] + $ypos[$k]['baseline-shift']) < $bottomy) $bottomy = $ypos[$k]['boxbottom'] + $ypos[$k]['baseline-shift'] ;
12299 }
12300 }
12301 else {
12302 if ($line_stacking_shift == 'disregard-shifts') {
12303 if ($ypos[$k]['exttop'] > $topy) $topy = $ypos[$k]['exttop'] ;
12304 if ($ypos[$k]['extbottom'] < $bottomy) $bottomy = $ypos[$k]['extbottom'] ;
12305 }
12306 else {
12307 if (($ypos[$k]['exttop'] + $ypos[$k]['baseline-shift']) > $topy) $topy = $ypos[$k]['exttop'] + $ypos[$k]['baseline-shift'] ;
12308 if (($ypos[$k]['extbottom'] + $ypos[$k]['baseline-shift']) < $bottomy) $bottomy = $ypos[$k]['extbottom'] + $ypos[$k]['baseline-shift'] ;
12309 }
12310 }
12311
12312 // If BORDER set on inline element
12313 if (isset($font[$k]['bord']) && $font[$k]['bord']) {
12314 $bordfontsize = $font[$k]['textparam']['bord-decoration']['fontsize'] / $shrin_k;
12315 $bordfontkey = $font[$k]['textparam']['bord-decoration']['fontkey'] ;
12316 if ($bordfontkey != $fontkey || $bordfontsize != $fontsize || isset($font[$k]['textparam']['bord-decoration']['baseline'])) {
12317 $bordfontdesc = $this->fonts[$bordfontkey]['desc'];
12318 $bordypos[$k] = $this->_setLineYpos($bordfontsize, $bordfontdesc, $CSSlineheight, $ypos[-1]);
12319 if (isset($font[$k]['textparam']['bord-decoration']['baseline']) && $font[$k]['textparam']['bord-decoration']['baseline'] != 0) {
12320 $bordypos[$k]['baseline-shift'] = $font[$k]['textparam']['bord-decoration']['baseline'] / $shrin_k;
12321 }
12322 }
12323 }
12324 // If BACKGROUND set on inline element
12325 if (isset($font[$k]['spanbgcolor']) && $font[$k]['spanbgcolor']) {
12326 $bgfontsize = $font[$k]['textparam']['bg-decoration']['fontsize'] / $shrin_k;
12327 $bgfontkey = $font[$k]['textparam']['bg-decoration']['fontkey'] ;
12328 if ($bgfontkey != $fontkey || $bgfontsize != $fontsize || isset($font[$k]['textparam']['bg-decoration']['baseline'])) {
12329 $bgfontdesc = $this->fonts[$bgfontkey]['desc'];
12330 $bgypos[$k] = $this->_setLineYpos($bgfontsize, $bgfontdesc, $CSSlineheight, $ypos[-1]);
12331 if (isset($font[$k]['textparam']['bg-decoration']['baseline']) && $font[$k]['textparam']['bg-decoration']['baseline'] != 0) {
12332 $bgypos[$k]['baseline-shift'] = $font[$k]['textparam']['bg-decoration']['baseline'] / $shrin_k;
12333 }
12334 }
12335 }
12336 }
12337 }
12338
12339
12340 // TOP or BOTTOM aligned images
12341 if ($mta > ($topy - $bottomy) ) {
12342 if (($topy - $mta) < $bottomy ) $bottomy = $topy - $mta ;
12343 }
12344 if ($mba > ($topy - $bottomy) ) {
12345 if (($bottomy + $mba) > $topy) $topy = $bottomy + $mba ;
12346 }
12347
12348 if ($line_stacking_strategy == 'block-line-height') { // fixed height set by block element (whether present or not)
12349 $topy = $ypos[-1]['exttop'];
12350 $bottomy = $ypos[-1]['extbottom'];
12351 }
12352
12353 $inclusiveHeight = $topy - $bottomy;
12354
12355 // SET $stackHeight taking note of line_stacking_strategy
12356 // NB inclusive height already takes account of need to consider block progression height (excludes leading set by lineheight)
12357 // or extended block progression height (includes leading set by lineheight)
12358 if ($line_stacking_strategy == 'block-line-height') { // fixed = extended block progression height of block element
12359 $stackHeight = $boxLineHeight;
12360 }
12361 else if ($line_stacking_strategy == 'max-height') { // smallest height which includes extended block progression height of block element
12362 // and block progression heights of inline elements (NOT extended)
12363 $stackHeight = $inclusiveHeight;
12364 }
12365 else if ($line_stacking_strategy == 'grid-height') { // smallest multiple of block element lineheight to include
12366 // block progression heights of inline elements (NOT extended)
12367 $stackHeight = $boxLineHeight;
12368 while($stackHeight < $inclusiveHeight) { $stackHeight += $boxLineHeight; }
12369 }
12370 else { // 'inline-line-height' = default // smallest height which includes extended block progression height of block element
12371 // AND extended block progression heights of inline elements
12372 $stackHeight = $inclusiveHeight;
12373 }
12374
12375 $diff = $stackHeight - $inclusiveHeight;
12376 $topy += $diff/2;
12377 $bottomy -= $diff/2;
12378
12379 // ADJUST $ypos => lineBox using $stackHeight; lineBox are all offsets from the top of stackHeight in mm
12380 // and SET IMAGE OFFSETS
12381 $lineBox[-1]['boxtop'] = $topy - $ypos[-1]['boxtop'];
12382 $lineBox[-1]['boxbottom'] = $topy - $ypos[-1]['boxbottom'];
12383 // $lineBox[-1]['exttop'] = $topy - $ypos[-1]['exttop'];
12384 // $lineBox[-1]['extbottom'] = $topy - $ypos[-1]['extbottom'];
12385 $lineBox[-1]['glyphYorigin'] = $topy - $ypos[-1]['glyphYorigin'];
12386 $lineBox[-1]['baseline-shift'] = $ypos[-1]['baseline-shift'];
12387
12388 $midpoint = $lineBox[-1]['boxbottom'] - (($lineBox[-1]['boxbottom']-$lineBox[-1]['boxtop'])/2);
12389
12390 foreach ( $content as $k => $chunk ) {
12391 if (isset($this->objectbuffer[$k])) {
12392 $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
12393 // LIST MARKERS
12394 if ($this->objectbuffer[$k]['type'] == 'listmarker') {
12395 $oh = $fontsize;
12396 }
12397 else if ($this->objectbuffer[$k]['type'] == 'dottab') { // mPDF 6 DOTTAB
12398 $oh = $font[$k]['size']; // == $this->objectbuffer[$k]['fontsize']/_MPDFK;
12399 $lineBox[$k]['boxtop'] = $topy - $ypos[$k]['boxtop'];
12400 $lineBox[$k]['boxbottom'] = $topy - $ypos[$k]['boxbottom'];
12401 $lineBox[$k]['glyphYorigin'] = $topy - $ypos[$k]['glyphYorigin'];
12402 $lineBox[$k]['baseline-shift'] = 0;
12403 // continue;
12404 }
12405 $va = $this->objectbuffer[$k]['vertical-align']; // = $objattr['vertical-align'] = set as M,T,B,S
12406
12407 if ($va == 'BS') { // (BASELINE default)
12408 $lineBox[$k]['top'] = $lineBox[-1]['glyphYorigin'] - $oh;
12409 }
12410 else if ($va == 'M') {
12411 $lineBox[$k]['top'] = $midpoint - $oh/2;
12412 }
12413 else if ($va == 'TT') {
12414 $lineBox[$k]['top'] = $lineBox[-1]['boxtop'];
12415 }
12416 else if ($va == 'TB') {
12417 $lineBox[$k]['top'] = $lineBox[-1]['boxbottom'] - $oh;
12418 }
12419 else if ($va == 'T') {
12420 $lineBox[$k]['top'] = 0;
12421 }
12422 else if ($va == 'B') {
12423 $lineBox[$k]['top'] = $stackHeight-$oh;
12424 }
12425 }
12426 else if ($content[$k] || $content[$k]==='0') {
12427 $lineBox[$k]['boxtop'] = $topy - $ypos[$k]['boxtop'];
12428 $lineBox[$k]['boxbottom'] = $topy - $ypos[$k]['boxbottom'];
12429 // $lineBox[$k]['exttop'] = $topy - $ypos[$k]['exttop'];
12430 // $lineBox[$k]['extbottom'] = $topy - $ypos[$k]['extbottom'];
12431 $lineBox[$k]['glyphYorigin'] = $topy - $ypos[$k]['glyphYorigin'];
12432 $lineBox[$k]['baseline-shift'] = $ypos[$k]['baseline-shift'];
12433 if (isset($bordypos[$k]['boxtop'])) {
12434 $lineBox[$k]['border-boxtop'] = $topy - $bordypos[$k]['boxtop'];
12435 $lineBox[$k]['border-boxbottom'] = $topy - $bordypos[$k]['boxbottom'];
12436 $lineBox[$k]['border-baseline-shift'] = $bordypos[$k]['baseline-shift'];
12437 }
12438 if (isset($bgypos[$k]['boxtop'])) {
12439 $lineBox[$k]['background-boxtop'] = $topy - $bgypos[$k]['boxtop'];
12440 $lineBox[$k]['background-boxbottom'] = $topy - $bgypos[$k]['boxbottom'];
12441 $lineBox[$k]['background-baseline-shift'] = $bgypos[$k]['baseline-shift'];
12442 }
12443 }
12444 }
12445 }
12446
12447
12448 function SetBasePath($str='') {
12449 if ( isset($_SERVER['HTTP_HOST']) ) { $host = $_SERVER['HTTP_HOST']; }
12450 else if ( isset($_SERVER['SERVER_NAME']) ) { $host = $_SERVER['SERVER_NAME']; }
12451 else { $host = ''; }
12452 if (!$str) {
12453 if ($_SERVER['SCRIPT_NAME']) { $currentPath = dirname($_SERVER['SCRIPT_NAME']); }
12454 else { $currentPath = dirname($_SERVER['PHP_SELF']); }
12455 $currentPath = str_replace("\\","/",$currentPath);
12456 if ($currentPath == '/') { $currentPath = ''; }
12457 if ($host) { // mPDF 6
12458 if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) { $currpath = 'https://' . $host . $currentPath .'/'; }
12459 else { $currpath = 'http://' . $host . $currentPath .'/'; }
12460 }
12461 else { $currpath = ''; }
12462 $this->basepath = $currpath;
12463 $this->basepathIsLocal = true;
12464 return;
12465 }
12466 $str = preg_replace('/\?.*/','',$str);
12467 if (!preg_match('/(http|https|ftp):\/\/.*\//i',$str)) { $str .= '/'; }
12468 $str .= 'xxx'; // in case $str ends in / e.g. http://www.bbc.co.uk/
12469 $this->basepath = dirname($str) . "/"; // returns e.g. e.g. http://www.google.com/dir1/dir2/dir3/
12470 $this->basepath = str_replace("\\","/",$this->basepath); //If on Windows
12471 $tr = parse_url($this->basepath);
12472 if (isset($tr['host']) && ($tr['host'] == $host)) { $this->basepathIsLocal = true; }
12473 else { $this->basepathIsLocal = false; }
12474 }
12475
12476
12477 function GetFullPath(&$path,$basepath='') {
12478 // When parsing CSS need to pass temporary basepath - so links are relative to current stylesheet
12479 if (!$basepath) { $basepath = $this->basepath; }
12480 //Fix path value
12481 $path = str_replace("\\","/",$path); //If on Windows
12482
12483 // mPDF 5.7.2
12484 if (substr($path,0,2) == "//") {
12485 $tr = parse_url($basepath);
12486 $path = $tr['scheme'].':'.$path; // mPDF 6
12487 }
12488
12489 $regexp = '|^./|'; // Inadvertently corrects "./path/etc" and "//www.domain.com/etc"
12490 $path = preg_replace($regexp,'',$path);
12491
12492 if(substr($path,0,1) == '#') { return; }
12493 // mPDF 5.7.4
12494 if (substr($path,0,7) == "mailto:") { return; }
12495 if (substr($path,0,3) == "../") { //It is a Relative Link
12496 $backtrackamount = substr_count($path,"../");
12497 $maxbacktrack = substr_count($basepath,"/") - 3;
12498 $filepath = str_replace("../",'',$path);
12499 $path = $basepath;
12500 //If it is an invalid relative link, then make it go to directory root
12501 if ($backtrackamount > $maxbacktrack) $backtrackamount = $maxbacktrack;
12502 //Backtrack some directories
12503 for( $i = 0 ; $i < $backtrackamount + 1 ; $i++ ) $path = substr( $path, 0 , strrpos($path,"/") );
12504 $path = $path . "/" . $filepath; //Make it an absolute path
12505 }
12506 else if( strpos($path,":/") === false || strpos($path,":/") > 10) { //It is a Local Link
12507 if (substr($path,0,1) == "/") {
12508 $tr = parse_url($basepath);
12509 // mPDF 5.7.2
12510 $root = '';
12511 if (!empty($tr['scheme'])) { $root .= $tr['scheme'].'://'; }
12512 $root .= $tr['host'];
12513 $root .= ((isset($tr['port']) && $tr['port']) ? (':'.$tr['port']) : ''); // mPDF 5.7.3
12514 $path = $root . $path;
12515 }
12516 else { $path = $basepath . $path; }
12517 }
12518 //Do nothing if it is an Absolute Link
12519 }
12520
12521
12522 // Used for external CSS files
12523 function _get_file($path) {
12524 // If local file try using local path (? quicker, but also allowed even if allow_url_fopen false)
12525 $contents = '';
12526 // mPDF 5.7.3
12527 if (strpos($path,"//") === false ) { $path = preg_replace('/\.css\?.*$/', '.css', $path); }
12528 $contents = @file_get_contents($path);
12529 if ($contents) { return $contents; }
12530 if ($this->basepathIsLocal) {
12531 $tr = parse_url($path);
12532 $lp=getenv("SCRIPT_NAME");
12533 $ap=realpath($lp);
12534 $ap=str_replace("\\","/",$ap);
12535 $docroot=substr($ap,0,strpos($ap,$lp));
12536 // WriteHTML parses all paths to full URLs; may be local file name
12537 if ($tr['scheme'] && $tr['host'] && $_SERVER["DOCUMENT_ROOT"] ) {
12538 $localpath = $_SERVER["DOCUMENT_ROOT"] . $tr['path'];
12539 }
12540 // DOCUMENT_ROOT is not returned on IIS
12541 else if ($docroot) {
12542 $localpath = $docroot . $tr['path'];
12543 }
12544 else { $localpath = $path; }
12545 $contents = @file_get_contents($localpath);
12546 }
12547 // if not use full URL
12548 else if (!$contents && !ini_get('allow_url_fopen') && function_exists("curl_init")) {
12549 $ch = curl_init($path);
12550 curl_setopt($ch, CURLOPT_HEADER, 0);
12551 curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 );
12552 $contents = curl_exec($ch);
12553 curl_close($ch);
12554 }
12555 return $contents;
12556 }
12557
12558
12559 function docPageNum($num = 0, $extras = false) {
12560 if ($num < 1) { $num = $this->page; }
12561 $type = $this->defaultPageNumStyle; // set default Page Number Style
12562 $ppgno = $num;
12563 $suppress = 0;
12564 $offset = 0;
12565 $lastreset = 0;
12566 foreach($this->PageNumSubstitutions AS $psarr) {
12567 if ($num >= $psarr['from']) {
12568 if ($psarr['reset']) {
12569 if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
12570 $ppgno = $num - $psarr['from'] + 1 + $offset;
12571 $lastreset = $psarr['from'];
12572 }
12573 if ($psarr['type']) { $type = $psarr['type']; }
12574 if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
12575 else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
12576 }
12577 }
12578 if ($suppress) { return ''; }
12579
12580 $ppgno = $this->_getStyledNumber($ppgno, $type);
12581 if ($extras) { $ppgno = $this->pagenumPrefix . $ppgno . $this->pagenumSuffix; }
12582 return $ppgno;
12583 }
12584
12585 function docPageNumTotal($num = 0, $extras = false) {
12586 if ($num < 1) { $num = $this->page; }
12587 $type = $this->defaultPageNumStyle; // set default Page Number Style
12588 $ppgstart = 1;
12589 $ppgend = count($this->pages)+1;
12590 $suppress = 0;
12591 $offset = 0;
12592 foreach($this->PageNumSubstitutions AS $psarr) {
12593 if ($num >= $psarr['from']) {
12594 if ($psarr['reset']) {
12595 if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
12596 $ppgstart = $psarr['from'] + $offset;
12597 $ppgend = count($this->pages)+1 + $offset;
12598 }
12599 if ($psarr['type']) { $type = $psarr['type']; }
12600 if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
12601 else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
12602 }
12603 if ($num < $psarr['from']) {
12604 if ($psarr['reset']) {
12605 $ppgend = $psarr['from'] + $offset;
12606 break;
12607 }
12608 }
12609 }
12610 if ($suppress) { return ''; }
12611 $ppgno = $ppgend-$ppgstart+$offset;
12612
12613 $ppgno = $this->_getStyledNumber($ppgno, $type);
12614 if ($extras) { $ppgno = $this->pagenumPrefix . $ppgno . $this->pagenumSuffix; }
12615 return $ppgno;
12616 }
12617
12618 // mPDF 6
12619 function _getStyledNumber($ppgno, $type, $listmarker=false) {
12620 if ($listmarker) {
12621 $reverse = true; // Reverse RTL numerals (Hebrew) when using for list
12622 $checkfont = true; // Using list - font is set, so check if character is available
12623 }
12624 else {
12625 $reverse = false; // For pagenumbers, RTL numerals (Hebrew) will get reversed later by bidi
12626 $checkfont = false; // For pagenumbers - font is not set, so no check
12627 }
12628 $lowertype = strtolower($type);
12629 if ($lowertype == 'upper-latin' || $lowertype == 'upper-alpha' || $type=='A') { $ppgno = $this->dec2alpha($ppgno,true); }
12630 else if ($lowertype == 'lower-latin' || $lowertype == 'lower-alpha' || $type=='a') { $ppgno = $this->dec2alpha($ppgno,false);}
12631 else if ($lowertype == 'upper-roman' || $type=='I') { $ppgno = $this->dec2roman($ppgno,true); }
12632 else if ($lowertype == 'lower-roman' || $type=='i') { $ppgno = $this->dec2roman($ppgno,false); }
12633 else if ($lowertype=='hebrew') { $ppgno = $this->dec2hebrew($ppgno, $reverse); }
12634 else if (preg_match('/(arabic-indic|bengali|devanagari|gujarati|gurmukhi|kannada|malayalam|oriya|persian|tamil|telugu|thai|urdu|cambodian|khmer|lao)/i',$lowertype,$m)) {
12635 switch($m[1]) { //Format type
12636 case 'arabic-indic': $cp = 0x0660; break;
12637 case 'persian':
12638 case 'urdu': $cp = 0x06F0; break;
12639 case 'bengali': $cp = 0x09E6; break;
12640 case 'devanagari': $cp = 0x0966; break;
12641 case 'gujarati': $cp = 0x0AE6; break;
12642 case 'gurmukhi': $cp = 0x0A66; break;
12643 case 'kannada': $cp = 0x0CE6; break;
12644 case 'malayalam': $cp = 0x0D66; break;
12645 case 'oriya': $cp = 0x0B66; break;
12646 case 'telugu': $cp = 0x0C66; break;
12647 case 'tamil': $cp = 0x0BE6; break;
12648 case 'thai': $cp = 0x0E50; break;
12649 case 'khmer':
12650 case 'cambodian': $cp = 0x17E0; break;
12651 case 'lao': $cp = 0x0ED0; break;
12652 }
12653 $ppgno = $this->dec2other($ppgno, $cp, $checkfont);
12654 }
12655 else if ($lowertype=='cjk-decimal') { $ppgno = $this->dec2cjk($ppgno); }
12656 return $ppgno;
12657 }
12658
12659 function docPageSettings($num = 0) {
12660 // Returns current type (numberstyle), suppression state for this page number;
12661 // reset is only returned if set for this page number
12662 if ($num < 1) { $num = $this->page; }
12663 $type = $this->defaultPageNumStyle; // set default Page Number Style
12664 $ppgno = $num;
12665 $suppress = 0;
12666 $offset = 0;
12667 $reset = '';
12668 foreach($this->PageNumSubstitutions AS $psarr) {
12669 if ($num >= $psarr['from']) {
12670 if ($psarr['reset']) {
12671 if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
12672 $ppgno = $num - $psarr['from'] + 1 + $offset;
12673 }
12674 if ($psarr['type']) { $type = $psarr['type']; }
12675 if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
12676 else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
12677 }
12678 if ($num == $psarr['from']) { $reset = $psarr['reset']; }
12679 }
12680 if ($suppress) { $suppress = 'on'; }
12681 else { $suppress = 'off'; }
12682 return array($type, $suppress, $reset);
12683 }
12684
12685 function RestartDocTemplate() {
12686 $this->docTemplateStart = $this->page;
12687 }
12688
12689
12690
12691 //Page header
12692 function Header($content='') {
12693
12694 $this->cMarginL = 0;
12695 $this->cMarginR = 0;
12696
12697
12698 if (($this->mirrorMargins && ($this->page%2==0) && $this->HTMLHeaderE) || ($this->mirrorMargins && ($this->page%2==1) && $this->HTMLHeader) || (!$this->mirrorMargins && $this->HTMLHeader)) {
12699 $this->writeHTMLHeaders();
12700 return;
12701 }
12702 }
12703
12704
12705
12706 /*-- TABLES --*/
12707 function TableHeaderFooter($content='',$tablestartpage='',$tablestartcolumn ='',$horf = 'H',$level, $firstSpread=true, $finalSpread=true) {
12708 if(($horf=='H' || $horf=='F') && !empty($content)) { // mPDF 5.7.2
12709 $table = &$this->table[1][1];
12710
12711 // mPDF 5.7.2
12712 if ($horf=='F') { // Table Footer
12713 $firstrow = count($table['cells']) - $table['footernrows'];
12714 $lastrow = count($table['cells']) - 1;
12715 }
12716 else { // Table Header
12717 $firstrow = 0;
12718 $lastrow = $table['headernrows'] - 1;
12719 }
12720 if(empty($content[$firstrow])) {
12721 if ($this->debug) { $this->Error("&lt;tfoot&gt; must precede &lt;tbody&gt; in a table"); }
12722 else { return; }
12723 }
12724
12725
12726 // Advance down page by half width of top border
12727 if ($horf=='H') { // Only if header
12728 if ($table['borders_separate']) { $adv = $table['border_spacing_V']/2 + $table['border_details']['T']['w'] + $table['padding']['T']; }
12729 else { $adv = $table['max_cell_border_width']['T'] /2 ; }
12730 if ($adv) {
12731 if ($this->table_rotate) {
12732 $this->y += ($adv);
12733 }
12734 else {
12735 $this->DivLn($adv,$this->blklvl,true);
12736 }
12737 }
12738 }
12739
12740 $topy = $content[$firstrow][0]['y']-$this->y;
12741
12742 for ($i=$firstrow ; $i<=$lastrow; $i++) {
12743
12744 $y = $this->y;
12745
12746 /*-- COLUMNS --*/
12747 // If outside columns, this is done in PaintDivBB
12748 if ($this->ColActive) {
12749 //OUTER FILL BGCOLOR of DIVS
12750 if ($this->blklvl > 0) {
12751 $firstblockfill = $this->GetFirstBlockFill();
12752 if ($firstblockfill && $this->blklvl >= $firstblockfill) {
12753 $divh = $content[$i][0]['h'];
12754 $bak_x = $this->x;
12755 $this->DivLn($divh,-3,false);
12756 // Reset current block fill
12757 $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
12758 $this->SetFColor($bcor);
12759 $this->x = $bak_x;
12760 }
12761 }
12762 }
12763 /*-- END COLUMNS --*/
12764
12765 $colctr = 0;
12766 foreach($content[$i] as $tablehf) {
12767 $colctr++;
12768 $y = $tablehf['y'] - $topy;
12769 $this->y = $y;
12770 //Set some cell values
12771 $x = $tablehf['x'];
12772 if (($this->mirrorMargins) && ($tablestartpage == 'ODD') && (($this->page)%2==0)) { // EVEN
12773 $x = $x +$this->MarginCorrection;
12774 }
12775 else if (($this->mirrorMargins) && ($tablestartpage == 'EVEN') && (($this->page)%2==1)) { // ODD
12776 $x = $x +$this->MarginCorrection;
12777 }
12778 /*-- COLUMNS --*/
12779 // Added to correct for Columns
12780 if ($this->ColActive) {
12781 if ($this->directionality == 'rtl') { // *OTL*
12782 $x -= ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth+$this->ColGap); // *OTL*
12783 } // *OTL*
12784 else { // *OTL*
12785 $x += ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth+$this->ColGap);
12786 } // *OTL*
12787 }
12788 /*-- END COLUMNS --*/
12789
12790 if ($colctr==1) { $x0 = $x; }
12791
12792 // mPDF ITERATION
12793 if ($this->iterationCounter) {
12794 foreach($tablehf['textbuffer'] AS $k=>$t) {
12795 if (!is_array($t[0]) && preg_match('/{iteration ([a-zA-Z0-9_]+)}/',$t[0], $m)) {
12796 $vname = '__'.$m[1].'_';
12797 if (!isset($this->$vname)) { $this->$vname = 1; }
12798 else { $this->$vname++; }
12799 $tablehf['textbuffer'][$k][0] = preg_replace('/{iteration '.$m[1].'}/', $this->$vname, $tablehf['textbuffer'][$k][0]);
12800 }
12801 }
12802 }
12803
12804 $w = $tablehf['w'];
12805 $h = $tablehf['h'];
12806 $va = $tablehf['va'];
12807 $R = $tablehf['R'];
12808 $direction = $tablehf['direction'];
12809 $mih = $tablehf['mih'];
12810 $border = $tablehf['border'];
12811 $border_details = $tablehf['border_details'];
12812 $padding = $tablehf['padding'];
12813 $this->tabletheadjustfinished = true;
12814
12815 $textbuffer = $tablehf['textbuffer'];
12816
12817 //Align
12818 $align = $tablehf['a'];
12819 $this->cellTextAlign=$align;
12820
12821 $this->cellLineHeight = $tablehf['cellLineHeight'];
12822 $this->cellLineStackingStrategy = $tablehf['cellLineStackingStrategy'];
12823 $this->cellLineStackingShift = $tablehf['cellLineStackingShift'];
12824
12825 $this->x = $x;
12826
12827 if ($this->ColActive) {
12828 if ($table['borders_separate']) {
12829 $tablefill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0;
12830 if ($tablefill) {
12831 $color = $this->ConvertColor($tablefill);
12832 if ($color) {
12833 $xadj = ($table['border_spacing_H']/2);
12834 $yadj = ($table['border_spacing_V']/2);
12835 $wadj = $table['border_spacing_H'];
12836 $hadj = $table['border_spacing_V'];
12837 if ($i == $firstrow && $horf=='H') { // Top
12838 $yadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
12839 $hadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
12840 }
12841 if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i+$tablehf['rowspan']) == ($lastrow+1)) || (!isset($tablehf['rowspan']) && ($i+1) == ($lastrow+1))) && $horf=='F') { // Bottom
12842 $hadj += $table['padding']['B'] + $table['border_details']['B']['w'] ;
12843 }
12844 if ($colctr == 1) { // Left
12845 $xadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
12846 $wadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
12847 }
12848 if ($colctr == count($content[$i]) ) { // Right
12849 $wadj += $table['padding']['R'] + $table['border_details']['R']['w'] ;
12850 }
12851 $this->SetFColor($color);
12852 $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F');
12853 }
12854 }
12855 }
12856 }
12857
12858 if ($table['empty_cells']!='hide' || !empty($textbuffer) || !$table['borders_separate']) { $paintcell = true; }
12859 else { $paintcell = false; }
12860
12861 //Vertical align
12862 if ($R && INTVAL($R) > 0 && isset($va) && $va!='B') { $va='B';}
12863
12864 if (!isset($va) || empty($va) || $va=='M') $this->y += ($h-$mih)/2;
12865 elseif (isset($va) && $va=='B') $this->y += $h-$mih;
12866
12867
12868 //TABLE ROW OR CELL FILL BGCOLOR
12869 $fill = 0;
12870 if (isset($tablehf['bgcolor']) && $tablehf['bgcolor'] && $tablehf['bgcolor']!='transparent') {
12871 $fill = $tablehf['bgcolor'];
12872 $leveladj = 6;
12873 }
12874 else if (isset($content[$i][0]['trbgcolor']) && $content[$i][0]['trbgcolor'] && $content[$i][0]['trbgcolor']!='transparent') { // Row color
12875 $fill = $content[$i][0]['trbgcolor'];
12876 $leveladj = 3;
12877 }
12878 if ($fill && $paintcell) {
12879 $color = $this->ConvertColor($fill);
12880 if ($color) {
12881 if ($table['borders_separate']) {
12882 if ($this->ColActive) {
12883 $this->SetFColor($color);
12884 $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');
12885 }
12886 else {
12887 $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);
12888 }
12889 }
12890 else {
12891 if ($this->ColActive) {
12892 $this->SetFColor($color);
12893 $this->Rect($x, $y, $w, $h, 'F');
12894 }
12895 else {
12896 $this->tableBackgrounds[$level*9+$leveladj][] = array('gradient'=>false, 'x'=>$x, 'y'=>$y, 'w'=>$w, 'h'=>$h, 'col'=>$color);
12897 }
12898 }
12899 }
12900 }
12901
12902
12903 /*-- BACKGROUNDS --*/
12904 if (isset($tablehf['gradient']) && $tablehf['gradient'] && $paintcell){
12905 $g = $this->grad->parseBackgroundGradient($tablehf['gradient']);
12906 if ($g) {
12907 if ($table['borders_separate']) {
12908 $px = $x+ ($table['border_spacing_H']/2);
12909 $py = $y+ ($table['border_spacing_V']/2);
12910 $pw = $w- $table['border_spacing_H'];
12911 $ph = $h- $table['border_spacing_V'];
12912 }
12913 else {
12914 $px = $x;
12915 $py = $y;
12916 $pw = $w;
12917 $ph = $h;
12918 }
12919 if ($this->ColActive) {
12920 $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
12921 }
12922 else {
12923 $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'=>'');
12924 }
12925 }
12926 }
12927
12928 if (isset($tablehf['background-image']) && $paintcell){
12929 if ($tablehf['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $tablehf['background-image']['gradient'] )) {
12930 $g = $this->grad->parseMozGradient( $tablehf['background-image']['gradient'] );
12931 if ($g) {
12932 if ($table['borders_separate']) {
12933 $px = $x+ ($table['border_spacing_H']/2);
12934 $py = $y+ ($table['border_spacing_V']/2);
12935 $pw = $w- $table['border_spacing_H'];
12936 $ph = $h- $table['border_spacing_V'];
12937 }
12938 else {
12939 $px = $x;
12940 $py = $y;
12941 $pw = $w;
12942 $ph = $h;
12943 }
12944 if ($this->ColActive) {
12945 $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
12946 }
12947 else {
12948 $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'=>'');
12949 }
12950 }
12951 }
12952 else if ($tablehf['background-image']['image_id']) { // Background pattern
12953 $n = count($this->patterns)+1;
12954 if ($table['borders_separate']) {
12955 $px = $x+ ($table['border_spacing_H']/2);
12956 $py = $y+ ($table['border_spacing_V']/2);
12957 $pw = $w- $table['border_spacing_H'];
12958 $ph = $h- $table['border_spacing_V'];
12959 }
12960 else {
12961 $px = $x;
12962 $py = $y;
12963 $pw = $w;
12964 $ph = $h;
12965 }
12966 if ($this->ColActive) {
12967 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']);
12968 $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']);
12969 if ($tablehf['background-image']['opacity']>0 && $tablehf['background-image']['opacity']<1) { $opac = $this->SetAlpha($tablehf['background-image']['opacity'],'Normal',true); }
12970 else { $opac = ''; }
12971 $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));
12972 }
12973 else {
12974 $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']);
12975 }
12976 }
12977 }
12978 /*-- END BACKGROUNDS --*/
12979
12980 //Cell Border
12981 if ($table['borders_separate'] && $paintcell && $border) {
12982 $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']);
12983 }
12984 else if ($paintcell && $border) {
12985 $this->_tableRect($x, $y, $w, $h, $border, $border_details, true, $table['borders_separate']); // true causes buffer
12986 }
12987
12988 //Print cell content
12989 if (!empty($textbuffer)) {
12990 if ($horf=='F' && preg_match('/{colsum([0-9]*)[_]*}/', $textbuffer[0][0], $m)) {
12991 $rep = sprintf("%01.".intval($m[1])."f", $this->colsums[$colctr-1]);
12992 $textbuffer[0][0] = preg_replace('/{colsum[0-9_]*}/', $rep ,$textbuffer[0][0]);
12993 }
12994
12995 if ($R) {
12996 $cellPtSize = $textbuffer[0][11] / $this->shrin_k;
12997 if (!$cellPtSize) { $cellPtSize = $this->default_font_size; }
12998 $cellFontHeight = ($cellPtSize/_MPDFK);
12999 $opx = $this->x;
13000 $opy = $this->y;
13001 $angle = INTVAL($R);
13002 // Only allow 45 - 90 degrees (when bottom-aligned) or -90
13003 if ($angle > 90) { $angle = 90; }
13004 else if ($angle > 0 && (isset($va) && $va!='B')) { $angle = 90; }
13005 else if ($angle > 0 && $angle <45) { $angle = 45; }
13006 else if ($angle < 0) { $angle = -90; }
13007 $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight);
13008 if (isset($align) && $align =='R') {
13009 $this->x += ($w) + ($offset) - ($cellFontHeight/3) - ($padding['R'] + $border_details['R']['w']);
13010 }
13011 else if (!isset($align ) || $align =='C') {
13012 $this->x += ($w/2) + ($offset);
13013 }
13014 else {
13015 $this->x += ($offset) + ($cellFontHeight/3)+($padding['L'] + $border_details['L']['w']);
13016 }
13017 $str = '';
13018 foreach($tablehf['textbuffer'] AS $t) { $str .= $t[0].' '; }
13019 $str = rtrim($str);
13020
13021 if (!isset($va) || $va=='M') {
13022 $this->y -= ($h-$mih)/2; //Undo what was added earlier VERTICAL ALIGN
13023 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'])); }
13024 else if ($angle < 0) { $this->y += (($h-$mih)/2)+($padding['T'] + $border_details['T']['w']); }
13025 }
13026 else if (isset($va) && $va=='B') {
13027 $this->y -= $h-$mih; //Undo what was added earlier VERTICAL ALIGN
13028 if ($angle > 0) { $this->y += $h-($border_details['B']['w']+$padding['B']); }
13029 else if ($angle < 0) { $this->y += $h-$mih+($padding['T'] + $border_details['T']['w']); }
13030 }
13031 else if (isset($va) && $va=='T') {
13032 if ($angle > 0) { $this->y += $mih-($border_details['B']['w']+$padding['B']); }
13033 else if ($angle < 0) { $this->y += ($padding['T'] + $border_details['T']['w']); }
13034 }
13035
13036 $this->Rotate($angle,$this->x,$this->y);
13037 $s_fs = $this->FontSizePt;
13038 $s_f = $this->FontFamily;
13039 $s_st = $this->FontStyle;
13040 if (!empty($textbuffer[0][3])) { //Font Color
13041 $cor = $textbuffer[0][3];
13042 $this->SetTColor($cor);
13043 }
13044 $this->SetFont($textbuffer[0][4],$textbuffer[0][2],$cellPtSize,true,true);
13045
13046 $this->magic_reverse_dir($str, $this->directionality, $textbuffer[0][18]);
13047 $this->Text($this->x,$this->y,$str,$textbuffer[0][18],$textbuffer[0][8]); // textvar
13048 $this->Rotate(0);
13049 $this->SetFont($s_f,$s_st,$s_fs,true,true);
13050 $this->SetTColor(0);
13051 $this->x = $opx;
13052 $this->y = $opy;
13053 }
13054 else {
13055 if ($table['borders_separate']) { // NB twice border width
13056 $xadj = $border_details['L']['w'] + $padding['L'] +($table['border_spacing_H']/2);
13057 $wadj = $border_details['L']['w'] + $border_details['R']['w'] + $padding['L'] +$padding['R'] + $table['border_spacing_H'];
13058 $yadj = $border_details['T']['w'] + $padding['T'] + ($table['border_spacing_H']/2);
13059 }
13060 else {
13061 $xadj = $border_details['L']['w']/2 + $padding['L'];
13062 $wadj = ($border_details['L']['w'] + $border_details['R']['w'])/2 + $padding['L'] + $padding['R'];
13063 $yadj = $border_details['T']['w']/2 + $padding['T'];
13064 }
13065
13066 $this->divwidth=$w-($wadj);
13067 $this->x += $xadj;
13068 $this->y += $yadj;
13069 $this->printbuffer($textbuffer,'',true, false, $direction);
13070 }
13071
13072 }
13073 $textbuffer = array();
13074
13075 /*-- BACKGROUNDS --*/
13076 if (!$this->ColActive) {
13077 if (isset($content[$i][0]['trgradients']) && ($colctr==1 || $table['borders_separate'])) {
13078 $g = $this->grad->parseBackgroundGradient($content[$i][0]['trgradients']);
13079 if ($g) {
13080 $gx = $x0;
13081 $gy = $y;
13082 $gh = $h;
13083 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
13084 if ($table['borders_separate']) {
13085 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
13086 $clx = $x+ ($table['border_spacing_H']/2);
13087 $cly = $y+ ($table['border_spacing_V']/2);
13088 $clw = $w- $table['border_spacing_H'];
13089 $clh = $h- $table['border_spacing_V'];
13090 // Set clipping path
13091 $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
13092 $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);
13093 }
13094 else {
13095 $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'=>'');
13096 }
13097 }
13098 }
13099
13100 if (isset($content[$i][0]['trbackground-images']) && ($colctr==1 || $table['borders_separate'])) {
13101 if ($content[$i][0]['trbackground-images']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $content[$i][0]['trbackground-images']['gradient'] )) {
13102 $g = $this->grad->parseMozGradient( $content[$i][0]['trbackground-images']['gradient'] );
13103 if ($g) {
13104 $gx = $x0;
13105 $gy = $y;
13106 $gh = $h;
13107 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
13108 if ($table['borders_separate']) {
13109 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
13110 $clx = $x+ ($table['border_spacing_H']/2);
13111 $cly = $y+ ($table['border_spacing_V']/2);
13112 $clw = $w- $table['border_spacing_H'];
13113 $clh = $h- $table['border_spacing_V'];
13114 // Set clipping path
13115 $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
13116 $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);
13117 }
13118 else {
13119 $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'=>'');
13120 }
13121 }
13122 }
13123 else {
13124 $image_id = $content[$i][0]['trbackground-images']['image_id'];
13125 $orig_w = $content[$i][0]['trbackground-images']['orig_w'];
13126 $orig_h = $content[$i][0]['trbackground-images']['orig_h'];
13127 $x_pos = $content[$i][0]['trbackground-images']['x_pos'];
13128 $y_pos = $content[$i][0]['trbackground-images']['y_pos'];
13129 $x_repeat = $content[$i][0]['trbackground-images']['x_repeat'];
13130 $y_repeat = $content[$i][0]['trbackground-images']['y_repeat'];
13131 $resize = $content[$i][0]['trbackground-images']['resize'];
13132 $opacity = $content[$i][0]['trbackground-images']['opacity'];
13133 $itype = $content[$i][0]['trbackground-images']['itype'];
13134
13135 $clippath = '';
13136 $gx = $x0;
13137 $gy = $y;
13138 $gh = $h;
13139 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
13140 if ($table['borders_separate']) {
13141 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
13142 $clx = $x+ ($table['border_spacing_H']/2);
13143 $cly = $y+ ($table['border_spacing_V']/2);
13144 $clw = $w- $table['border_spacing_H'];
13145 $clh = $h- $table['border_spacing_V'];
13146 // Set clipping path
13147 $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
13148 $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);
13149 }
13150 else {
13151 $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);
13152 }
13153 }
13154 }
13155 }
13156 /*-- END BACKGROUNDS --*/
13157
13158 // TABLE BORDER - if separate OR collapsed and only table border
13159 if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) {
13160 $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H']/2);
13161 $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H']/2);
13162 $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V']/2);
13163 $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V']/2);
13164 $tbx = $x;
13165 $tby = $y;
13166 $tbw = $w;
13167 $tbh = $h;
13168 $tab_bord = 0;
13169 $corner = '';
13170 if ($i == $firstrow && $horf=='H') { // Top
13171 $tby -= $halfspaceT + ($table['border_details']['T']['w']/2);
13172 $tbh += $halfspaceT + ($table['border_details']['T']['w']/2);
13173 $this->setBorder($tab_bord , _BORDER_TOP);
13174 $corner .= 'T';
13175 }
13176 if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i+$tablehf['rowspan']) == ($lastrow+1))) && $horf=='F') { // Bottom
13177 $tbh += $halfspaceB + ($table['border_details']['B']['w']/2);
13178 $this->setBorder($tab_bord , _BORDER_BOTTOM);
13179 $corner .= 'B';
13180 }
13181 if ($colctr == 1 && $firstSpread) { // Left
13182 $tbx -= $halfspaceL + ($table['border_details']['L']['w']/2);
13183 $tbw += $halfspaceL + ($table['border_details']['L']['w']/2);
13184 $this->setBorder($tab_bord , _BORDER_LEFT);
13185 $corner .= 'L';
13186 }
13187 if ($colctr == count($content[$i]) && $finalSpread) { // Right
13188 $tbw += $halfspaceR + ($table['border_details']['R']['w']/2);
13189 $this->setBorder($tab_bord , _BORDER_RIGHT);
13190 $corner .= 'R';
13191 }
13192 $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'] );
13193 }
13194
13195
13196 }// end column $content
13197 $this->y = $y + $h; //Update y coordinate
13198 }// end row $i
13199 unset($table );
13200 $this->colsums = array();
13201 }
13202 }
13203 /*-- END TABLES --*/
13204
13205
13206 function SetHTMLHeader($header='',$OE='',$write=false) {
13207
13208 $height = 0;
13209 if (is_array($header) && isset($header['html']) && $header['html']) {
13210 $Hhtml = $header['html'];
13211 if ($this->setAutoTopMargin) {
13212 if (isset($header['h'])) { $height = $header['h']; }
13213 else { $height = $this->_gethtmlheight($Hhtml); }
13214 }
13215 }
13216 else if (!is_array($header) && $header) {
13217 $Hhtml = $header;
13218 if ($this->setAutoTopMargin) { $height = $this->_gethtmlheight($Hhtml); }
13219 }
13220 else { $Hhtml = ''; }
13221
13222 if ($OE != 'E') { $OE = 'O'; }
13223 if ($OE == 'E') {
13224
13225 if ($Hhtml) {
13226 $this->HTMLHeaderE['html'] = $Hhtml;
13227 $this->HTMLHeaderE['h'] = $height;
13228 }
13229 else { $this->HTMLHeaderE = ''; }
13230 }
13231 else {
13232
13233 if ($Hhtml) {
13234 $this->HTMLHeader['html'] = $Hhtml;
13235 $this->HTMLHeader['h'] = $height;
13236 }
13237 else { $this->HTMLHeader = ''; }
13238 }
13239 if (!$this->mirrorMargins && $OE == 'E') { return; }
13240 if ($Hhtml=='') { return; }
13241
13242 if ($this->setAutoTopMargin=='pad') {
13243 $this->tMargin = $this->margin_header + $height + $this->orig_tMargin;
13244 if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) { $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin; }
13245 }
13246 else if ($this->setAutoTopMargin=='stretch') {
13247 $this->tMargin = max($this->orig_tMargin, $this->margin_header + $height + $this->autoMarginPadding);
13248 if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) { $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin; }
13249 }
13250 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(); }
13251 }
13252
13253 function SetHTMLFooter($footer='',$OE='') {
13254 $height = 0;
13255 if (is_array($footer) && isset($footer['html']) && $footer['html']) {
13256 $Fhtml = $footer['html'];
13257 if ($this->setAutoBottomMargin) {
13258 if (isset($footer['h'])) { $height = $footer['h']; }
13259 else { $height = $this->_gethtmlheight($Fhtml); }
13260 }
13261 }
13262 else if (!is_array($footer) && $footer) {
13263 $Fhtml = $footer;
13264 if ($this->setAutoBottomMargin) { $height = $this->_gethtmlheight($Fhtml); }
13265 }
13266 else { $Fhtml = ''; }
13267
13268 if ($OE != 'E') { $OE = 'O'; }
13269 if ($OE == 'E') {
13270
13271 if ($Fhtml) {
13272 $this->HTMLFooterE['html'] = $Fhtml;
13273 $this->HTMLFooterE['h'] = $height;
13274 }
13275 else { $this->HTMLFooterE = ''; }
13276 }
13277 else {
13278
13279 if ($Fhtml) {
13280 $this->HTMLFooter['html'] = $Fhtml;
13281 $this->HTMLFooter['h'] = $height;
13282 }
13283 else { $this->HTMLFooter = ''; }
13284 }
13285 if (!$this->mirrorMargins && $OE == 'E') { return; }
13286 if ($Fhtml=='') { return false; }
13287
13288 if ($this->setAutoBottomMargin=='pad') {
13289 $this->bMargin = $this->margin_footer + $height + $this->orig_bMargin;
13290 $this->PageBreakTrigger=$this->h-$this->bMargin ;
13291 if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) { $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin; }
13292 }
13293 else if ($this->setAutoBottomMargin=='stretch') {
13294 $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $height + $this->autoMarginPadding);
13295 $this->PageBreakTrigger=$this->h-$this->bMargin ;
13296 if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) { $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin; }
13297 }
13298 }
13299
13300
13301 function _getHtmlHeight($html) {
13302 $save_state = $this->state;
13303 if($this->state==0) {
13304 $this->AddPage($this->CurOrientation);
13305 }
13306 $this->state = 2;
13307 $this->Reset();
13308 $this->pageoutput[$this->page] = array();
13309 $save_x = $this->x;
13310 $save_y = $this->y;
13311 $this->x = $this->lMargin;
13312 $this->y = $this->margin_header;
13313 $html = str_replace('{PAGENO}',$this->pagenumPrefix.$this->docPageNum($this->page).$this->pagenumSuffix,$html);
13314 $html = str_replace($this->aliasNbPgGp,$this->nbpgPrefix.$this->docPageNumTotal($this->page).$this->nbpgSuffix,$html );
13315 $html = str_replace($this->aliasNbPg,$this->page,$html );
13316 $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', array($this, 'date_callback'),$html ); // mPDF 5.7
13317 $this->HTMLheaderPageLinks = array();
13318 $this->HTMLheaderPageAnnots = array();
13319 $this->HTMLheaderPageForms = array();
13320 $savepb = $this->pageBackgrounds;
13321 $this->writingHTMLheader = true;
13322 $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
13323 $this->writingHTMLheader = false;
13324 $h = ($this->y - $this->margin_header);
13325 $this->Reset();
13326 // mPDF 5.7.2 - Clear in case Float used in Header/Footer
13327 $this->blk[0]['blockContext'] = 0;
13328 $this->blk[0]['float_endpos'] = 0;
13329
13330 $this->pageoutput[$this->page] = array();
13331 $this->headerbuffer = '';
13332 $this->pageBackgrounds = $savepb;
13333 $this->x = $save_x;
13334 $this->y = $save_y;
13335 $this->state = $save_state;
13336 if($save_state==0) {
13337 unset($this->pages[1]);
13338 $this->page = 0;
13339 }
13340 return $h;
13341 }
13342
13343
13344 // Called internally from Header
13345 function writeHTMLHeaders() {
13346
13347 if ($this->mirrorMargins && ($this->page)%2==0) { $OE = 'E'; } // EVEN
13348 else { $OE = 'O'; }
13349 if ($OE == 'E') {
13350 $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeaderE['html'] ;
13351 }
13352 else {
13353 $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeader['html'] ;
13354 }
13355 if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
13356 $this->saveHTMLHeader[$this->page][$OE]['rotate'] = true;
13357 $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->tMargin;
13358 $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->bMargin;
13359 $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
13360 $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
13361 $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->h;
13362 $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->w;
13363 }
13364 else {
13365 $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->lMargin;
13366 $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->rMargin;
13367 $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
13368 $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
13369 $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->w;
13370 $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->h;
13371 }
13372 }
13373
13374 function writeHTMLFooters() {
13375
13376 if ($this->mirrorMargins && ($this->page)%2==0) { $OE = 'E'; } // EVEN
13377 else { $OE = 'O'; }
13378 if ($OE == 'E') {
13379 $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooterE['html'] ;
13380 }
13381 else {
13382 $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooter['html'] ;
13383 }
13384 if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
13385 $this->saveHTMLFooter[$this->page][$OE]['rotate'] = true;
13386 $this->saveHTMLFooter[$this->page][$OE]['ml'] = $this->tMargin;
13387 $this->saveHTMLFooter[$this->page][$OE]['mr'] = $this->bMargin;
13388 $this->saveHTMLFooter[$this->page][$OE]['mt'] = $this->rMargin;
13389 $this->saveHTMLFooter[$this->page][$OE]['mb'] = $this->lMargin;
13390 $this->saveHTMLFooter[$this->page][$OE]['mh'] = $this->margin_header;
13391 $this->saveHTMLFooter[$this->page][$OE]['mf'] = $this->margin_footer;
13392 $this->saveHTMLFooter[$this->page][$OE]['pw'] = $this->h;
13393 $this->saveHTMLFooter[$this->page][$OE]['ph'] = $this->w;
13394 }
13395 else {
13396 $this->saveHTMLFooter[$this->page][$OE]['ml'] = $this->lMargin;
13397 $this->saveHTMLFooter[$this->page][$OE]['mr'] = $this->rMargin;
13398 $this->saveHTMLFooter[$this->page][$OE]['mt'] = $this->tMargin;
13399 $this->saveHTMLFooter[$this->page][$OE]['mb'] = $this->bMargin;
13400 $this->saveHTMLFooter[$this->page][$OE]['mh'] = $this->margin_header;
13401 $this->saveHTMLFooter[$this->page][$OE]['mf'] = $this->margin_footer;
13402 $this->saveHTMLFooter[$this->page][$OE]['pw'] = $this->w;
13403 $this->saveHTMLFooter[$this->page][$OE]['ph'] = $this->h;
13404 }
13405 }
13406
13407 // mPDF 6
13408 function _shareHeaderFooterWidth($cl,$cc,$cr) { // mPDF 6
13409 $l = mb_strlen($cl, 'UTF-8');
13410 $c = mb_strlen($cc, 'UTF-8');
13411 $r = mb_strlen($cr, 'UTF-8');
13412 $s = max($l,$r);
13413 $tw = $c + 2*$s;
13414 if ($tw > 0) { return array(intval($s*100/$tw), intval($c*100/$tw), intval($s*100/$tw)); }
13415 else { return array(33,33,33); }
13416 }
13417
13418 // mPDF 6
13419 // Create an HTML header/footer from array (non-HTML header/footer)
13420 function _createHTMLheaderFooter($arr,$hf) {
13421 $lContent = (isset($arr['L']['content']) ? $arr['L']['content'] : '');
13422 $cContent = (isset($arr['C']['content']) ? $arr['C']['content'] : '');
13423 $rContent = (isset($arr['R']['content']) ? $arr['R']['content'] : '');
13424 list($lw, $cw, $rw) = $this->_shareHeaderFooterWidth($lContent, $cContent, $rContent);
13425 if ($hf=='H') { $valign = 'bottom'; $vpadding = '0 0 '.$this->header_line_spacing.'em 0'; }
13426 else { $valign = 'top'; $vpadding = ''.$this->footer_line_spacing.'em 0 0 0'; }
13427 if ($this->directionality == 'rtl') { // table columns get reversed so need different text-alignment
13428 $talignL = 'right';
13429 $talignR = 'left';
13430 }
13431 else {
13432 $talignL = 'left';
13433 $talignR = 'right';
13434 }
13435 $html = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: '.$valign.'; color: #000000; ';
13436 if (isset($arr['line']) && $arr['line']) { $html .= ' border-'.$valign.': 0.1mm solid #000000;'; }
13437 $html .= '">';
13438 $html .= '<tr>';
13439 $html .= '<td width="'.$lw.'%" style="padding: '.$vpadding.'; text-align: '.$talignL.'; ';
13440 if (isset($arr['L']['font-family'])) { $html .= ' font-family: '.$arr['L']['font-family'].';'; }
13441 if (isset($arr['L']['color'])) { $html .= ' color: '.$arr['L']['color'].';'; }
13442 if (isset($arr['L']['font-size'])) { $html .= ' font-size: '.$arr['L']['font-size'].'pt;'; }
13443 if (isset($arr['L']['font-style'])) {
13444 if ($arr['L']['font-style']=='B' || $arr['L']['font-style']=='BI') { $html .= ' font-weight: bold;'; }
13445 if ($arr['L']['font-style']=='I' || $arr['L']['font-style']=='BI') { $html .= ' font-style: italic;'; }
13446 }
13447 $html .= '">'. $lContent .'</td>';
13448 $html .= '<td width="'.$cw.'%" style="padding: '.$vpadding.'; text-align: center; ';
13449 if (isset($arr['C']['font-family'])) { $html .= ' font-family: '.$arr['C']['font-family'].';'; }
13450 if (isset($arr['C']['color'])) { $html .= ' color: '.$arr['C']['color'].';'; }
13451 if (isset($arr['C']['font-size'])) { $html .= ' font-size: '.$arr['L']['font-size'].'pt;'; }
13452 if (isset($arr['C']['font-style'])) {
13453 if ($arr['C']['font-style']=='B' || $arr['C']['font-style']=='BI') { $html .= ' font-weight: bold;'; }
13454 if ($arr['C']['font-style']=='I' || $arr['C']['font-style']=='BI') { $html .= ' font-style: italic;'; }
13455 }
13456 $html .= '">'. $cContent .'</td>';
13457 $html .= '<td width="'.$rw.'%" style="padding: '.$vpadding.'; text-align: '.$talignR.'; ';
13458 if (isset($arr['R']['font-family'])) { $html .= ' font-family: '.$arr['R']['font-family'].';'; }
13459 if (isset($arr['R']['color'])) { $html .= ' color: '.$arr['R']['color'].';'; }
13460 if (isset($arr['R']['font-size'])) { $html .= ' font-size: '.$arr['R']['font-size'].'pt;'; }
13461 if (isset($arr['R']['font-style'])) {
13462 if ($arr['R']['font-style']=='B' || $arr['R']['font-style']=='BI') { $html .= ' font-weight: bold;'; }
13463 if ($arr['R']['font-style']=='I' || $arr['R']['font-style']=='BI') { $html .= ' font-style: italic;'; }
13464 }
13465 $html .= '">'. $rContent .'</td>';
13466 $html .= '</tr></table>';
13467 return $html;
13468 }
13469
13470 function DefHeaderByName($name,$arr) {
13471 if (!$name) { $name = '_nonhtmldefault'; }
13472 $html = $this->_createHTMLheaderFooter($arr,'H');
13473
13474 $this->pageHTMLheaders[$name]['html'] = $html;
13475 $this->pageHTMLheaders[$name]['h'] = $this->_gethtmlheight($html);
13476 }
13477
13478 function DefFooterByName($name,$arr) {
13479 if (!$name) { $name = '_nonhtmldefault'; }
13480 $html = $this->_createHTMLheaderFooter($arr,'F');
13481
13482 $this->pageHTMLfooters[$name]['html'] = $html;
13483 $this->pageHTMLfooters[$name]['h'] = $this->_gethtmlheight($html);
13484 }
13485
13486 function SetHeaderByName($name,$side='O',$write=false) {
13487 if (!$name) { $name = '_nonhtmldefault'; }
13488 $this->SetHTMLHeader($this->pageHTMLheaders[$name],$side,$write);
13489 }
13490
13491 function SetFooterByName($name,$side='O') {
13492 if (!$name) { $name = '_nonhtmldefault'; }
13493 $this->SetHTMLFooter($this->pageHTMLfooters[$name],$side);
13494 }
13495
13496
13497 function DefHTMLHeaderByName($name,$html) {
13498 if (!$name) { $name = '_default'; }
13499
13500 $this->pageHTMLheaders[$name]['html'] = $html;
13501 $this->pageHTMLheaders[$name]['h'] = $this->_gethtmlheight($html);
13502 }
13503
13504 function DefHTMLFooterByName($name,$html) {
13505 if (!$name) { $name = '_default'; }
13506
13507 $this->pageHTMLfooters[$name]['html'] = $html;
13508 $this->pageHTMLfooters[$name]['h'] = $this->_gethtmlheight($html);
13509 }
13510
13511 function SetHTMLHeaderByName($name,$side='O',$write=false) {
13512 if (!$name) { $name = '_default'; }
13513 $this->SetHTMLHeader($this->pageHTMLheaders[$name],$side,$write);
13514 }
13515
13516 function SetHTMLFooterByName($name,$side='O') {
13517 if (!$name) { $name = '_default'; }
13518 $this->SetHTMLFooter($this->pageHTMLfooters[$name],$side);
13519 }
13520
13521
13522
13523 function SetHeader($Harray=array(),$side='',$write=false) {
13524 $oddhtml = '';
13525 $evenhtml = '';
13526 if (is_string($Harray)) {
13527 if (strlen($Harray)==0) {
13528 $oddhtml = '';
13529 $evenhtml = '';
13530 }
13531 else if (strpos($Harray,'|') !== false) {
13532 $hdet = explode('|',$Harray);
13533 list($lw, $cw, $rw) = $this->_shareHeaderFooterWidth($hdet[0], $hdet[1], $hdet[2]);
13534 $oddhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: bottom; color: #000000; ';
13535 if ($this->defaultheaderfontsize) { $oddhtml .= ' font-size: '.$this->defaultheaderfontsize.'pt;'; }
13536 if ($this->defaultheaderfontstyle) {
13537 if ($this->defaultheaderfontstyle=='B' || $this->defaultheaderfontstyle=='BI') { $oddhtml .= ' font-weight: bold;'; }
13538 if ($this->defaultheaderfontstyle=='I' || $this->defaultheaderfontstyle=='BI') { $oddhtml .= ' font-style: italic;'; }
13539 }
13540 if ($this->defaultheaderline) { $oddhtml .= ' border-bottom: 0.1mm solid #000000;'; }
13541 $oddhtml .= '">';
13542 $oddhtml .= '<tr>';
13543 $oddhtml .= '<td width="'.$lw.'%" style="padding: 0 0 '.$this->header_line_spacing.'em 0; text-align: left; ">'. $hdet[0] .'</td>';
13544 $oddhtml .= '<td width="'.$cw.'%" style="padding: 0 0 '.$this->header_line_spacing.'em 0; text-align: center; ">'. $hdet[1] .'</td>';
13545 $oddhtml .= '<td width="'.$rw.'%" style="padding: 0 0 '.$this->header_line_spacing.'em 0; text-align: right; ">'. $hdet[2] .'</td>';
13546 $oddhtml .= '</tr></table>';
13547
13548 $evenhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: bottom; color: #000000; ';
13549 if ($this->defaultheaderfontsize) { $evenhtml .= ' font-size: '.$this->defaultheaderfontsize.'pt;'; }
13550 if ($this->defaultheaderfontstyle) {
13551 if ($this->defaultheaderfontstyle=='B' || $this->defaultheaderfontstyle=='BI') { $evenhtml .= ' font-weight: bold;'; }
13552 if ($this->defaultheaderfontstyle=='I' || $this->defaultheaderfontstyle=='BI') { $evenhtml .= ' font-style: italic;'; }
13553 }
13554 if ($this->defaultheaderline) { $evenhtml .= ' border-bottom: 0.1mm solid #000000;'; }
13555 $evenhtml .= '">';
13556 $evenhtml .= '<tr>';
13557 $evenhtml .= '<td width="'.$rw.'%" style="padding: 0 0 '.$this->header_line_spacing.'em 0; text-align: left; ">'. $hdet[2] .'</td>';
13558 $evenhtml .= '<td width="'.$cw.'%" style="padding: 0 0 '.$this->header_line_spacing.'em 0; text-align: center; ">'. $hdet[1] .'</td>';
13559 $evenhtml .= '<td width="'.$lw.'%" style="padding: 0 0 '.$this->header_line_spacing.'em 0; text-align: right; ">'. $hdet[0] .'</td>';
13560 $evenhtml .= '</tr></table>';
13561
13562 }
13563 else {
13564 $oddhtml = '<div style="margin: 0; color: #000000; ';
13565 if ($this->defaultheaderfontsize) { $oddhtml .= ' font-size: '.$this->defaultheaderfontsize.'pt;'; }
13566 if ($this->defaultheaderfontstyle) {
13567 if ($this->defaultheaderfontstyle=='B' || $this->defaultheaderfontstyle=='BI') { $oddhtml .= ' font-weight: bold;'; }
13568 if ($this->defaultheaderfontstyle=='I' || $this->defaultheaderfontstyle=='BI') { $oddhtml .= ' font-style: italic;'; }
13569 }
13570 if ($this->defaultheaderline) { $oddhtml .= ' border-bottom: 0.1mm solid #000000;'; }
13571 $oddhtml .= 'text-align: right; ">'. $Harray .'</div>';
13572
13573 $evenhtml = '<div style="margin: 0; color: #000000; ';
13574 if ($this->defaultheaderfontsize) { $evenhtml .= ' font-size: '.$this->defaultheaderfontsize.'pt;'; }
13575 if ($this->defaultheaderfontstyle) {
13576 if ($this->defaultheaderfontstyle=='B' || $this->defaultheaderfontstyle=='BI') { $evenhtml .= ' font-weight: bold;'; }
13577 if ($this->defaultheaderfontstyle=='I' || $this->defaultheaderfontstyle=='BI') { $evenhtml .= ' font-style: italic;'; }
13578 }
13579 if ($this->defaultheaderline) { $evenhtml .= ' border-bottom: 0.1mm solid #000000;'; }
13580 $evenhtml .= 'text-align: left; ">'. $Harray .'</div>';
13581
13582 }
13583 }
13584 else if (is_array($Harray) && !empty($Harray)) {
13585 if ($side=='O') { $odd = $Harray; }
13586 else if ($side=='E') { $even = $Harray; }
13587 else {
13588 $odd = $Harray['odd'];
13589 $even = $Harray['even'];
13590 }
13591 $oddhtml = $this->_createHTMLheaderFooter($odd,'H');
13592
13593 $evenhtml = $this->_createHTMLheaderFooter($even,'H');
13594 }
13595
13596 if ($side=='E') { $this->SetHTMLHeader($evenhtml ,'E', $write); }
13597 else if ($side=='O') { $this->SetHTMLHeader($oddhtml ,'O', $write); }
13598 else {
13599 $this->SetHTMLHeader($oddhtml ,'O', $write);
13600 $this->SetHTMLHeader($evenhtml ,'E', $write);
13601 }
13602
13603 }
13604
13605
13606
13607 function SetFooter($Farray=array(),$side='') {
13608 $oddhtml = '';
13609 $evenhtml = '';
13610 if (is_string($Farray)) {
13611 if (strlen($Farray)==0) {
13612 $oddhtml = '';
13613 $evenhtml = '';
13614 }
13615 else if (strpos($Farray,'|') !== false) {
13616 $hdet = explode('|',$Farray);
13617 $oddhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: top; color: #000000; ';
13618 if ($this->defaultfooterfontsize) { $oddhtml .= ' font-size: '.$this->defaultfooterfontsize.'pt;'; }
13619 if ($this->defaultfooterfontstyle) {
13620 if ($this->defaultfooterfontstyle=='B' || $this->defaultfooterfontstyle=='BI') { $oddhtml .= ' font-weight: bold;'; }
13621 if ($this->defaultfooterfontstyle=='I' || $this->defaultfooterfontstyle=='BI') { $oddhtml .= ' font-style: italic;'; }
13622 }
13623 if ($this->defaultfooterline) { $oddhtml .= ' border-top: 0.1mm solid #000000;'; }
13624 $oddhtml .= '">';
13625 $oddhtml .= '<tr>';
13626 $oddhtml .= '<td width="33%" style="padding: '.$this->footer_line_spacing.'em 0 0 0; text-align: left; ">'. $hdet[0] .'</td>';
13627 $oddhtml .= '<td width="33%" style="padding: '.$this->footer_line_spacing.'em 0 0 0; text-align: center; ">'. $hdet[1] .'</td>';
13628 $oddhtml .= '<td width="33%" style="padding: '.$this->footer_line_spacing.'em 0 0 0; text-align: right; ">'. $hdet[2] .'</td>';
13629 $oddhtml .= '</tr></table>';
13630
13631 $evenhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: top; color: #000000; ';
13632 if ($this->defaultfooterfontsize) { $evenhtml .= ' font-size: '.$this->defaultfooterfontsize.'pt;'; }
13633 if ($this->defaultfooterfontstyle) {
13634 if ($this->defaultfooterfontstyle=='B' || $this->defaultfooterfontstyle=='BI') { $evenhtml .= ' font-weight: bold;'; }
13635 if ($this->defaultfooterfontstyle=='I' || $this->defaultfooterfontstyle=='BI') { $evenhtml .= ' font-style: italic;'; }
13636 }
13637 if ($this->defaultfooterline) { $evenhtml .= ' border-top: 0.1mm solid #000000;'; }
13638 $evenhtml .= '">';
13639 $evenhtml .= '<tr>';
13640 $evenhtml .= '<td width="33%" style="padding: '.$this->footer_line_spacing.'em 0 0 0; text-align: left; ">'. $hdet[2] .'</td>';
13641 $evenhtml .= '<td width="33%" style="padding: '.$this->footer_line_spacing.'em 0 0 0; text-align: center; ">'. $hdet[1] .'</td>';
13642 $evenhtml .= '<td width="33%" style="padding: '.$this->footer_line_spacing.'em 0 0 0; text-align: right; ">'. $hdet[0] .'</td>';
13643 $evenhtml .= '</tr></table>';
13644
13645 }
13646 else {
13647 $oddhtml = '<div style="margin: 0; color: #000000; ';
13648 if ($this->defaultfooterfontsize) { $oddhtml .= ' font-size: '.$this->defaultfooterfontsize.'pt;'; }
13649 if ($this->defaultfooterfontstyle) {
13650 if ($this->defaultfooterfontstyle=='B' || $this->defaultfooterfontstyle=='BI') { $oddhtml .= ' font-weight: bold;'; }
13651 if ($this->defaultfooterfontstyle=='I' || $this->defaultfooterfontstyle=='BI') { $oddhtml .= ' font-style: italic;'; }
13652 }
13653 if ($this->defaultfooterline) { $oddhtml .= ' border-top: 0.1mm solid #000000;'; }
13654 $oddhtml .= 'text-align: right; ">'. $Farray .'</div>';
13655
13656 $evenhtml = '<div style="margin: 0; color: #000000; ';
13657 if ($this->defaultfooterfontsize) { $evenhtml .= ' font-size: '.$this->defaultfooterfontsize.'pt;'; }
13658 if ($this->defaultfooterfontstyle) {
13659 if ($this->defaultfooterfontstyle=='B' || $this->defaultfooterfontstyle=='BI') { $evenhtml .= ' font-weight: bold;'; }
13660 if ($this->defaultfooterfontstyle=='I' || $this->defaultfooterfontstyle=='BI') { $evenhtml .= ' font-style: italic;'; }
13661 }
13662 if ($this->defaultfooterline) { $evenhtml .= ' border-top: 0.1mm solid #000000;'; }
13663 $evenhtml .= 'text-align: left; ">'. $Farray .'</div>';
13664
13665 }
13666 }
13667 else if (is_array($Farray)) {
13668 if ($side=='O') { $odd = $Farray; }
13669 else if ($side=='E') { $even = $Farray; }
13670 else {
13671 if (isset($Farray['odd'])) $odd = $Farray['odd'];
13672 if (isset($Farray['even'])) $even = $Farray['even'];
13673 }
13674
13675 if (isset($odd)) $oddhtml = $this->_createHTMLheaderFooter($odd,'F');
13676
13677 if (isset($even)) $evenhtml = $this->_createHTMLheaderFooter($even,'F');
13678
13679 }
13680 /*-- HTMLfooterS-FOOTERS --*/
13681 if ($side=='E') { $this->SetHTMLfooter($evenhtml ,'E'); }
13682 else if ($side=='O') { $this->SetHTMLfooter($oddhtml ,'O'); }
13683 else {
13684 $this->SetHTMLfooter($oddhtml ,'O');
13685 $this->SetHTMLfooter($evenhtml ,'E');
13686 }
13687 /*-- END HTMLfooterS-FOOTERS --*/
13688 }
13689
13690 /*-- WATERMARK --*/
13691 function SetWatermarkText($txt='', $alpha=-1) {
13692 if ($alpha>=0) $this->watermarkTextAlpha = $alpha;
13693 $this->watermarkText = $txt;
13694 }
13695
13696 function SetWatermarkImage($src, $alpha=-1, $size='D', $pos='F') {
13697 if ($alpha>=0) $this->watermarkImageAlpha = $alpha;
13698 $this->watermarkImage = $src;
13699 $this->watermark_size = $size;
13700 $this->watermark_pos = $pos;
13701 }
13702 /*-- END WATERMARK --*/
13703
13704
13705 //Page footer
13706 function Footer() {
13707 /*-- CSS-PAGE --*/
13708 // PAGED MEDIA - CROP / CROSS MARKS from @PAGE
13709 if ($this->show_marks == 'CROP' || $this->show_marks == 'CROPCROSS') {
13710 // Show TICK MARKS
13711 $this->SetLineWidth(0.1); // = 0.1 mm
13712 $this->SetDColor($this->ConvertColor(0));
13713 $l = $this->cropMarkLength;
13714 $m = $this->cropMarkMargin; // Distance of crop mark from margin
13715 $b = $this->nonPrintMargin; // Non-printable border at edge of paper sheet
13716 $ax1 = $b;
13717 $bx = $this->page_box['outer_width_LR'] - $m;
13718 $ax = max($ax1, $bx-$l);
13719 $cx1 = $this->w - $b;
13720 $dx = $this->w - $this->page_box['outer_width_LR'] + $m;
13721 $cx = min($cx1, $dx+$l);
13722 $ay1 = $b;
13723 $by = $this->page_box['outer_width_TB'] - $m;
13724 $ay = max($ay1, $by-$l);
13725 $cy1 = $this->h - $b;
13726 $dy = $this->h - $this->page_box['outer_width_TB'] + $m;
13727 $cy = min($cy1, $dy+$l);
13728
13729 $this->Line($ax, $this->page_box['outer_width_TB'], $bx, $this->page_box['outer_width_TB']);
13730 $this->Line($cx, $this->page_box['outer_width_TB'], $dx, $this->page_box['outer_width_TB']);
13731 $this->Line($ax, $this->h - $this->page_box['outer_width_TB'], $bx, $this->h - $this->page_box['outer_width_TB']);
13732 $this->Line($cx, $this->h - $this->page_box['outer_width_TB'], $dx, $this->h - $this->page_box['outer_width_TB']);
13733 $this->Line($this->page_box['outer_width_LR'], $ay, $this->page_box['outer_width_LR'], $by);
13734 $this->Line($this->page_box['outer_width_LR'], $cy, $this->page_box['outer_width_LR'], $dy);
13735 $this->Line($this->w - $this->page_box['outer_width_LR'], $ay, $this->w - $this->page_box['outer_width_LR'], $by);
13736 $this->Line($this->w - $this->page_box['outer_width_LR'], $cy, $this->w - $this->page_box['outer_width_LR'], $dy);
13737
13738 if ($this->printers_info) {
13739 $hd = date('Y-m-d H:i').' Page '.$this->page.' of {nb}';
13740 $this->SetTColor($this->ConvertColor(0));
13741 $this->SetFont('arial','',7.5,true,true);
13742 $this->x = $this->page_box['outer_width_LR'] + 1.5;
13743 $this->y = 1;
13744 $this->Cell($headerpgwidth ,$this->FontSize,$hd,0,0,'L',0,'',0,0,0,'M');
13745 $this->SetFont($this->default_font,'',$this->original_default_font_size);
13746 }
13747
13748 }
13749 if ($this->show_marks == 'CROSS' || $this->show_marks == 'CROPCROSS') {
13750 $this->SetLineWidth(0.1); // = 0.1 mm
13751 $this->SetDColor($this->ConvertColor(0));
13752 $l = 14 /2; // longer length of the cross line (half)
13753 $w = 6 /2; // shorter width of the cross line (half)
13754 $r = 1.2; // radius of circle
13755 $m = $this->crossMarkMargin; // Distance of cross mark from margin
13756 $x1 = $this->page_box['outer_width_LR'] - $m;
13757 $x2 = $this->w - $this->page_box['outer_width_LR'] + $m;
13758 $y1 = $this->page_box['outer_width_TB'] - $m;
13759 $y2 = $this->h - $this->page_box['outer_width_TB'] + $m;
13760 // Left
13761 $this->Circle($x1, $this->h/2, $r, 'S') ;
13762 $this->Line($x1-$w, $this->h/2, $x1+$w, $this->h/2);
13763 $this->Line($x1, $this->h/2-$l, $x1, $this->h/2+$l);
13764 // Right
13765 $this->Circle($x2, $this->h/2, $r, 'S') ;
13766 $this->Line($x2-$w, $this->h/2, $x2+$w, $this->h/2);
13767 $this->Line($x2, $this->h/2-$l, $x2, $this->h/2+$l);
13768 // Top
13769 $this->Circle($this->w/2, $y1, $r, 'S') ;
13770 $this->Line($this->w/2, $y1-$w, $this->w/2, $y1+$w);
13771 $this->Line($this->w/2-$l, $y1, $this->w/2+$l, $y1);
13772 // Bottom
13773 $this->Circle($this->w/2, $y2, $r, 'S') ;
13774 $this->Line($this->w/2, $y2-$w, $this->w/2, $y2+$w);
13775 $this->Line($this->w/2-$l, $y2, $this->w/2+$l, $y2);
13776 }
13777
13778 /*-- END CSS-PAGE --*/
13779
13780 // mPDF 6
13781 // If @page set non-HTML headers/footers named, they were not read until later in the HTML code - so now set them
13782 if ($this->page==1) {
13783 if ($this->firstPageBoxHeader) {
13784 if (isset($this->pageHTMLheaders[$this->firstPageBoxHeader])) { $this->HTMLHeader = $this->pageHTMLheaders[$this->firstPageBoxHeader]; }
13785 $this->Header();
13786 }
13787 if ($this->firstPageBoxFooter) {
13788 if (isset($this->pageHTMLfooters[$this->firstPageBoxFooter])) { $this->HTMLFooter = $this->pageHTMLfooters[$this->firstPageBoxFooter]; }
13789 }
13790 $this->firstPageBoxHeader='';
13791 $this->firstPageBoxFooter='';
13792 }
13793
13794
13795 if (($this->mirrorMargins && ($this->page%2==0) && $this->HTMLFooterE) || ($this->mirrorMargins && ($this->page%2==1) && $this->HTMLFooter) || (!$this->mirrorMargins && $this->HTMLFooter)) {
13796 $this->writeHTMLFooters();
13797 }
13798
13799 /*-- WATERMARK --*/
13800 if (($this->watermarkText) && ($this->showWatermarkText)) {
13801 $this->watermark( $this->watermarkText, 45, 120, $this->watermarkTextAlpha); // Watermark text
13802 }
13803 if (($this->watermarkImage) && ($this->showWatermarkImage)) {
13804 $this->watermarkImg( $this->watermarkImage, $this->watermarkImageAlpha); // Watermark image
13805 }
13806 /*-- END WATERMARK --*/
13807
13808 }
13809
13810
13811 /*-- HYPHENATION --*/
13812 ///////////////////
13813 ///////////////////
13814 // HYPHENATION
13815 ///////////////////
13816 ///////////////////
13817 // Word hyphenation
13818 // mPDF 6
13819 function hyphenateWord($word, $currptr) {
13820 // Do everything inside this function in utf-8
13821 // Don't hyphenate web addresses
13822 if (preg_match('/^(http:|www\.)/',$word)) { return -1; }
13823
13824 $ptr = -1;
13825
13826 // Get dictionary
13827 if (!$this->loadedSHYdictionary) {
13828 if (file_exists(_MPDF_PATH.'patterns/dictionary.txt')) {
13829 $this->SHYdictionary = file(_MPDF_PATH.'patterns/dictionary.txt',FILE_SKIP_EMPTY_LINES);
13830 foreach($this->SHYdictionary as $entry) {
13831 $entry = trim($entry);
13832 $poss = array();
13833 $offset = 0;
13834 $p = true;
13835 $wl = mb_strlen($entry ,'UTF-8');
13836 while($offset < $wl) {
13837 $p = mb_strpos($entry, '/', $offset, 'UTF-8');
13838 if ($p !== false) { $poss[] = $p - count($poss); }
13839 else { break; }
13840 $offset = $p+1;
13841 }
13842 if (count($poss)) { $this->SHYdictionaryWords[str_replace('/', '', mb_strtolower($entry))] = $poss; }
13843 }
13844 }
13845 $this->loadedSHYdictionary = true;
13846 }
13847
13848 if (!in_array($this->SHYlang,$this->SHYlanguages)) { return -1; }
13849 // If no pattern loaded or not the best one
13850 if (count($this->SHYpatterns) < 1 || ($this->loadedSHYpatterns && $this->loadedSHYpatterns != $this->SHYlang)) {
13851 include(_MPDF_PATH."patterns/" . $this->SHYlang . ".php");
13852 $patterns = explode(' ', $patterns);
13853 $new_patterns = array();
13854 for($i = 0; $i < count($patterns); $i++) {
13855 $value = $patterns[$i];
13856 $new_patterns[preg_replace('/[0-9]/', '', $value)] = $value;
13857 }
13858 $this->SHYpatterns = $new_patterns;
13859 $this->loadedSHYpatterns = $this->SHYlang;
13860 }
13861
13862 if ($this->usingCoreFont) { $word = mb_convert_encoding($word,'UTF-8',$this->mb_enc); }
13863
13864 $prepre = '';
13865 $postpost = '';
13866 $startpunctuation = "\xc2\xab\xc2\xbf\xe2\x80\x98\xe2\x80\x9b\xe2\x80\x9c\xe2\x80\x9f";
13867 $endpunctuation = "\xe2\x80\x9e\xe2\x80\x9d\xe2\x80\x9a\xe2\x80\x99\xc2\xbb";
13868
13869
13870 if (preg_match('/^(["\''.$startpunctuation .'])+(.{'.$this->SHYcharmin.',})$/u',$word,$m)) {
13871 $prepre = $m[1];
13872 $word = $m[2];
13873 }
13874 if (preg_match('/^(.{'.$this->SHYcharmin.',})([\'\.,;:!?"'.$endpunctuation .']+)$/u',$word,$m)) {
13875 $word = $m[1];
13876 $postpost = $m[2];
13877 }
13878 if(mb_strlen($word,'UTF-8') < $this->SHYcharmin) {
13879 return -1;
13880 }
13881 $success = false;
13882
13883 $preprelen = mb_strlen($prepre);
13884
13885 if(isset($this->SHYdictionaryWords[mb_strtolower($word)])) {
13886 foreach($this->SHYdictionaryWords[mb_strtolower($word)] AS $i) {
13887 if (($i+$preprelen) >= $currptr) { break ; }
13888 $ptr = $i+$preprelen;
13889 $success = true;
13890 }
13891 }
13892
13893 if (!$success) {
13894 $text_word = '_' . $word . '_';
13895 $word_length = mb_strlen($text_word,'UTF-8');
13896 $text_word = mb_strtolower($text_word,'UTF-8');
13897 $hyphenated_word = array();
13898 $numb3rs = array('0' => true, '1' => true, '2' => true, '3' => true, '4' => true, '5' => true, '6' => true, '7' => true, '8' => true, '9' => true);
13899 for($position = 0; $position <= ($word_length - $this->SHYcharmin); $position++) {
13900 $maxwins = min(($word_length - $position), $this->SHYcharmax);
13901 for($win = $this->SHYcharmin; $win <= $maxwins; $win++) {
13902 if(isset($this->SHYpatterns[mb_substr($text_word, $position, $win,'UTF-8')])) {
13903 $pattern = $this->SHYpatterns[mb_substr($text_word, $position, $win,'UTF-8')];
13904 $digits = 1;
13905 $pattern_length = mb_strlen($pattern,'UTF-8');
13906 for($i = 0; $i < $pattern_length; $i++) {
13907 $char = $pattern[$i];
13908 if(isset($numb3rs[$char])) {
13909 $zero = ($i == 0) ? $position - 1 : $position + $i - $digits;
13910 if(!isset($hyphenated_word[$zero]) || $hyphenated_word[$zero] != $char) $hyphenated_word[$zero] = $char;
13911 $digits++;
13912 }
13913 }
13914 }
13915 }
13916 }
13917 for($i = $this->SHYleftmin; $i <= (mb_strlen($word,'UTF-8') - $this->SHYrightmin); $i++) {
13918 if(isset($hyphenated_word[$i]) && $hyphenated_word[$i] % 2 != 0) {
13919 if (($i+$preprelen) > $currptr) { break ; }
13920 $ptr = $i+$preprelen;
13921 }
13922 }
13923 }
13924 return $ptr;
13925
13926 }
13927 /*-- END HYPHENATION --*/
13928
13929
13930 /*-- HTML-CSS --*/
13931 ///////////////////
13932 /// HTML parser ///
13933 ///////////////////
13934 function WriteHTML($html,$sub=0,$init=true,$close=true) {
13935 // $sub - 0 = default; 1=headerCSS only; 2=HTML body (parts) only; 3 - HTML parses only
13936 // 4 - writes HTML headers/Fixed pos DIVs - stores in buffer - for single page only
13937 // $close - if false Leaves buffers etc. in current state, so that it can continue a block etc.
13938 // $init - Clears and sets buffers to Top level block etc.
13939
13940 if (empty($html)) { $html = ''; }
13941 if ($this->progressBar) { $this->UpdateProgressBar(1,0,'Parsing CSS & Headers'); } // *PROGRESS-BAR*
13942
13943 if ($init) {
13944 $this->headerbuffer='';
13945 $this->textbuffer = array();
13946 $this->fixedPosBlockSave = array();
13947 }
13948 if ($sub == 1) { $html = '<style> '.$html.' </style>'; } // stylesheet only
13949
13950 if ($this->allow_charset_conversion) {
13951 if ($sub < 1) {
13952 $this->ReadCharset($html);
13953 }
13954 if ($this->charset_in && $sub!=4) {
13955 $success = iconv($this->charset_in,'UTF-8//TRANSLIT',$html);
13956 if ($success) { $html = $success; }
13957 }
13958 }
13959 $html = $this->purify_utf8($html,false);
13960 if ($init) {
13961 $this->blklvl = 0;
13962 $this->lastblocklevelchange = 0;
13963 $this->blk = array();
13964 $this->initialiseBlock($this->blk[0]);
13965 $this->blk[0]['width'] =& $this->pgwidth;
13966 $this->blk[0]['inner_width'] =& $this->pgwidth;
13967 $this->blk[0]['blockContext'] = $this->blockContext;
13968 }
13969
13970 $zproperties = array();
13971 if ($sub < 2) {
13972 $this->ReadMetaTags($html);
13973
13974 if (preg_match('/<base[^>]*href=["\']([^"\'>]*)["\']/i', $html, $m)) {
13975 $this->SetBasePath($m[1]);
13976 }
13977 $html = $this->cssmgr->ReadCSS($html);
13978
13979 if ($this->autoLangToFont && !$this->usingCoreFont && preg_match('/<html [^>]*lang=[\'\"](.*?)[\'\"]/ism',$html,$m)) {
13980 $html_lang = $m[1];
13981 }
13982
13983 if (preg_match('/<html [^>]*dir=[\'\"]\s*rtl\s*[\'\"]/ism',$html)) {
13984 $zproperties['DIRECTION'] = 'rtl';
13985 }
13986
13987 // allow in-line CSS for body tag to be parsed // Get <body> tag inline CSS
13988 if (preg_match('/<body([^>]*)>(.*?)<\/body>/ism',$html,$m) || preg_match('/<body([^>]*)>(.*)$/ism',$html,$m)) {
13989 $html = $m[2];
13990 // Changed to allow style="background: url('bg.jpg')"
13991 if (preg_match('/style=[\"](.*?)[\"]/ism',$m[1],$mm) || preg_match('/style=[\'](.*?)[\']/ism',$m[1],$mm)) {
13992 $zproperties = $this->cssmgr->readInlineCSS($mm[1]);
13993 }
13994 if (preg_match('/dir=[\'\"]\s*rtl\s*[\'\"]/ism',$m[1])) {
13995 $zproperties['DIRECTION'] = 'rtl';
13996 }
13997 if (isset($html_lang) && $html_lang) { $zproperties['LANG'] = $html_lang; }
13998 if ($this->autoLangToFont && !$this->onlyCoreFonts && preg_match('/lang=[\'\"](.*?)[\'\"]/ism',$m[1],$mm)) {
13999 $zproperties['LANG'] = $mm[1];
14000 }
14001
14002 }
14003 }
14004 $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
14005 if ($zproperties) { $properties = $this->cssmgr->array_merge_recursive_unique($properties,$zproperties); }
14006
14007 if (isset($properties['DIRECTION']) && $properties['DIRECTION']) {
14008 $this->cssmgr->CSS['BODY']['DIRECTION'] = $properties['DIRECTION'];
14009 }
14010 if (!isset($this->cssmgr->CSS['BODY']['DIRECTION'])) {
14011 $this->cssmgr->CSS['BODY']['DIRECTION'] = $this->directionality;
14012 }
14013 else { $this->SetDirectionality($this->cssmgr->CSS['BODY']['DIRECTION']); }
14014
14015 $this->setCSS($properties,'','BODY');
14016
14017 $this->blk[0]['InlineProperties'] = $this->saveInlineProperties();
14018
14019 if ($sub == 1) { return ''; }
14020 if (!isset($this->cssmgr->CSS['BODY'])) { $this->cssmgr->CSS['BODY'] = array(); }
14021
14022 /*-- BACKGROUNDS --*/
14023 if (isset($properties['BACKGROUND-GRADIENT'])) {
14024 $this->bodyBackgroundGradient = $properties['BACKGROUND-GRADIENT'];
14025 }
14026
14027 if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE']) {
14028 $ret = $this->SetBackground($properties, $this->pgwidth);
14029 if ($ret) { $this->bodyBackgroundImage = $ret; }
14030 }
14031 /*-- END BACKGROUNDS --*/
14032
14033 /*-- CSS-PAGE --*/
14034 // If page-box is set
14035 if ($this->state==0 && ((isset($this->cssmgr->CSS['@PAGE']) && $this->cssmgr->CSS['@PAGE']) || (isset($this->cssmgr->CSS['@PAGE>>PSEUDO>>FIRST']) && $this->cssmgr->CSS['@PAGE>>PSEUDO>>FIRST'])) ) { // mPDF 5.7.3
14036 $this->page_box['current'] = '';
14037 $this->page_box['using'] = true;
14038 list($pborientation,$pbmgl,$pbmgr,$pbmgt,$pbmgb,$pbmgh,$pbmgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS('', false, 'O');
14039 $this->DefOrientation = $this->CurOrientation = $pborientation;
14040 $this->orig_lMargin = $this->DeflMargin = $pbmgl;
14041 $this->orig_rMargin = $this->DefrMargin = $pbmgr;
14042 $this->orig_tMargin = $this->tMargin = $pbmgt;
14043 $this->orig_bMargin = $this->bMargin = $pbmgb;
14044 $this->orig_hMargin = $this->margin_header = $pbmgh;
14045 $this->orig_fMargin = $this->margin_footer = $pbmgf;
14046 list($pborientation,$pbmgl,$pbmgr,$pbmgt,$pbmgb,$pbmgh,$pbmgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS('', true, 'O'); // first page
14047 $this->show_marks = $marks;
14048 if ($hname) $this->firstPageBoxHeader = $hname;
14049 if ($fname) $this->firstPageBoxFooter = $fname;
14050 }
14051 /*-- END CSS-PAGE --*/
14052
14053 $parseonly = false;
14054 $this->bufferoutput = false;
14055 if ($sub == 3) {
14056 $parseonly = true;
14057 // Close any open block tags
14058 $arr=array();
14059 $ai=0;
14060 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag'],$arr,$ai); }
14061 // Output any text left in buffer
14062 if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); }
14063 $this->textbuffer=array();
14064 }
14065 else if ($sub == 4) {
14066 // Close any open block tags
14067 $arr=array();
14068 $ai=0;
14069 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag'],$arr,$ai); }
14070 // Output any text left in buffer
14071 if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); }
14072 $this->bufferoutput = true;
14073 $this->textbuffer=array();
14074 $this->headerbuffer='';
14075 $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
14076 $this->setCSS($properties,'','BODY');
14077 }
14078
14079 mb_internal_encoding('UTF-8');
14080
14081 $html = $this->AdjustHTML($html, $this->tabSpaces); //Try to make HTML look more like XHTML
14082
14083 if ($this->autoScriptToLang) { $html = $this->markScriptToLang($html); }
14084
14085 preg_match_all('/<htmlpageheader([^>]*)>(.*?)<\/htmlpageheader>/si',$html,$h);
14086 for($i=0;$i<count($h[1]);$i++) {
14087 if (preg_match('/name=[\'|\"](.*?)[\'|\"]/',$h[1][$i],$n)) {
14088 $this->pageHTMLheaders[$n[1]]['html'] = $h[2][$i];
14089 $this->pageHTMLheaders[$n[1]]['h'] = $this->_gethtmlheight($h[2][$i]);
14090 }
14091 }
14092 preg_match_all('/<htmlpagefooter([^>]*)>(.*?)<\/htmlpagefooter>/si',$html,$f);
14093 for($i=0;$i<count($f[1]);$i++) {
14094 if (preg_match('/name=[\'|\"](.*?)[\'|\"]/',$f[1][$i],$n)) {
14095 $this->pageHTMLfooters[$n[1]]['html'] = $f[2][$i];
14096 $this->pageHTMLfooters[$n[1]]['h'] = $this->_gethtmlheight($f[2][$i]);
14097 }
14098 }
14099
14100 $html = preg_replace('/<htmlpageheader.*?<\/htmlpageheader>/si','',$html);
14101 $html = preg_replace('/<htmlpagefooter.*?<\/htmlpagefooter>/si','',$html);
14102
14103 if($this->state==0 && $sub!=1 && $sub!=3 && $sub!=4) {
14104 $this->AddPage($this->CurOrientation);
14105 }
14106
14107
14108 if (isset($hname) && preg_match('/^html_(.*)$/i',$hname,$n)) $this->SetHTMLHeader($this->pageHTMLheaders[$n[1]],'O',true);
14109 if (isset($fname) && preg_match('/^html_(.*)$/i',$fname,$n)) $this->SetHTMLFooter($this->pageHTMLfooters[$n[1]],'O');
14110
14111
14112
14113 $html=str_replace('<?','< ',$html); //Fix '<?XML' bug from HTML code generated by MS Word
14114
14115 $this->checkSIP = false;
14116 $this->checkSMP = false;
14117 $this->checkCJK = false;
14118 if ($this->onlyCoreFonts) { $html = $this->SubstituteChars($html); }
14119 else {
14120 if (preg_match("/([".$this->pregRTLchars."])/u", $html)) { $this->biDirectional = true; } // *OTL*
14121 if (preg_match("/([\x{20000}-\x{2FFFF}])/u", $html)) { $this->checkSIP = true; }
14122 if (preg_match("/([\x{10000}-\x{1FFFF}])/u", $html)) { $this->checkSMP = true; }
14123 /*-- CJK-FONTS --*/
14124 if (preg_match("/([".$this->pregCJKchars."])/u", $html)) { $this->checkCJK = true; }
14125 /*-- END CJK-FONTS --*/
14126 }
14127
14128 // Don't allow non-breaking spaces that are converted to substituted chars or will break anyway and mess up table width calc.
14129 $html = str_replace('<tta>160</tta>',chr(32),$html);
14130 $html = str_replace('</tta><tta>','|',$html);
14131 $html = str_replace('</tts><tts>','|',$html);
14132 $html = str_replace('</ttz><ttz>','|',$html);
14133
14134 //Add new supported tags in the DisableTags function
14135 $html=strip_tags($html,$this->enabledtags); //remove all unsupported tags, but the ones inside the 'enabledtags' string
14136
14137 //Explode the string in order to parse the HTML code
14138 $a=preg_split('/<(.*?)>/ms',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
14139 // ? more accurate regexp that allows e.g. <a name="Silly <name>">
14140 // if changing - also change in fn.SubstituteChars()
14141 // $a = preg_split ('/<((?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+)>/ms', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
14142
14143 if ($this->mb_enc) {
14144 mb_internal_encoding($this->mb_enc);
14145 }
14146 $pbc = 0;
14147 if ($this->progressBar) { $this->UpdateProgressBar(1,0); } // *PROGRESS-BAR*
14148 $this->subPos = -1;
14149 $cnt = count($a);
14150 for($i=0;$i<$cnt; $i++) {
14151 $e = $a[$i];
14152 if($i%2==0) {
14153 //TEXT
14154 if ($this->blk[$this->blklvl]['hide']) { continue; }
14155 if ($this->inlineDisplayOff) { continue; }
14156 if ($this->inMeter) { continue; }
14157
14158 if ($this->inFixedPosBlock) { $this->fixedPosBlock .= $e; continue; } // *CSS-POSITION*
14159 if (strlen($e) == 0) { continue; }
14160
14161 if ($this->ignorefollowingspaces && !$this->ispre) {
14162 if (strlen(ltrim($e)) == 0) { continue; }
14163 if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats' && substr($e,0,1) == ' ') {
14164 $this->ignorefollowingspaces = false;
14165 $e = ltrim($e);
14166 }
14167 }
14168
14169 $this->OTLdata = NULL; // mPDF 5.7.1
14170
14171 $e = strcode2utf($e);
14172 $e = $this->lesser_entity_decode($e);
14173
14174 if ($this->usingCoreFont) {
14175 // If core font is selected in document which is not onlyCoreFonts - substitute with non-core font
14176 if ($this->useSubstitutions && !$this->onlyCoreFonts && $this->subPos<$i && !$this->specialcontent) {
14177 $cnt += $this->SubstituteCharsNonCore($a, $i, $e);
14178 }
14179 // CONVERT ENCODING
14180 $e = mb_convert_encoding($e,$this->mb_enc,'UTF-8');
14181 if ($this->textvar & FT_UPPERCASE) { $e = mb_strtoupper($e,$this->mb_enc); } // mPDF 5.7.1
14182 else if ($this->textvar & FT_LOWERCASE) { $e = mb_strtolower($e,$this->mb_enc); } // mPDF 5.7.1
14183 else if ($this->textvar & FT_CAPITALIZE) { $e = mb_convert_case($e, MB_CASE_TITLE, "UTF-8"); } // mPDF 5.7.1
14184 }
14185 else {
14186 if ($this->checkSIP && $this->CurrentFont['sipext'] && $this->subPos<$i && (!$this->specialcontent || !$this->useActiveForms)) {
14187 $cnt += $this->SubstituteCharsSIP($a, $i, $e);
14188 }
14189
14190 if ($this->useSubstitutions && !$this->onlyCoreFonts && $this->CurrentFont['type']!='Type0' && $this->subPos<$i && (!$this->specialcontent || !$this->useActiveForms)) {
14191 $cnt += $this->SubstituteCharsMB($a, $i, $e);
14192 }
14193
14194 if ($this->textvar & FT_UPPERCASE) { $e = mb_strtoupper($e,$this->mb_enc); }
14195 else if ($this->textvar & FT_LOWERCASE) { $e = mb_strtolower($e,$this->mb_enc); }
14196 else if ($this->textvar & FT_CAPITALIZE) { $e = mb_convert_case($e, MB_CASE_TITLE, "UTF-8"); }
14197
14198 /*-- OTL --*/
14199 // Use OTL OpenType Table Layout - GSUB & GPOS
14200 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL'] && (!$this->specialcontent || !$this->useActiveForms)) {
14201 $e = $this->otl->applyOTL($e, $this->CurrentFont['useOTL']);
14202 $this->OTLdata = $this->otl->OTLdata;
14203 $this->otl->removeChar($e, $this->OTLdata , "\xef\xbb\xbf"); // Remove ZWNBSP (also Byte order mark FEFF)
14204 }
14205 /*-- END OTL --*/
14206 else { // *OTL*
14207 // removes U+200E/U+200F LTR and RTL mark and U+200C/U+200D Zero-width Joiner and Non-joiner
14208 $e = preg_replace("/[\xe2\x80\x8c\xe2\x80\x8d\xe2\x80\x8e\xe2\x80\x8f]/u",'',$e);
14209 $e = preg_replace("/[\xef\xbb\xbf]/u",'',$e); // Remove ZWNBSP (also Byte order mark FEFF)
14210 } // *OTL*
14211 }
14212 if (($this->tts) || ($this->ttz) || ($this->tta)) {
14213 $es = explode('|',$e);
14214 $e = '';
14215 foreach($es AS $val) {
14216 $e .= chr($val);
14217 }
14218 }
14219
14220 // FORM ELEMENTS
14221 if ($this->specialcontent) {
14222 /*-- FORMS --*/
14223 //SELECT tag (form element)
14224 if ($this->specialcontent == "type=select") {
14225 $e = ltrim($e);
14226 if (!empty($this->OTLdata)) { $this->otl->trimOTLdata($this->OTLdata, true, false); } // *OTL*
14227 $stringwidth = $this->GetStringWidth($e);
14228 if (!isset($this->selectoption['MAXWIDTH']) || $stringwidth > $this->selectoption['MAXWIDTH']) { $this->selectoption['MAXWIDTH'] = $stringwidth; }
14229 if (!isset($this->selectoption['SELECTED']) || $this->selectoption['SELECTED'] == '') {
14230 $this->selectoption['SELECTED'] = $e;
14231 if (!empty($this->OTLdata)) { $this->selectoption['SELECTED-OTLDATA'] = $this->OTLdata; } // *OTL*
14232 }
14233 // Active Forms
14234 if (isset($this->selectoption['ACTIVE']) && $this->selectoption['ACTIVE']) {
14235 $this->selectoption['ITEMS'][]=array('exportValue'=>$this->selectoption['currentVAL'], 'content'=>$e, 'selected'=>$this->selectoption['currentSEL']);
14236 }
14237 $this->OTLdata = array();
14238 }
14239 // TEXTAREA
14240 else {
14241 $objattr = unserialize($this->specialcontent);
14242 $objattr['text'] = $e;
14243 $objattr['OTLdata'] = $this->OTLdata;
14244 $this->OTLdata = array();
14245 $te = "\xbb\xa4\xactype=textarea,objattr=".serialize($objattr)."\xbb\xa4\xac";
14246 if ($this->tdbegin) {
14247 $this->_saveCellTextBuffer($te, $this->HREF);
14248 }
14249 else {
14250 $this->_saveTextBuffer($te, $this->HREF);
14251 }
14252 }
14253 /*-- END FORMS --*/
14254 }
14255
14256 // TABLE
14257 else if ($this->tableLevel) {
14258 /*-- TABLES --*/
14259 if ($this->tdbegin) {
14260 if (($this->ignorefollowingspaces) && !$this->ispre) {
14261 $e = ltrim($e);
14262 if (!empty($this->OTLdata)) { $this->otl->trimOTLdata($this->OTLdata, true, false); } // *OTL*
14263 }
14264 if ($e || $e==='0') {
14265 if ($this->blockjustfinished && $this->cell[$this->row][$this->col]['s']>0) {
14266 $this->_saveCellTextBuffer("\n");
14267 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
14268 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
14269 }
14270 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
14271 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
14272 }
14273 $this->cell[$this->row][$this->col]['s'] = 0;// reset
14274 }
14275 $this->blockjustfinished=false;
14276
14277 if (!isset($this->cell[$this->row][$this->col]['R']) || !$this->cell[$this->row][$this->col]['R']) {
14278 if (isset($this->cell[$this->row][$this->col]['s'])) {
14279 $this->cell[$this->row][$this->col]['s'] += $this->GetStringWidth($e, false, $this->OTLdata, $this->textvar);
14280 }
14281 else { $this->cell[$this->row][$this->col]['s'] = $this->GetStringWidth($e, false, $this->OTLdata, $this->textvar); }
14282 if (!empty($this->spanborddet)) {
14283 $this->cell[$this->row][$this->col]['s'] += (isset($this->spanborddet['L']['w']) ? $this->spanborddet['L']['w'] : 0) + (isset($this->spanborddet['R']['w']) ? $this->spanborddet['R']['w'] : 0);
14284 }
14285 }
14286 $this->_saveCellTextBuffer($e, $this->HREF);
14287 if (substr($this->cell[$this->row][$this->col]['a'],0,1) == 'D') {
14288 $dp = $this->decimal_align[substr($this->cell[$this->row][$this->col]['a'],0,2)];
14289 $s = preg_split('/'.preg_quote($dp,'/').'/', $e, 2); // ? needs to be /u if not core
14290 $s0 = $this->GetStringWidth($s[0], false);
14291 if (isset($s[1]) && $s[1]) { $s1 = $this->GetStringWidth(($s[1].$dp), false); }
14292 else $s1 = 0;
14293 if (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'])) {
14294 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'] = $s0;
14295 }
14296 else {
14297 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'] = max($s0, $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0']);
14298 }
14299 if (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'])) {
14300 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'] = $s1;
14301 }
14302 else {
14303 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'] = max($s1, $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1']);
14304 }
14305 }
14306
14307 if ($this->tableLevel==1 && $this->useGraphs) {
14308 $this->graphs[$this->currentGraphId]['data'][$this->row][$this->col] = $e;
14309 }
14310 $this->nestedtablejustfinished = false;
14311 $this->linebreakjustfinished=false;
14312 }
14313 }
14314 /*-- END TABLES --*/
14315 }
14316 // ALL ELSE
14317 else {
14318 if ($this->ignorefollowingspaces && !$this->ispre) {
14319 $e = ltrim($e);
14320 if (!empty($this->OTLdata)) { $this->otl->trimOTLdata($this->OTLdata, true, false); } // *OTL*
14321 }
14322 if ($e || $e==='0') $this->_saveTextBuffer($e, $this->HREF);
14323 }
14324 if ($e || $e==='0') $this->ignorefollowingspaces=false; // mPDF 6
14325 if (substr($e,-1,1) == ' ' && !$this->ispre && $this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
14326 $this->ignorefollowingspaces = true;
14327 }
14328 }
14329
14330
14331 else { // TAG **
14332 if(isset($e[0]) && $e[0]=='/') {
14333 /*-- PROGRESS-BAR --*/
14334 if ($this->progressBar) { // 10% increments
14335 if (intval($i*10/$cnt) != $pbc) { $pbc = intval($i*10/$cnt); $this->UpdateProgressBar(1,$pbc*10,$tag); }
14336 }
14337 /*-- END PROGRESS-BAR --*/
14338
14339 $endtag = trim(strtoupper(substr($e,1)));
14340
14341
14342 /*-- CSS-POSITION --*/
14343 // mPDF 6
14344 if ($this->inFixedPosBlock) {
14345 if (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags)) { $this->fixedPosBlockDepth--; }
14346 if ($this->fixedPosBlockDepth == 0) {
14347 $this->fixedPosBlockSave[] = array($this->fixedPosBlock, $this->fixedPosBlockBBox, $this->page);
14348 $this->fixedPosBlock = '';
14349 $this->inFixedPosBlock = false;
14350 continue;
14351 }
14352 $this->fixedPosBlock .= '<'.$e.'>';
14353 continue;
14354 }
14355 /*-- END CSS-POSITION --*/
14356
14357 // mPDF 6
14358 // Correct for tags where HTML5 specifies optional end tags (see also OpenTag() )
14359 if ($this->allow_html_optional_endtags && !$parseonly) {
14360 if (isset($this->blk[$this->blklvl]['tag'])) {
14361 $closed = false;
14362 // li end tag may be omitted if there is no more content in the parent element
14363 if (!$closed && $this->blk[$this->blklvl]['tag']=='LI' && $endtag!='LI' && (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags))) { $this->CloseTag('LI',$a,$i); $closed = true; }
14364 // dd end tag may be omitted if there is no more content in the parent element
14365 if (!$closed && $this->blk[$this->blklvl]['tag']=='DD' && $endtag!='DD' && (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags))) { $this->CloseTag('DD',$a,$i); $closed = true; }
14366 // p end tag may be omitted if there is no more content in the parent element and the parent element is not an A element [??????]
14367 if (!$closed && $this->blk[$this->blklvl]['tag']=='P' && $endtag!='P' && (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags))) { $this->CloseTag('P',$a,$i); $closed = true; }
14368 // option end tag may be omitted if there is no more content in the parent element
14369 if (!$closed && $this->blk[$this->blklvl]['tag']=='OPTION' && $endtag!='OPTION' && (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags))) { $this->CloseTag('OPTION',$a,$i); $closed = true; }
14370 }
14371 /*-- TABLES --*/
14372 // Check for Table tags where HTML specifies optional end tags,
14373 if ($endtag == 'TABLE') {
14374 if ($this->lastoptionaltag == 'THEAD' || $this->lastoptionaltag == 'TBODY' || $this->lastoptionaltag == 'TFOOT') {
14375 $this->CloseTag($this->lastoptionaltag,$a,$i);
14376 }
14377 if ($this->lastoptionaltag == 'TR') { $this->CloseTag('TR',$a,$i); }
14378 if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag,$a,$i); $this->CloseTag('TR',$a,$i); }
14379 }
14380 if ($endtag == 'THEAD' || $endtag == 'TBODY' || $endtag == 'TFOOT') {
14381 if ($this->lastoptionaltag == 'TR') { $this->CloseTag('TR',$a,$i); }
14382 if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag,$a,$i); $this->CloseTag('TR',$a,$i); }
14383 }
14384 if ($endtag == 'TR') {
14385 if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag,$a,$i); }
14386 }
14387 /*-- END TABLES --*/
14388 }
14389
14390
14391 // mPDF 6
14392 if($this->blk[$this->blklvl]['hide']) {
14393 if (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags)) {
14394 unset($this->blk[$this->blklvl]);
14395 $this->blklvl--;
14396 }
14397 continue;
14398 }
14399
14400 // mPDF 6
14401 $this->CloseTag($endtag,$a,$i); // mPDF 6
14402 }
14403
14404 else { // OPENING TAG
14405 if($this->blk[$this->blklvl]['hide']) {
14406 if (strpos($e,' ')) { $te = strtoupper(substr($e,0,strpos($e,' '))); }
14407 else { $te = strtoupper($e); }
14408 // mPDF 6
14409 if ($te == 'THEAD' || $te == 'TBODY' || $te == 'TFOOT' || $te == 'TR' || $te == 'TD' || $te == 'TH') {
14410 $this->lastoptionaltag = $te;
14411 }
14412 if (in_array($te, $this->outerblocktags) || in_array($te, $this->innerblocktags)) {
14413 $this->blklvl++;
14414 $this->blk[$this->blklvl]['hide']=true;
14415 $this->blk[$this->blklvl]['tag'] = $te; // mPDF 6
14416 }
14417 continue;
14418 }
14419
14420 /*-- CSS-POSITION --*/
14421 if ($this->inFixedPosBlock) {
14422 if (strpos($e,' ')) { $te = strtoupper(substr($e,0,strpos($e,' '))); }
14423 else { $te = strtoupper($e); }
14424 $this->fixedPosBlock .= '<'.$e.'>';
14425 if (in_array($te, $this->outerblocktags) || in_array($te, $this->innerblocktags)) { $this->fixedPosBlockDepth++; }
14426 continue;
14427 }
14428 /*-- END CSS-POSITION --*/
14429 $regexp = '|=\'(.*?)\'|s'; // eliminate single quotes, if any
14430 $e = preg_replace($regexp,"=\"\$1\"",$e);
14431 // changes anykey=anyvalue to anykey="anyvalue" (only do this inside [some] tags)
14432 if (substr($e,0,10)!='pageheader' && substr($e,0,10)!='pagefooter' && substr($e,0,12)!='tocpagebreak' && substr($e,0,10)!='indexentry' && substr($e,0,8)!='tocentry') { // mPDF 6 (ZZZ99H)
14433 $regexp = '| (\\w+?)=([^\\s>"]+)|si';
14434 $e = preg_replace($regexp," \$1=\"\$2\"",$e);
14435 }
14436
14437 $e = preg_replace('/ (\\S+?)\s*=\s*"/i', " \\1=\"", $e);
14438
14439 //Fix path values, if needed
14440 $orig_srcpath = '';
14441 if ((stristr($e,"href=") !== false) or (stristr($e,"src=") !== false) ) {
14442 $regexp = '/ (href|src)\s*=\s*"(.*?)"/i';
14443 preg_match($regexp,$e,$auxiliararray);
14444 if (isset($auxiliararray[2])) { $path = $auxiliararray[2]; }
14445 else { $path = ''; }
14446 if (trim($path) != '' && !(stristr($e,"src=") !== false && substr($path,0,4)=='var:') && substr($path,0,1)!='@') {
14447 $path=htmlspecialchars_decode($path); // mPDF 5.7.4 URLs
14448 $orig_srcpath = $path;
14449 $this->GetFullPath($path);
14450 $regexp = '/ (href|src)="(.*?)"/i';
14451 $e = preg_replace($regexp,' \\1="'.$path.'"',$e);
14452 }
14453 }//END of Fix path values
14454
14455 //Extract attributes
14456 $contents=array();
14457 $contents1=array();
14458 $contents2=array();
14459 // Changed to allow style="background: url('bg.jpg')"
14460 // Changed to improve performance; maximum length of \S (attribute) = 16
14461 // Increase allowed attribute name to 32 - cutting off "toc-even-header-name" etc.
14462 preg_match_all('/\\S{1,32}=["][^"]*["]/',$e,$contents1);
14463 preg_match_all('/\\S{1,32}=[\'][^\']*[\']/i',$e,$contents2);
14464
14465 $contents = array_merge($contents1, $contents2);
14466 preg_match('/\\S+/',$e,$a2);
14467 $tag=(isset($a2[0]) ? strtoupper($a2[0]) : '');
14468 $attr=array();
14469 if ($orig_srcpath) { $attr['ORIG_SRC'] = $orig_srcpath; }
14470 if (!empty($contents)) {
14471 foreach($contents[0] as $v) {
14472 // Changed to allow style="background: url('bg.jpg')"
14473 if(preg_match('/^([^=]*)=["]?([^"]*)["]?$/',$v,$a3) || preg_match('/^([^=]*)=[\']?([^\']*)[\']?$/',$v,$a3)) {
14474 if (strtoupper($a3[1])=='ID' || strtoupper($a3[1])=='CLASS') { // 4.2.013 Omits STYLE
14475 $attr[strtoupper($a3[1])]=trim(strtoupper($a3[2]));
14476 }
14477 // includes header-style-right etc. used for <pageheader>
14478 else if (preg_match('/^(HEADER|FOOTER)-STYLE/i',$a3[1])) {
14479 $attr[strtoupper($a3[1])]=trim(strtoupper($a3[2]));
14480 }
14481 else {
14482 $attr[strtoupper($a3[1])]=trim($a3[2]);
14483 }
14484 }
14485 }
14486 }
14487 $this->OpenTag($tag,$attr,$a,$i); // mPDF 6
14488 /*-- CSS-POSITION --*/
14489 if ($this->inFixedPosBlock) {
14490 $this->fixedPosBlockBBox = array($tag,$attr, $this->x, $this->y);
14491 $this->fixedPosBlock = '';
14492 $this->fixedPosBlockDepth = 1;
14493 }
14494 /*-- END CSS-POSITION --*/
14495 if (preg_match('/\/$/',$e)) { $this->closeTag($tag,$a,$i); }
14496 }
14497
14498 } // end TAG
14499 } //end of foreach($a as $i=>$e)
14500
14501 if ($close) {
14502
14503 // Close any open block tags
14504 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag'],$a,$i); }
14505
14506 // Output any text left in buffer
14507 if (count($this->textbuffer) && !$parseonly) { $this->printbuffer($this->textbuffer); }
14508 if (!$parseonly) $this->textbuffer=array();
14509
14510 /*-- CSS-FLOAT --*/
14511 // If ended with a float, need to move to end page
14512 $currpos = $this->page*1000 + $this->y;
14513 if (isset($this->blk[$this->blklvl]['float_endpos']) && $this->blk[$this->blklvl]['float_endpos'] > $currpos) {
14514 $old_page = $this->page;
14515 $new_page = intval($this->blk[$this->blklvl]['float_endpos'] /1000);
14516 if ($old_page != $new_page) {
14517 $s = $this->PrintPageBackgrounds();
14518 // Writes after the marker so not overwritten later by page background etc.
14519 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.$this->uniqstr.')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
14520 $this->pageBackgrounds = array();
14521 $this->page = $new_page;
14522 $this->ResetMargins();
14523 $this->Reset();
14524 $this->pageoutput[$this->page] = array();
14525 }
14526 $this->y = (($this->blk[$this->blklvl]['float_endpos'] *1000) % 1000000)/1000; // mod changes operands to integers before processing
14527 }
14528 /*-- END CSS-FLOAT --*/
14529
14530 /*-- CSS-IMAGE-FLOAT --*/
14531 $this->printfloatbuffer();
14532 /*-- END CSS-IMAGE-FLOAT --*/
14533
14534 //Create Internal Links, if needed
14535 if (!empty($this->internallink) ) {
14536 foreach($this->internallink as $k=>$v) {
14537 if (strpos($k,"#") !== false ) { continue; } //ignore
14538 $ypos = $v['Y'];
14539 $pagenum = $v['PAGE'];
14540 $sharp = "#";
14541 while (array_key_exists($sharp.$k,$this->internallink)) {
14542 $internallink = $this->internallink[$sharp.$k];
14543 $this->SetLink($internallink,$ypos,$pagenum);
14544 $sharp .= "#";
14545 }
14546 }
14547 }
14548
14549 $this->bufferoutput = false;
14550
14551 /*-- CSS-POSITION --*/
14552 if (count($this->fixedPosBlockSave) && $sub != 4) {
14553 foreach($this->fixedPosBlockSave AS $fpbs) {
14554 $old_page = $this->page;
14555 $this->page = $fpbs[2];
14556 $this->WriteFixedPosHTML($fpbs[0], 0, 0, 100, 100,'auto', $fpbs[1]); // 0,0,10,10 are overwritten by bbox
14557 $this->page = $old_page;
14558 }
14559 $this->fixedPosBlockSave = array();
14560 }
14561 /*-- END CSS-POSITION --*/
14562
14563 }
14564 }
14565
14566 /*-- CSS-POSITION --*/
14567
14568 function WriteFixedPosHTML($html='',$x, $y, $w, $h, $overflow='visible', $bounding=array()) {
14569 // $overflow can be 'hidden', 'visible' or 'auto' - 'auto' causes autofit to size
14570 // Annotations disabled - enabled in mPDF 5.0
14571 // Links do work
14572 // Will always go on current page (or start Page 1 if required)
14573 // Probably INCOMPATIBLE WITH keep with table, columns etc.
14574 // Called externally or interally via <div style="position: [fixed|absolute]">
14575 // When used internally, $x $y $w $h and $overflow are all overridden by $bounding
14576
14577 $overflow = strtolower($overflow);
14578 if($this->state==0) {
14579 $this->AddPage($this->CurOrientation);
14580 }
14581 $save_y = $this->y;
14582 $save_x = $this->x;
14583 $this->fullImageHeight = $this->h;
14584 $save_cols = false;
14585 /*-- COLUMNS --*/
14586 if ($this->ColActive) {
14587 $save_cols = true;
14588 $save_nbcol = $this->NbCol; // other values of gap and vAlign will not change by setting Columns off
14589 $this->SetColumns(0);
14590 }
14591 /*-- END COLUMNS --*/
14592 $save_annots = $this->title2annots; // *ANNOTATIONS*
14593 $this->writingHTMLheader = true; // a FIX to stop pagebreaks etc.
14594 $this->writingHTMLfooter = true;
14595 $this->InFooter = true; // suppresses autopagebreaks
14596 $save_bgs = $this->pageBackgrounds;
14597 $checkinnerhtml = preg_replace('/\s/','',$html);
14598
14599 if ($w > $this->w) { $x = 0; $w = $this->w; }
14600 if ($h > $this->h) { $y = 0; $h = $this->h; }
14601 if ($x > $this->w) { $x = $this->w - $w; }
14602 if ($y > $this->h) { $y = $this->h - $h; }
14603
14604 if (!empty($bounding)) {
14605 // $cont_ containing block = full physical page (position: absolute) or page inside margins (position: fixed)
14606 // $bbox_ Bounding box is the <div> which is positioned absolutely/fixed
14607 // top/left/right/bottom/width/height/background*/border*/padding*/margin* are taken from bounding
14608 // font*[family/size/style/weight]/line-height/text*[align/decoration/transform/indent]/color are transferred to $inner
14609 // as an enclosing <div> (after having checked ID/CLASS)
14610 // $x, $y, $w, $h are inside of $bbox_ = containing box for $inner_
14611 // $inner_ InnerHTML is the contents of that block to be output
14612 $tag = $bounding[0];
14613 $attr = $bounding[1];
14614 $orig_x0 = $bounding[2];
14615 $orig_y0 = $bounding[3];
14616
14617 // As in WriteHTML() initialising
14618 $this->blklvl = 0;
14619 $this->lastblocklevelchange = 0;
14620 $this->blk = array();
14621 $this->initialiseBlock($this->blk[0]);
14622
14623 $this->blk[0]['width'] =& $this->pgwidth;
14624 $this->blk[0]['inner_width'] =& $this->pgwidth;
14625
14626 $this->blk[0]['blockContext'] = $this->blockContext;
14627
14628 $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
14629 $this->setCSS($properties,'','BODY');
14630 $this->blklvl = 1;
14631 $this->initialiseBlock($this->blk[1]);
14632 $this->blk[1]['tag'] = $tag;
14633 $this->blk[1]['attr'] = $attr;
14634 $this->Reset();
14635 $p = $this->cssmgr->MergeCSS('BLOCK',$tag,$attr);
14636 if (isset($p['ROTATE']) && ($p['ROTATE']==90 || $p['ROTATE']==-90 || $p['ROTATE']==180)) { $rotate = $p['ROTATE']; } // mPDF 6
14637 else { $rotate = 0; }
14638 if (isset($p['OVERFLOW'])) { $overflow = strtolower($p['OVERFLOW']); }
14639 if (strtolower($p['POSITION']) == 'fixed') {
14640 $cont_w = $this->pgwidth; // $this->blk[0]['inner_width'];
14641 $cont_h = $this->h - $this->tMargin - $this->bMargin;
14642 $cont_x = $this->lMargin;
14643 $cont_y = $this->tMargin;
14644 }
14645 else {
14646 $cont_w = $this->w; // ABSOLUTE;
14647 $cont_h = $this->h;
14648 $cont_x = 0;
14649 $cont_y = 0;
14650 }
14651
14652 // Pass on in-line properties to the innerhtml
14653 $css = '';
14654 if (isset($p['TEXT-ALIGN'])) { $css .= 'text-align: '.strtolower($p['TEXT-ALIGN']).'; '; }
14655 if (isset($p['TEXT-TRANSFORM'])) { $css .= 'text-transform: '.strtolower($p['TEXT-TRANSFORM']).'; '; }
14656 if (isset($p['TEXT-INDENT'])) { $css .= 'text-indent: '.strtolower($p['TEXT-INDENT']).'; '; }
14657 if (isset($p['TEXT-DECORATION'])) { $css .= 'text-decoration: '.strtolower($p['TEXT-DECORATION']).'; '; }
14658 if (isset($p['FONT-FAMILY'])) { $css .= 'font-family: '.strtolower($p['FONT-FAMILY']).'; '; }
14659 if (isset($p['FONT-STYLE'])) { $css .= 'font-style: '.strtolower($p['FONT-STYLE']).'; '; }
14660 if (isset($p['FONT-WEIGHT'])) { $css .= 'font-weight: '.strtolower($p['FONT-WEIGHT']).'; '; }
14661 if (isset($p['FONT-SIZE'])) { $css .= 'font-size: '.strtolower($p['FONT-SIZE']).'; '; }
14662 if (isset($p['LINE-HEIGHT'])) { $css .= 'line-height: '.strtolower($p['LINE-HEIGHT']).'; '; }
14663 if (isset($p['TEXT-SHADOW'])) { $css .= 'text-shadow: '.strtolower($p['TEXT-SHADOW']).'; '; }
14664 if (isset($p['LETTER-SPACING'])) { $css .= 'letter-spacing: '.strtolower($p['LETTER-SPACING']).'; '; }
14665 // mPDF 6
14666 if (isset($p['FONT-VARIANT-POSITION'])) { $css .= 'font-variant-position: '.strtolower($p['FONT-VARIANT-POSITION']).'; '; }
14667 if (isset($p['FONT-VARIANT-CAPS'])) { $css .= 'font-variant-caps: '.strtolower($p['FONT-VARIANT-CAPS']).'; '; }
14668 if (isset($p['FONT-VARIANT-LIGATURES'])) { $css .= 'font-variant-ligatures: '.strtolower($p['FONT-VARIANT-LIGATURES']).'; '; }
14669 if (isset($p['FONT-VARIANT-NUMERIC'])) { $css .= 'font-variant-numeric: '.strtolower($p['FONT-VARIANT-NUMERIC']).'; '; }
14670 if (isset($p['FONT-VARIANT-ALTERNATES'])) { $css .= 'font-variant-alternates: '.strtolower($p['FONT-VARIANT-ALTERNATES']).'; '; }
14671 if (isset($p['FONT-FEATURE-SETTINGS'])) { $css .= 'font-feature-settings: '.strtolower($p['FONT-FEATURE-SETTINGS']).'; '; }
14672 if (isset($p['FONT-LANGUAGE-OVERRIDE'])) { $css .= 'font-language-override: '.strtolower($p['FONT-LANGUAGE-OVERRIDE']).'; '; }
14673 if (isset($p['FONT-KERNING'])) { $css .= 'font-kerning: '.strtolower($p['FONT-KERNING']).'; '; }
14674
14675 if (isset($p['COLOR'])) { $css .= 'color: '.strtolower($p['COLOR']).'; '; }
14676 if (isset($p['Z-INDEX'])) { $css .= 'z-index: '.$p['Z-INDEX'].'; '; }
14677 if ($css) {
14678 $html = '<div style="'.$css.'">'.$html.'</div>';
14679 }
14680 // Copy over (only) the properties to set for border and background
14681 $pb = array();
14682 $pb['MARGIN-TOP'] = (isset($p['MARGIN-TOP']) ? $p['MARGIN-TOP'] : '');
14683 $pb['MARGIN-RIGHT'] = (isset($p['MARGIN-RIGHT']) ? $p['MARGIN-RIGHT'] : '');
14684 $pb['MARGIN-BOTTOM'] = (isset($p['MARGIN-BOTTOM']) ? $p['MARGIN-BOTTOM'] : '');
14685 $pb['MARGIN-LEFT'] = (isset($p['MARGIN-LEFT']) ? $p['MARGIN-LEFT'] : '');
14686 $pb['PADDING-TOP'] = (isset($p['PADDING-TOP']) ? $p['PADDING-TOP'] : '');
14687 $pb['PADDING-RIGHT'] = (isset($p['PADDING-RIGHT']) ? $p['PADDING-RIGHT'] : '');
14688 $pb['PADDING-BOTTOM'] = (isset($p['PADDING-BOTTOM']) ? $p['PADDING-BOTTOM'] : '');
14689 $pb['PADDING-LEFT'] = (isset($p['PADDING-LEFT']) ? $p['PADDING-LEFT'] : '');
14690 $pb['BORDER-TOP'] = (isset($p['BORDER-TOP']) ? $p['BORDER-TOP'] : '');
14691 $pb['BORDER-RIGHT'] = (isset($p['BORDER-RIGHT']) ? $p['BORDER-RIGHT'] : '');
14692 $pb['BORDER-BOTTOM'] = (isset($p['BORDER-BOTTOM']) ? $p['BORDER-BOTTOM'] : '');
14693 $pb['BORDER-LEFT'] = (isset($p['BORDER-LEFT']) ? $p['BORDER-LEFT'] : '');
14694 if (isset($p['BORDER-TOP-LEFT-RADIUS-H'])) { $pb['BORDER-TOP-LEFT-RADIUS-H'] = $p['BORDER-TOP-LEFT-RADIUS-H']; }
14695 if (isset($p['BORDER-TOP-LEFT-RADIUS-V'])) { $pb['BORDER-TOP-LEFT-RADIUS-V'] = $p['BORDER-TOP-LEFT-RADIUS-V']; }
14696 if (isset($p['BORDER-TOP-RIGHT-RADIUS-H'])) { $pb['BORDER-TOP-RIGHT-RADIUS-H'] = $p['BORDER-TOP-RIGHT-RADIUS-H']; }
14697 if (isset($p['BORDER-TOP-RIGHT-RADIUS-V'])) { $pb['BORDER-TOP-RIGHT-RADIUS-V'] = $p['BORDER-TOP-RIGHT-RADIUS-V']; }
14698 if (isset($p['BORDER-BOTTOM-LEFT-RADIUS-H'])) { $pb['BORDER-BOTTOM-LEFT-RADIUS-H'] = $p['BORDER-BOTTOM-LEFT-RADIUS-H']; }
14699 if (isset($p['BORDER-BOTTOM-LEFT-RADIUS-V'])) { $pb['BORDER-BOTTOM-LEFT-RADIUS-V'] = $p['BORDER-BOTTOM-LEFT-RADIUS-V']; }
14700 if (isset($p['BORDER-BOTTOM-RIGHT-RADIUS-H'])) { $pb['BORDER-BOTTOM-RIGHT-RADIUS-H'] = $p['BORDER-BOTTOM-RIGHT-RADIUS-H']; }
14701 if (isset($p['BORDER-BOTTOM-RIGHT-RADIUS-V'])) { $pb['BORDER-BOTTOM-RIGHT-RADIUS-V'] = $p['BORDER-BOTTOM-RIGHT-RADIUS-V']; }
14702 if (isset($p['BACKGROUND-COLOR'])) { $pb['BACKGROUND-COLOR'] = $p['BACKGROUND-COLOR']; }
14703 if (isset($p['BOX-SHADOW'])) { $pb['BOX-SHADOW'] = $p['BOX-SHADOW']; }
14704 /*-- BACKGROUNDS --*/
14705 if (isset($p['BACKGROUND-IMAGE'])) { $pb['BACKGROUND-IMAGE'] = $p['BACKGROUND-IMAGE']; }
14706 if (isset($p['BACKGROUND-IMAGE-RESIZE'])) { $pb['BACKGROUND-IMAGE-RESIZE'] = $p['BACKGROUND-IMAGE-RESIZE']; }
14707 if (isset($p['BACKGROUND-IMAGE-OPACITY'])) { $pb['BACKGROUND-IMAGE-OPACITY'] = $p['BACKGROUND-IMAGE-OPACITY']; }
14708 if (isset($p['BACKGROUND-REPEAT'])) { $pb['BACKGROUND-REPEAT'] = $p['BACKGROUND-REPEAT']; }
14709 if (isset($p['BACKGROUND-POSITION'])) { $pb['BACKGROUND-POSITION'] = $p['BACKGROUND-POSITION']; }
14710 if (isset($p['BACKGROUND-GRADIENT'])) { $pb['BACKGROUND-GRADIENT'] = $p['BACKGROUND-GRADIENT']; }
14711 if (isset($p['BACKGROUND-SIZE'])) { $pb['BACKGROUND-SIZE'] = $p['BACKGROUND-SIZE']; }
14712 if (isset($p['BACKGROUND-ORIGIN'])) { $pb['BACKGROUND-ORIGIN'] = $p['BACKGROUND-ORIGIN']; }
14713 if (isset($p['BACKGROUND-CLIP'])) { $pb['BACKGROUND-CLIP'] = $p['BACKGROUND-CLIP']; }
14714
14715 /*-- END BACKGROUNDS --*/
14716
14717 $this->setCSS($pb,'BLOCK',$tag);
14718
14719 //================================================================
14720 $bbox_br = $this->blk[1]['border_right']['w'];
14721 $bbox_bl = $this->blk[1]['border_left']['w'];
14722 $bbox_bt = $this->blk[1]['border_top']['w'];
14723 $bbox_bb = $this->blk[1]['border_bottom']['w'];
14724 $bbox_pr = $this->blk[1]['padding_right'];
14725 $bbox_pl = $this->blk[1]['padding_left'];
14726 $bbox_pt = $this->blk[1]['padding_top'];
14727 $bbox_pb = $this->blk[1]['padding_bottom'];
14728 $bbox_mr = $this->blk[1]['margin_right'];
14729 if (isset($p['MARGIN-RIGHT']) && strtolower($p['MARGIN-RIGHT'])=='auto') { $bbox_mr = 'auto'; }
14730 $bbox_ml = $this->blk[1]['margin_left'];
14731 if (isset($p['MARGIN-LEFT']) && strtolower($p['MARGIN-LEFT'])=='auto') { $bbox_ml = 'auto'; }
14732 $bbox_mt = $this->blk[1]['margin_top'];
14733 if (isset($p['MARGIN-TOP']) && strtolower($p['MARGIN-TOP'])=='auto') { $bbox_mt = 'auto'; }
14734 $bbox_mb = $this->blk[1]['margin_bottom'];
14735 if (isset($p['MARGIN-BOTTOM']) && strtolower($p['MARGIN-BOTTOM'])=='auto') { $bbox_mb = 'auto'; }
14736 if (isset($p['LEFT']) && strtolower($p['LEFT'])!='auto') { $bbox_left = $this->ConvertSize($p['LEFT'], $cont_w, $this->FontSize,false); }
14737 else { $bbox_left = 'auto'; }
14738 if (isset($p['TOP']) && strtolower($p['TOP'])!='auto') { $bbox_top = $this->ConvertSize($p['TOP'], $cont_h, $this->FontSize,false); }
14739 else { $bbox_top = 'auto'; }
14740 if (isset($p['RIGHT']) && strtolower($p['RIGHT'])!='auto') { $bbox_right = $this->ConvertSize($p['RIGHT'], $cont_w, $this->FontSize,false); }
14741 else { $bbox_right = 'auto'; }
14742 if (isset($p['BOTTOM']) && strtolower($p['BOTTOM'])!='auto') { $bbox_bottom = $this->ConvertSize($p['BOTTOM'], $cont_h, $this->FontSize,false); }
14743 else { $bbox_bottom = 'auto'; }
14744 if (isset($p['WIDTH']) && strtolower($p['WIDTH'])!='auto') { $inner_w = $this->ConvertSize($p['WIDTH'], $cont_w, $this->FontSize,false); }
14745 else { $inner_w = 'auto'; }
14746 if (isset($p['HEIGHT']) && strtolower($p['HEIGHT'])!='auto') { $inner_h = $this->ConvertSize($p['HEIGHT'], $cont_h, $this->FontSize,false); }
14747 else { $inner_h = 'auto'; }
14748
14749 // If bottom or right pos are set and not left / top - save this to adjust rotated block later
14750 if ($rotate == 90 || $rotate==-90) { // mPDF 6
14751 if ($bbox_left === 'auto' && $bbox_right !== 'auto') { $rot_rpos = $bbox_right; }
14752 else { $rot_rpos = false; }
14753 if ($bbox_top === 'auto' && $bbox_bottom !== 'auto') { $rot_bpos = $bbox_bottom; }
14754 else { $rot_bpos = false; }
14755 }
14756
14757 //================================================================
14758 if ($checkinnerhtml=='' && $inner_h==='auto') { $inner_h = 0.0001; }
14759 if ($checkinnerhtml=='' && $inner_w==='auto') { $inner_w = 2*$this->GetCharWidth('W',false); }
14760 //================================================================
14761 // Algorithm from CSS2.1 See http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-height
14762 // mPD 5.3.14
14763 // Special case (not CSS) if all not specified, centre vertically on page
14764 $bbox_top_orig = '';
14765 if ($bbox_top==='auto' && $inner_h==='auto' && $bbox_bottom==='auto' && $bbox_mt==='auto' && $bbox_mb==='auto') {
14766 $bbox_top_orig = $bbox_top;
14767 if ($bbox_mt==='auto') { $bbox_mt = 0; }
14768 if ($bbox_mb==='auto') { $bbox_mb = 0; }
14769 $bbox_top = $orig_y0 - $bbox_mt - $cont_y;
14770 // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto'
14771 }
14772 // mPD 5.3.14
14773 else if ($bbox_top==='auto' && $inner_h==='auto' && $bbox_bottom==='auto') {
14774 $bbox_top_orig = $bbox_top = $orig_y0 - $cont_y;
14775 if ($bbox_mt==='auto') { $bbox_mt = 0; }
14776 if ($bbox_mb==='auto') { $bbox_mb = 0; }
14777 // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto'
14778 }
14779 else if ($bbox_top!=='auto' && $inner_h!=='auto' && $bbox_bottom!=='auto') {
14780 if ($bbox_mt==='auto' && $bbox_mb==='auto') {
14781 $x = $cont_h - $bbox_top - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_bottom;
14782 $bbox_mt = $bbox_mb = ($x/2);
14783 }
14784 else if ($bbox_mt==='auto') {
14785 $bbox_mt = $cont_h - $bbox_top - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
14786 }
14787 else if ($bbox_mb==='auto') {
14788 $bbox_mb = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_bottom;
14789 }
14790 else {
14791 $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt;
14792 }
14793 }
14794 else {
14795 if ($bbox_mt==='auto') { $bbox_mt = 0; }
14796 if ($bbox_mb==='auto') { $bbox_mb = 0; }
14797 if ($bbox_top==='auto' && $inner_h==='auto' && $bbox_bottom!=='auto') {
14798 // solve for $bbox_top when content_h known - $inner_h=='auto' && $bbox_top =='auto'
14799 }
14800 else if ($bbox_top==='auto' && $bbox_bottom==='auto' && $inner_h!=='auto') {
14801 $bbox_top = $orig_y0 - $bbox_mt - $cont_y;
14802 $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt;
14803 }
14804 else if ($inner_h==='auto' && $bbox_bottom==='auto' && $bbox_top!=='auto') {
14805 // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto'
14806 }
14807 else if ($bbox_top==='auto' && $inner_h!=='auto' && $bbox_bottom!=='auto') {
14808 $bbox_top = $cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt - $bbox_bottom;
14809 }
14810 else if ($inner_h==='auto' && $bbox_top!=='auto' && $bbox_bottom!=='auto') {
14811 $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mt - $bbox_bottom;
14812 }
14813 else if ($bbox_bottom==='auto' && $bbox_top!=='auto' && $inner_h!=='auto') {
14814 $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt;
14815 }
14816 }
14817
14818 // THEN DO SAME FOR WIDTH
14819 // http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width
14820 if ($bbox_left==='auto' && $inner_w==='auto' && $bbox_right==='auto') {
14821 if ($bbox_ml==='auto') { $bbox_ml = 0; }
14822 if ($bbox_mr==='auto') { $bbox_mr = 0; }
14823 // IF containing element RTL, should set $bbox_right
14824 $bbox_left = $orig_x0 - $bbox_ml - $cont_x;
14825 // solve for $bbox_right when content_w known - $inner_w=='auto' && $bbox_right=='auto'
14826 }
14827 else if ($bbox_left!=='auto' && $inner_w!=='auto' && $bbox_right!=='auto') {
14828 if ($bbox_ml==='auto' && $bbox_mr==='auto') {
14829 $x = $cont_w - $bbox_left - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_right;
14830 $bbox_ml = $bbox_mr = ($x/2);
14831 }
14832 else if ($bbox_ml==='auto') {
14833 $bbox_ml = $cont_w - $bbox_left - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_mr - $bbox_right;
14834 }
14835 else if ($bbox_mr==='auto') {
14836 $bbox_mr = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_right;
14837 }
14838 else {
14839 $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
14840 }
14841 }
14842 else {
14843 if ($bbox_ml==='auto') { $bbox_ml = 0; }
14844 if ($bbox_mr==='auto') { $bbox_mr = 0; }
14845 if ($bbox_left==='auto' && $inner_w==='auto' && $bbox_right!=='auto') {
14846 // solve for $bbox_left when content_w known - $inner_w=='auto' && $bbox_left =='auto'
14847 }
14848 else if ($bbox_left==='auto' && $bbox_right==='auto' && $inner_w!=='auto') {
14849 // IF containing element RTL, should set $bbox_right
14850 $bbox_left = $orig_x0 - $bbox_ml - $cont_x;
14851 $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
14852 }
14853 else if ($inner_w==='auto' && $bbox_right==='auto' && $bbox_left!=='auto') {
14854 // solve for $bbox_right when content_w known - $inner_w=='auto' && $bbox_right=='auto'
14855 }
14856 else if ($bbox_left==='auto' && $inner_w!=='auto' && $bbox_right!=='auto') {
14857 $bbox_left = $cont_w - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right;
14858 }
14859 else if ($inner_w==='auto' && $bbox_left!=='auto' && $bbox_right!=='auto') {
14860 $inner_w = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right;
14861 }
14862 else if ($bbox_right==='auto' && $bbox_left!=='auto' && $inner_w!=='auto') {
14863 $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
14864 }
14865 }
14866
14867 //================================================================
14868 //================================================================
14869 /*-- BACKGROUNDS --*/
14870 if (isset($pb['BACKGROUND-IMAGE']) && $pb['BACKGROUND-IMAGE']) {
14871 $ret = $this->SetBackground($pb, $this->blk[1]['inner_width']);
14872 if ($ret) { $this->blk[1]['background-image'] = $ret; }
14873 }
14874 /*-- END BACKGROUNDS --*/
14875
14876 //================================================================
14877 $y = $cont_y + $bbox_top + $bbox_mt + $bbox_bt + $bbox_pt;
14878 $h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
14879 $x = $cont_x + $bbox_left + $bbox_ml + $bbox_bl + $bbox_pl;
14880 $w = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $bbox_pr - $bbox_br - $bbox_mr - $bbox_right;
14881 // Set (temporary) values for x y w h to do first paint, if values are auto
14882 if ($inner_h==='auto' && $bbox_top==='auto') {
14883 $y = $cont_y + $bbox_mt + $bbox_bt + $bbox_pt;
14884 $h = $cont_h - ($bbox_bottom + $bbox_mt + $bbox_mb + $bbox_bt + $bbox_bb + $bbox_pt + $bbox_pb);
14885 }
14886 else if ($inner_h==='auto' && $bbox_bottom==='auto') {
14887 $y = $cont_y + $bbox_top + $bbox_mt + $bbox_bt + $bbox_pt;
14888 $h = $cont_h - ($bbox_top + $bbox_mt + $bbox_mb + $bbox_bt + $bbox_bb + $bbox_pt + $bbox_pb);
14889 }
14890 if ($inner_w==='auto' && $bbox_left==='auto') {
14891 $x = $cont_x + $bbox_ml + $bbox_bl + $bbox_pl;
14892 $w = $cont_w - ($bbox_right + $bbox_ml + $bbox_mr + $bbox_bl + $bbox_br + $bbox_pl + $bbox_pr);
14893 }
14894 else if ($inner_w==='auto' && $bbox_right==='auto') {
14895 $x = $cont_x + $bbox_left + $bbox_ml + $bbox_bl + $bbox_pl;
14896 $w = $cont_w - ($bbox_left + $bbox_ml + $bbox_mr + $bbox_bl + $bbox_br + $bbox_pl + $bbox_pr);
14897 }
14898 $bbox_y = $cont_y + $bbox_top + $bbox_mt;
14899 $bbox_x = $cont_x + $bbox_left + $bbox_ml;
14900 $saved_block1 = $this->blk[1];
14901 unset($p);
14902 unset($pb);
14903 //================================================================
14904 if ($inner_w==='auto') { // do a first write
14905 $this->lMargin=$x;
14906 $this->rMargin=$this->w - $w - $x;
14907 // SET POSITION & FONT VALUES
14908 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
14909 $this->pageoutput[$this->page]=array();
14910 $this->x = $x;
14911 $this->y = $y;
14912 $this->HTMLheaderPageLinks = array();
14913 $this->HTMLheaderPageAnnots = array();
14914 $this->HTMLheaderPageForms = array();
14915 $this->pageBackgrounds = array();
14916 $this->maxPosR = 0;
14917 $this->maxPosL = $this->w; // For RTL
14918 $this->WriteHTML($html , 4);
14919 $inner_w = $this->maxPosR - $this->lMargin;
14920 if ($bbox_right==='auto') {
14921 $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
14922 }
14923 else if ($bbox_left==='auto') {
14924 $bbox_left = $cont_w - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right;
14925 $bbox_x = $cont_x + $bbox_left + $bbox_ml ;
14926 $inner_x = $bbox_x + $bbox_bl + $bbox_pl;
14927 $x = $inner_x;
14928 }
14929 $w = $inner_w;
14930 $bbox_y = $cont_y + $bbox_top + $bbox_mt;
14931 $bbox_x = $cont_x + $bbox_left + $bbox_ml;
14932 }
14933
14934 if ($inner_h==='auto') { // do a first write
14935 $this->lMargin=$x;
14936 $this->rMargin=$this->w - $w - $x;
14937 // SET POSITION & FONT VALUES
14938 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
14939 $this->pageoutput[$this->page]=array();
14940 $this->x = $x;
14941 $this->y = $y;
14942 $this->HTMLheaderPageLinks = array();
14943 $this->HTMLheaderPageAnnots = array();
14944 $this->HTMLheaderPageForms = array();
14945 $this->pageBackgrounds = array();
14946 $this->WriteHTML($html , 4);
14947 $inner_h = $this->y - $y;
14948 if ($overflow!='hidden' && $overflow!='visible') { // constrained
14949 if (($this->y + $bbox_pb + $bbox_bb) > ($cont_y + $cont_h)) {
14950 $adj = ($this->y + $bbox_pb + $bbox_bb) - ($cont_y + $cont_h);
14951 $inner_h -= $adj;
14952 }
14953 }
14954 if ($bbox_bottom==='auto' && $bbox_top_orig==='auto') {
14955 $bbox_bottom = $bbox_top = ($cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb)/2;
14956 if ($overflow!='hidden' && $overflow!='visible') { // constrained
14957 if ($bbox_top < 0) {
14958 $bbox_top = 0;
14959 $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
14960 }
14961 }
14962 $bbox_y = $cont_y + $bbox_top + $bbox_mt;
14963 $inner_y = $bbox_y + $bbox_bt + $bbox_pt;
14964 $y = $inner_y;
14965
14966 }
14967 else if ($bbox_bottom==='auto') {
14968 $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb;
14969 }
14970 else if ($bbox_top==='auto') {
14971 $bbox_top = $cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
14972 if ($overflow!='hidden' && $overflow!='visible') { // constrained
14973 if ($bbox_top < 0) {
14974 $bbox_top = 0;
14975 $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
14976 }
14977 }
14978 $bbox_y = $cont_y + $bbox_top + $bbox_mt;
14979 $inner_y = $bbox_y + $bbox_bt + $bbox_pt;
14980 $y = $inner_y;
14981 }
14982 $h = $inner_h;
14983 $bbox_y = $cont_y + $bbox_top + $bbox_mt;
14984 $bbox_x = $cont_x + $bbox_left + $bbox_ml;
14985 }
14986 $inner_w = $w;
14987 $inner_h = $h;
14988
14989 }
14990 $this->lMargin=$x;
14991 $this->rMargin=$this->w - $w - $x;
14992 // SET POSITION & FONT VALUES
14993 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
14994 $this->pageoutput[$this->page]=array();
14995 $this->x = $x;
14996 $this->y = $y;
14997 $this->HTMLheaderPageLinks = array();
14998 $this->HTMLheaderPageAnnots = array();
14999 $this->HTMLheaderPageForms = array();
15000 $this->pageBackgrounds = array();
15001 $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
15002 $actual_h = $this->y - $y;
15003 $use_w = $w;
15004 $use_h = $h;
15005 $ratio = $actual_h / $use_w;
15006
15007 if ($overflow!='hidden' && $overflow!='visible') {
15008 $target = $h/$w;
15009 if (($ratio / $target ) > 1) {
15010 $nl = CEIL($actual_h / $this->lineheight);
15011 $l = $use_w * $nl;
15012 $est_w = sqrt(($l * $this->lineheight) / $target) * 0.8;
15013 $use_w += ($est_w - $use_w) - ($w/100);
15014 }
15015 $bpcstart = ($ratio / $target);
15016 $bpcctr = 1;
15017 while(($ratio / $target ) > 1) {
15018
15019 if ($this->progressBar) { $this->UpdateProgressBar(4,intval(100/($ratio/$target)),('Auto-sizing fixed-position block: '.$bpcctr++)); } // *PROGRESS-BAR*
15020
15021 $this->x = $x;
15022 $this->y = $y;
15023
15024 if (($ratio / $target) > 1.5 || ($ratio / $target) < 0.6) {
15025 $use_w += ($w/$this->incrementFPR1);
15026 }
15027 else if (($ratio / $target) > 1.2 || ($ratio / $target) < 0.85) {
15028 $use_w += ($w/$this->incrementFPR2);
15029 }
15030 else if (($ratio / $target) > 1.1 || ($ratio / $target) < 0.91) {
15031 $use_w += ($w/$this->incrementFPR3);
15032 }
15033 else {
15034 $use_w += ($w/$this->incrementFPR4);
15035 }
15036
15037 $use_h = $use_w * $target ;
15038 $this->rMargin=$this->w - $use_w - $x;
15039 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
15040 $this->HTMLheaderPageLinks = array();
15041 $this->HTMLheaderPageAnnots = array();
15042 $this->HTMLheaderPageForms = array();
15043 $this->pageBackgrounds = array();
15044 $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
15045 $actual_h = $this->y - $y;
15046 $ratio = $actual_h / $use_w;
15047 }
15048 if ($this->progressBar) { $this->UpdateProgressBar(4,'100',' '); } // *PROGRESS-BAR*
15049 }
15050 $shrink_f = $w/$use_w;
15051
15052 //================================================================
15053
15054 $this->pages[$this->page] .= '___BEFORE_BORDERS___';
15055 $block_s = $this->PrintPageBackgrounds(); // Save to print later inside clipping path
15056 $this->pageBackgrounds = array();
15057
15058 //================================================================
15059
15060 if ($rotate == 90 || $rotate==-90) { // mPDF 6
15061 $prerotw = $bbox_bl + $bbox_pl + $inner_w + $bbox_pr + $bbox_br;
15062 $preroth = $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb;
15063 $rot_start = " q\n";
15064 if ($rotate == 90) {
15065 if ($rot_rpos !== false) { $adjw = $prerotw; } // width before rotation
15066 else { $adjw = $preroth; } // height before rotation
15067 if ($rot_bpos !== false) { $adjh = -$prerotw + $preroth; }
15068 else { $adjh = 0; }
15069 }
15070 else {
15071 if ($rot_rpos !== false) { $adjw = $prerotw - $preroth; }
15072 else { $adjw = 0; }
15073 if ($rot_bpos !== false) { $adjh = $preroth; } // height before rotation
15074 else { $adjh = $prerotw; } // width before rotation
15075 }
15076 $rot_start .= $this->transformTranslate($adjw, $adjh, true)."\n";
15077 $rot_start .= $this->transformRotate($rotate, $bbox_x, $bbox_y, true)."\n";
15078 $rot_end = " Q\n";
15079 }
15080 else if ($rotate == 180) { // mPDF 6
15081 $rot_start = " q\n";
15082 $rot_start .= $this->transformTranslate($bbox_bl + $bbox_pl + $inner_w + $bbox_pr + $bbox_br, $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb, true)."\n";
15083 $rot_start .= $this->transformRotate(180, $bbox_x, $bbox_y, true)."\n";
15084 $rot_end = " Q\n";
15085 }
15086 else {
15087 $rot_start = '';
15088 $rot_end = '';
15089 }
15090
15091 //================================================================
15092 if (!empty($bounding)) {
15093 // WHEN HEIGHT // BOTTOM EDGE IS KNOWN and $this->y is set to the bottom
15094 // Re-instate saved $this->blk[1]
15095 $this->blk[1] = $saved_block1;
15096
15097 // These are only needed when painting border/background
15098 $this->blk[1]['width'] = $bbox_w = $cont_w - $bbox_left - $bbox_ml - $bbox_mr - $bbox_right;
15099 $this->blk[1]['x0'] = $bbox_x;
15100 $this->blk[1]['y0'] = $bbox_y;
15101 $this->blk[1]['startpage'] = $this->page;
15102 $this->blk[1]['y1'] = $bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb ;
15103 $this->_out($rot_start);
15104 $this->PaintDivBB('',0,1); // Prints borders and sets backgrounds in $this->pageBackgrounds
15105 $this->_out($rot_end);
15106 }
15107
15108 $s = $this->PrintPageBackgrounds();
15109 $s = $rot_start.$s.$rot_end;
15110 $this->pages[$this->page] = preg_replace('/___BEFORE_BORDERS___/', "\n".$s."\n", $this->pages[$this->page]);
15111 $this->pageBackgrounds = array();
15112
15113 $this->_out($rot_start);
15114
15115 // Clipping Output
15116 if ($overflow=='hidden') {
15117 //Bounding rectangle to clip
15118 $clip_y1 = $this->y;
15119 if (!empty($bounding) && ($this->y + $bbox_pb + $bbox_bb) > ($bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb )) {
15120 $clip_y1 = ($bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb ) - ($bbox_pb + $bbox_bb);
15121 }
15122 //$op = 'W* n'; // Clipping
15123 $op = 'W n'; // Clipping alternative mode
15124 $this->_out("q");
15125 $ch = $clip_y1 - $y;
15126 $this->_out(sprintf('%.3F %.3F %.3F %.3F re %s',$x*_MPDFK,($this->h-$y)*_MPDFK,$w*_MPDFK,-$ch*_MPDFK,$op));
15127 if (!empty($block_s)) {
15128 $tmp = "q\n".sprintf('%.3F %.3F %.3F %.3F re %s',$x*_MPDFK,($this->h-$y)*_MPDFK,$w*_MPDFK,-$ch*_MPDFK,$op);
15129 $tmp .= "\n".$block_s."\nQ";
15130 $block_s = $tmp ;
15131 }
15132 }
15133
15134
15135 if (!empty($block_s)) {
15136 if ($shrink_f != 1) { // i.e. autofit has resized the box
15137 $tmp = "q\n".$this->transformScale(($shrink_f*100),($shrink_f*100), $x, $y, true);
15138 $tmp .= "\n".$block_s."\nQ";
15139 $block_s = $tmp ;
15140 }
15141 $this->_out($block_s);
15142 }
15143
15144
15145
15146 if ($shrink_f != 1) { // i.e. autofit has resized the box
15147 $this->StartTransform();
15148 $this->transformScale(($shrink_f*100),($shrink_f*100), $x, $y);
15149 }
15150
15151 $this->_out($this->headerbuffer);
15152
15153 if ($shrink_f != 1) { // i.e. autofit has resized the box
15154 $this->StopTransform();
15155 }
15156
15157 if ($overflow=='hidden') {
15158 //End clipping
15159 $this->_out("Q");
15160 }
15161
15162 $this->_out($rot_end);
15163
15164
15165 // Page Links
15166 foreach($this->HTMLheaderPageLinks AS $lk) {
15167 if ($rotate) {
15168 $tmp = $lk[2]; // Switch h - w
15169 $lk[2] = $lk[3];
15170 $lk[3] = $tmp;
15171
15172 $lx1 = (($lk[0]/_MPDFK));
15173 $ly1 = (($this->h-($lk[1]/_MPDFK)));
15174 if ($rotate == 90) {
15175 $adjx = -($lx1-$bbox_x) + ($preroth - ($ly1-$bbox_y));
15176 $adjy = -($ly1-$bbox_y) + ($lx1-$bbox_x);
15177 $lk[2] = -$lk[2];
15178 }
15179 else if ($rotate == -90) {
15180 $adjx = -($lx1-$bbox_x) + ($ly1-$bbox_y);
15181 $adjy = -($ly1-$bbox_y) - ($lx1-$bbox_x) + $prerotw;
15182 $lk[3] = -$lk[3];
15183 }
15184 if ($rot_rpos !== false) { $adjx += $prerotw - $preroth; }
15185 if ($rot_bpos !== false) { $adjy += $preroth - $prerotw; }
15186 $lx1 += $adjx;
15187 $ly1 += $adjy;
15188
15189 $lk[0] = $lx1*_MPDFK;
15190 $lk[1] = ($this->h-$ly1)*_MPDFK;
15191 }
15192 if ($shrink_f != 1) { // i.e. autofit has resized the box
15193 $lx1 = (($lk[0]/_MPDFK)-$x);
15194 $lx2 = $x + ($lx1 * $shrink_f);
15195 $lk[0] = $lx2*_MPDFK;
15196 $ly1 = (($this->h-($lk[1]/_MPDFK))-$y);
15197 $ly2 = $y + ($ly1 * $shrink_f);
15198 $lk[1] = ($this->h-$ly2)*_MPDFK;
15199 $lk[2] *= $shrink_f; // width
15200 $lk[3] *= $shrink_f; // height
15201 }
15202 $this->PageLinks[$this->page][]=$lk;
15203 }
15204
15205 foreach($this->HTMLheaderPageForms AS $n=>$f) {
15206 if ($shrink_f != 1) { // i.e. autofit has resized the box
15207 $f['x'] = $x + (($f['x'] -$x) * $shrink_f);
15208 $f['y'] = $y + (($f['y'] -$y) * $shrink_f);
15209 $f['w'] *= $shrink_f;
15210 $f['h'] *= $shrink_f;
15211 $f['style']['fontsize'] *= $shrink_f;
15212 }
15213 $this->mpdfform->forms[$f['n']] = $f;
15214 }
15215 // Page Annotations
15216 foreach($this->HTMLheaderPageAnnots AS $lk) {
15217 if ($rotate) {
15218 if ($rotate == 90) {
15219 $adjx = -($lk['x']-$bbox_x) + ($preroth - ($lk['y']-$bbox_y));
15220 $adjy = -($lk['y']-$bbox_y) + ($lk['x']-$bbox_x);
15221 }
15222 else if ($rotate == -90) {
15223 $adjx = -($lk['x']-$bbox_x) + ($lk['y']-$bbox_y);
15224 $adjy = -($lk['y']-$bbox_y) - ($lk['x']-$bbox_x) + $prerotw;
15225 }
15226 if ($rot_rpos !== false) { $adjx += $prerotw - $preroth; }
15227 if ($rot_bpos !== false) { $adjy += $preroth - $prerotw; }
15228 $lk['x'] += $adjx;
15229 $lk['y'] += $adjy;
15230 }
15231 if ($shrink_f != 1) { // i.e. autofit has resized the box
15232 $lk['x'] = $x + (($lk['x']-$x) * $shrink_f);
15233 $lk['y'] = $y + (($lk['y']-$y) * $shrink_f);
15234 }
15235 $this->PageAnnots[$this->page][]=$lk;
15236 }
15237
15238 // Restore
15239 $this->headerbuffer = '';
15240 $this->HTMLheaderPageLinks = array();
15241 $this->HTMLheaderPageAnnots = array();
15242 $this->HTMLheaderPageForms = array();
15243 $this->pageBackgrounds = $save_bgs;
15244 $this->writingHTMLheader = false;
15245
15246 $this->writingHTMLfooter = false;
15247 $this->fullImageHeight = false;
15248 $this->ResetMargins();
15249 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
15250 $this->SetXY($save_x,$save_y) ;
15251 $this->title2annots = $save_annots; // *ANNOTATIONS*
15252 $this->InFooter = false; // turns back on autopagebreaks
15253 $this->pageoutput[$this->page]=array();
15254 $this->pageoutput[$this->page]['Font']='';
15255 /*-- COLUMNS --*/
15256 if ($save_cols) {
15257 $this->SetColumns($save_nbcol,$this->colvAlign,$this->ColGap);
15258 }
15259 /*-- END COLUMNS --*/
15260 }
15261 /*-- END CSS-POSITION --*/
15262
15263
15264
15265 function initialiseBlock(&$blk) {
15266 $blk['margin_top'] = 0;
15267 $blk['margin_left'] = 0;
15268 $blk['margin_bottom'] = 0;
15269 $blk['margin_right'] = 0;
15270 $blk['padding_top'] = 0;
15271 $blk['padding_left'] = 0;
15272 $blk['padding_bottom'] = 0;
15273 $blk['padding_right'] = 0;
15274 $blk['border_top']['w'] = 0;
15275 $blk['border_left']['w'] = 0;
15276 $blk['border_bottom']['w'] = 0;
15277 $blk['border_right']['w'] = 0;
15278 $blk['direction'] = 'ltr';
15279 $blk['hide'] = false;
15280 $blk['outer_left_margin'] = 0;
15281 $blk['outer_right_margin'] = 0;
15282 $blk['cascadeCSS'] = array();
15283 $blk['block-align'] = false;
15284 $blk['bgcolor'] = false;
15285 $blk['page_break_after_avoid'] = false;
15286 $blk['keep_block_together'] = false;
15287 $blk['float'] = false;
15288 $blk['line_height'] = '';
15289 $blk['margin_collapse'] = false;
15290 }
15291
15292
15293 function border_details($bd) {
15294 $prop = preg_split('/\s+/',trim($bd));
15295
15296 if (isset($this->blk[$this->blklvl]['inner_width'])) { $refw = $this->blk[$this->blklvl]['inner_width']; }
15297 else if (isset($this->blk[$this->blklvl-1]['inner_width'])) { $refw = $this->blk[$this->blklvl-1]['inner_width']; }
15298 else { $refw = $this->w; }
15299 if ( count($prop) == 1 ) {
15300 $bsize = $this->ConvertSize($prop[0],$refw,$this->FontSize,false);
15301 if ($bsize > 0) {
15302 return array('s' => 1, 'w' => $bsize, 'c' => $this->ConvertColor(0), 'style'=>'solid');
15303 }
15304 else { return array('w' => 0, 's' => 0); }
15305 }
15306
15307 else if (count($prop) == 2 ) {
15308 // 1px solid
15309 if (in_array($prop[1],$this->borderstyles) || $prop[1] == 'none' || $prop[1] == 'hidden' ) { $prop[2] = ''; }
15310 // solid #000000
15311 else if (in_array($prop[0],$this->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) { $prop[0] = ''; $prop[1] = $prop[0]; $prop[2] = $prop[1]; }
15312 // 1px #000000
15313 else { $prop[1] = ''; $prop[2] = $prop[1]; }
15314 }
15315 else if ( count($prop) == 3 ) {
15316 // Change #000000 1px solid to 1px solid #000000 (proper)
15317 if (substr($prop[0],0,1) == '#') { $tmp = $prop[0]; $prop[0] = $prop[1]; $prop[1] = $prop[2]; $prop[2] = $tmp; }
15318 // Change solid #000000 1px to 1px solid #000000 (proper)
15319 else if (substr($prop[0],1,1) == '#') { $tmp = $prop[1]; $prop[0] = $prop[2]; $prop[1] = $prop[0]; $prop[2] = $tmp; }
15320 // Change solid 1px #000000 to 1px solid #000000 (proper)
15321 else if (in_array($prop[0],$this->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) {
15322 $tmp = $prop[0]; $prop[0] = $prop[1]; $prop[1] = $tmp;
15323 }
15324 }
15325 else { return array(); }
15326 // Size
15327 $bsize = $this->ConvertSize($prop[0],$refw,$this->FontSize,false);
15328 //color
15329 $coul = $this->ConvertColor($prop[2]); // returns array
15330 // Style
15331 $prop[1] = strtolower($prop[1]);
15332 if (in_array($prop[1],$this->borderstyles) && $bsize > 0) { $on = 1; }
15333 else if ($prop[1] == 'hidden') { $on = 1; $bsize = 0; $coul = ''; }
15334 else if ($prop[1] == 'none') { $on = 0; $bsize = 0; $coul = ''; }
15335 else { $on = 0; $bsize = 0; $coul = ''; $prop[1] = ''; }
15336 return array('s' => $on, 'w' => $bsize, 'c' => $coul, 'style'=> $prop[1] );
15337 }
15338
15339
15340
15341 /*-- END HTML-CSS --*/
15342
15343
15344 /*-- BORDER-RADIUS --*/
15345 function _borderPadding($a, $b, &$px, &$py) {
15346 // $px and py are padding long axis (x) and short axis (y)
15347 $added = 0; // extra padding
15348
15349 $x = $a-$px;
15350 $y = $b-$py;
15351 // Check if Falls within ellipse of border radius
15352 if ( ( (($x+$added)*($x+$added))/($a*$a) + (($y+$added)*($y+$added))/($b*$b) ) <=1 ) { return false; }
15353
15354 $t = atan2($y,$x);
15355
15356 $newx = $b / sqrt((($b*$b)/($a*$a)) + ( tan($t) * tan($t) ) );
15357 $newy = $a / sqrt((($a*$a)/($b*$b)) + ( (1/tan($t)) * (1/tan($t)) ) );
15358 $px = max($px, $a - $newx + $added);
15359 $py = max($py, $b - $newy + $added);
15360 }
15361 /*-- END BORDER-RADIUS --*/
15362
15363
15364
15365 /*-- HTML-CSS --*/
15366
15367
15368 /*-- CSS-PAGE --*/
15369 function SetPagedMediaCSS($name='', $first, $oddEven) {
15370 if ($oddEven == 'E') {
15371 if ($this->directionality=='rtl') { $side = 'R'; }
15372 else { $side = 'L'; }
15373 }
15374 else {
15375 if ($this->directionality=='rtl') { $side = 'L'; }
15376 else { $side = 'R'; }
15377 }
15378 $name = strtoupper($name);
15379 $p = array();
15380 $p['SIZE'] = 'AUTO';
15381
15382 // Uses mPDF original margins as default
15383 $p['MARGIN-RIGHT'] = strval($this->orig_rMargin).'mm';
15384 $p['MARGIN-LEFT'] = strval($this->orig_lMargin).'mm';
15385 $p['MARGIN-TOP'] = strval($this->orig_tMargin).'mm';
15386 $p['MARGIN-BOTTOM'] = strval($this->orig_bMargin).'mm';
15387 $p['MARGIN-HEADER'] = strval($this->orig_hMargin).'mm';
15388 $p['MARGIN-FOOTER'] = strval($this->orig_fMargin).'mm';
15389
15390 // Basic page + selector
15391 if (isset($this->cssmgr->CSS['@PAGE'])) { $zp = $this->cssmgr->CSS['@PAGE']; }
15392 else { $zp = array(); }
15393 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
15394
15395 if (isset($p['EVEN-HEADER-NAME']) && $oddEven=='E') {
15396 $p['HEADER'] = $p['EVEN-HEADER-NAME']; unset($p['EVEN-HEADER-NAME']);
15397 }
15398 if (isset($p['ODD-HEADER-NAME']) && $oddEven!='E') {
15399 $p['HEADER'] = $p['ODD-HEADER-NAME']; unset($p['ODD-HEADER-NAME']);
15400 }
15401 if (isset($p['EVEN-FOOTER-NAME']) && $oddEven=='E') {
15402 $p['FOOTER'] = $p['EVEN-FOOTER-NAME']; unset($p['EVEN-FOOTER-NAME']);
15403 }
15404 if (isset($p['ODD-FOOTER-NAME']) && $oddEven!='E') {
15405 $p['FOOTER'] = $p['ODD-FOOTER-NAME']; unset($p['ODD-FOOTER-NAME']);
15406 }
15407
15408 // If right/Odd page
15409 if (isset($this->cssmgr->CSS['@PAGE>>PSEUDO>>RIGHT']) && $side=='R') {
15410 $zp = $this->cssmgr->CSS['@PAGE>>PSEUDO>>RIGHT'];
15411 }
15412 else { $zp = array(); }
15413 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
15414 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
15415 // Disallow margin-left or -right on :LEFT or :RIGHT
15416 if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
15417 if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
15418 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
15419
15420 // If left/Even page
15421 if (isset($this->cssmgr->CSS['@PAGE>>PSEUDO>>LEFT']) && $side=='L') {
15422 $zp = $this->cssmgr->CSS['@PAGE>>PSEUDO>>LEFT'];
15423 }
15424 else { $zp = array(); }
15425 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
15426 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
15427 // Disallow margin-left or -right on :LEFT or :RIGHT
15428 if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
15429 if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
15430 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
15431
15432 // If first page
15433 if (isset($this->cssmgr->CSS['@PAGE>>PSEUDO>>FIRST']) && $first) { $zp = $this->cssmgr->CSS['@PAGE>>PSEUDO>>FIRST']; }
15434 else { $zp = array(); }
15435 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
15436 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
15437 // Disallow margin-left or -right on :FIRST // mPDF 5.7.3
15438 if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
15439 if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
15440 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
15441
15442 // If named page
15443 if ($name) {
15444 if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name])) { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name]; }
15445 else { $zp = array(); }
15446 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
15447
15448 if (isset($p['EVEN-HEADER-NAME']) && $oddEven=='E') {
15449 $p['HEADER'] = $p['EVEN-HEADER-NAME']; unset($p['EVEN-HEADER-NAME']);
15450 }
15451 if (isset($p['ODD-HEADER-NAME']) && $oddEven!='E') {
15452 $p['HEADER'] = $p['ODD-HEADER-NAME']; unset($p['ODD-HEADER-NAME']);
15453 }
15454 if (isset($p['EVEN-FOOTER-NAME']) && $oddEven=='E') {
15455 $p['FOOTER'] = $p['EVEN-FOOTER-NAME']; unset($p['EVEN-FOOTER-NAME']);
15456 }
15457 if (isset($p['ODD-FOOTER-NAME']) && $oddEven!='E') {
15458 $p['FOOTER'] = $p['ODD-FOOTER-NAME']; unset($p['ODD-FOOTER-NAME']);
15459 }
15460
15461 // If named right/Odd page
15462 if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>RIGHT']) && $side=='R') { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>RIGHT']; }
15463 else { $zp = array(); }
15464 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
15465 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
15466 // Disallow margin-left or -right on :LEFT or :RIGHT
15467 if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
15468 if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
15469 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
15470
15471 // If named left/Even page
15472 if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>LEFT']) && $side=='L') { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>LEFT']; }
15473 else { $zp = array(); }
15474 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
15475 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
15476 // Disallow margin-left or -right on :LEFT or :RIGHT
15477 if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
15478 if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
15479 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
15480
15481 // If named first page
15482 if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>FIRST']) && $first) { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>FIRST']; }
15483 else { $zp = array(); }
15484 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
15485 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
15486 // Disallow margin-left or -right on :FIRST // mPDF 5.7.3
15487 if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
15488 if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
15489 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
15490 }
15491
15492 $orientation = $mgl = $mgr = $mgt = $mgb = $mgh = $mgf = '';
15493 $header = $footer = '';
15494 $resetpagenum = $pagenumstyle = $suppress = '';
15495 $marks = '';
15496 $bg = array();
15497
15498 $newformat = '';
15499
15500
15501 if (isset($p['SHEET-SIZE']) && is_array($p['SHEET-SIZE'])) {
15502 $newformat = $p['SHEET-SIZE'];
15503 if ($newformat[0] > $newformat[1]) { // landscape
15504 $newformat = array_reverse($newformat);
15505 $p['ORIENTATION'] = 'L';
15506 }
15507 else { $p['ORIENTATION'] = 'P'; }
15508 $this->_setPageSize($newformat, $p['ORIENTATION']);
15509 }
15510
15511 if (isset($p['SIZE']) && is_array($p['SIZE']) && !$newformat) {
15512 if ($p['SIZE']['W'] > $p['SIZE']['H']) { $p['ORIENTATION'] = 'L'; }
15513 else { $p['ORIENTATION'] = 'P'; }
15514 }
15515 if (is_array($p['SIZE'])) {
15516 if ($p['SIZE']['W'] > $this->fw) { $p['SIZE']['W'] = $this->fw; } // mPD 4.2 use fw not fPt
15517 if ($p['SIZE']['H'] > $this->fh) { $p['SIZE']['H'] = $this->fh; }
15518 if (($p['ORIENTATION']==$this->DefOrientation && !$newformat) || ($newformat && $p['ORIENTATION']=='P')) {
15519 $outer_width_LR = ($this->fw - $p['SIZE']['W'])/2;
15520 $outer_width_TB = ($this->fh - $p['SIZE']['H'])/2;
15521 }
15522 else {
15523 $outer_width_LR = ($this->fh - $p['SIZE']['W'])/2;
15524 $outer_width_TB = ($this->fw - $p['SIZE']['H'])/2;
15525 }
15526 $pgw = $p['SIZE']['W'];
15527 $pgh = $p['SIZE']['H'];
15528 }
15529 else { // AUTO LANDSCAPE PORTRAIT
15530 $outer_width_LR = 0;
15531 $outer_width_TB = 0;
15532 if (!$newformat) {
15533 if (strtoupper($p['SIZE']) == 'AUTO') { $p['ORIENTATION']=$this->DefOrientation; }
15534 else if (strtoupper($p['SIZE']) == 'LANDSCAPE') { $p['ORIENTATION']='L'; }
15535 else { $p['ORIENTATION']='P'; }
15536 }
15537 if (($p['ORIENTATION']==$this->DefOrientation && !$newformat) || ($newformat && $p['ORIENTATION']=='P')) {
15538 $pgw = $this->fw;
15539 $pgh = $this->fh;
15540 }
15541 else {
15542 $pgw = $this->fh;
15543 $pgh = $this->fw;
15544 }
15545 }
15546
15547 if (isset($p['HEADER']) && $p['HEADER']) { $header = $p['HEADER']; }
15548 if (isset($p['FOOTER']) && $p['FOOTER']) { $footer = $p['FOOTER']; }
15549 if (isset($p['RESETPAGENUM']) && $p['RESETPAGENUM']) { $resetpagenum = $p['RESETPAGENUM']; }
15550 if (isset($p['PAGENUMSTYLE']) && $p['PAGENUMSTYLE']) { $pagenumstyle = $p['PAGENUMSTYLE']; }
15551 if (isset($p['SUPPRESS']) && $p['SUPPRESS']) { $suppress = $p['SUPPRESS']; }
15552
15553 if (isset($p['MARKS'])) {
15554 if (preg_match('/cross/i', $p['MARKS']) && preg_match('/crop/i', $p['MARKS'])) { $marks = 'CROPCROSS'; }
15555 else if (strtoupper($p['MARKS']) == 'CROP') { $marks = 'CROP'; }
15556 else if (strtoupper($p['MARKS']) == 'CROSS') { $marks = 'CROSS'; }
15557 }
15558
15559 if (isset($p['BACKGROUND-COLOR']) && $p['BACKGROUND-COLOR']) { $bg['BACKGROUND-COLOR'] = $p['BACKGROUND-COLOR']; }
15560 /*-- BACKGROUNDS --*/
15561 if (isset($p['BACKGROUND-GRADIENT']) && $p['BACKGROUND-GRADIENT']) { $bg['BACKGROUND-GRADIENT'] = $p['BACKGROUND-GRADIENT']; }
15562 if (isset($p['BACKGROUND-IMAGE']) && $p['BACKGROUND-IMAGE']) { $bg['BACKGROUND-IMAGE'] = $p['BACKGROUND-IMAGE']; }
15563 if (isset($p['BACKGROUND-REPEAT']) && $p['BACKGROUND-REPEAT']) { $bg['BACKGROUND-REPEAT'] = $p['BACKGROUND-REPEAT']; }
15564 if (isset($p['BACKGROUND-POSITION']) && $p['BACKGROUND-POSITION']) { $bg['BACKGROUND-POSITION'] = $p['BACKGROUND-POSITION']; }
15565 if (isset($p['BACKGROUND-IMAGE-RESIZE']) && $p['BACKGROUND-IMAGE-RESIZE']) { $bg['BACKGROUND-IMAGE-RESIZE'] = $p['BACKGROUND-IMAGE-RESIZE']; }
15566 if (isset($p['BACKGROUND-IMAGE-OPACITY'])) { $bg['BACKGROUND-IMAGE-OPACITY'] = $p['BACKGROUND-IMAGE-OPACITY']; }
15567 /*-- END BACKGROUNDS --*/
15568
15569 if (isset($p['MARGIN-LEFT'])) { $mgl = $this->ConvertSize($p['MARGIN-LEFT'],$pgw) + $outer_width_LR; }
15570 if (isset($p['MARGIN-RIGHT'])) { $mgr = $this->ConvertSize($p['MARGIN-RIGHT'],$pgw) + $outer_width_LR; }
15571 if (isset($p['MARGIN-BOTTOM'])) { $mgb = $this->ConvertSize($p['MARGIN-BOTTOM'],$pgh) + $outer_width_TB; }
15572 if (isset($p['MARGIN-TOP'])) { $mgt = $this->ConvertSize($p['MARGIN-TOP'],$pgh) + $outer_width_TB; }
15573 if (isset($p['MARGIN-HEADER'])) { $mgh = $this->ConvertSize($p['MARGIN-HEADER'],$pgh) + $outer_width_TB; }
15574 if (isset($p['MARGIN-FOOTER'])) { $mgf = $this->ConvertSize($p['MARGIN-FOOTER'],$pgh) + $outer_width_TB; }
15575
15576 if (isset($p['ORIENTATION']) && $p['ORIENTATION']) { $orientation = $p['ORIENTATION']; }
15577 $this->page_box['outer_width_LR'] = $outer_width_LR; // Used in MARKS:crop etc.
15578 $this->page_box['outer_width_TB'] = $outer_width_TB;
15579
15580 return array($orientation,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$header,$footer,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat);
15581 }
15582 /*-- END CSS-PAGE --*/
15583
15584
15585
15586 /*-- CSS-FLOAT --*/
15587 // Added mPDF 3.0 Float DIV - CLEAR
15588 function ClearFloats($clear, $blklvl=0) {
15589 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($blklvl,true);
15590 $end = $currpos = ($this->page*1000 + $this->y);
15591 if ($clear == 'BOTH' && ($l_exists || $r_exists)) {
15592 $this->pageoutput[$this->page] = array();
15593 $end = max($l_max, $r_max, $currpos);
15594 }
15595 else if ($clear == 'RIGHT' && $r_exists) {
15596 $this->pageoutput[$this->page] = array();
15597 $end = max($r_max, $currpos);
15598 }
15599 else if ($clear == 'LEFT' && $l_exists ) {
15600 $this->pageoutput[$this->page] = array();
15601 $end = max($l_max, $currpos);
15602 }
15603 else { return; }
15604 $old_page = $this->page;
15605 $new_page = intval($end/1000);
15606 if ($old_page != $new_page) {
15607 $s = $this->PrintPageBackgrounds();
15608 // Writes after the marker so not overwritten later by page background etc.
15609 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.$this->uniqstr.')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
15610 $this->pageBackgrounds = array();
15611 $this->page = $new_page;
15612 }
15613 $this->ResetMargins();
15614 $this->pageoutput[$this->page] = array();
15615 $this->y = (($end*1000) % 1000000)/1000; // mod changes operands to integers before processing
15616 }
15617
15618
15619 // Added mPDF 3.0 Float DIV
15620 function GetFloatDivInfo($blklvl=0,$clear=false) {
15621 // If blklvl specified, only returns floats at that level - for ClearFloats
15622 $l_exists = false;
15623 $r_exists = false;
15624 $l_max = 0;
15625 $r_max = 0;
15626 $l_width = 0;
15627 $r_width = 0;
15628 if (count($this->floatDivs)) {
15629 $currpos = ($this->page*1000 + $this->y);
15630 foreach($this->floatDivs AS $f) {
15631 if (($clear && $f['blockContext'] == $this->blk[$blklvl]['blockContext']) || (!$clear && $currpos >= $f['startpos'] && $currpos < ($f['endpos']-0.001) && $f['blklvl'] > $blklvl && $f['blockContext'] == $this->blk[$blklvl]['blockContext'])) {
15632 if ($f['side']=='L') {
15633 $l_exists= true;
15634 $l_max = max($l_max, $f['endpos']);
15635 $l_width = max($l_width , $f['w']);
15636 }
15637 if ($f['side']=='R') {
15638 $r_exists= true;
15639 $r_max = max($r_max, $f['endpos']);
15640 $r_width = max($r_width , $f['w']);
15641 }
15642 }
15643 }
15644 }
15645 return array($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width);
15646 }
15647 /*-- END CSS-FLOAT --*/
15648
15649
15650
15651
15652 function OpenTag($tag,$attr,&$ahtml,&$ihtml) { // mPDF 6
15653 //Opening tag
15654
15655 // mPDF 6
15656 // Correct for tags where HTML5 specifies optional end tags excluding table elements (cf WriteHTML() )
15657 if ($this->allow_html_optional_endtags) {
15658 if (isset($this->blk[$this->blklvl]['tag'])) {
15659 $closed = false;
15660 // li end tag may be omitted if immediately followed by another li element
15661 if (!$closed && $this->blk[$this->blklvl]['tag']=='LI' && $tag=='LI') { $this->CloseTag('LI',$ahtml,$ihtml); $closed = true; }
15662 // dt end tag may be omitted if immediately followed by another dt element or a dd element
15663 if (!$closed && $this->blk[$this->blklvl]['tag']=='DT' && ($tag=='DT' || $tag=='DD')) { $this->CloseTag('DT',$ahtml,$ihtml); $closed = true; }
15664 // dd end tag may be omitted if immediately followed by another dd element or a dt element
15665 if (!$closed && $this->blk[$this->blklvl]['tag']=='DD' && ($tag=='DT' || $tag=='DD')) { $this->CloseTag('DD',$ahtml,$ihtml); $closed = true; }
15666 // p end tag may be omitted if immediately followed by an address, article, aside, blockquote, div, dl, fieldset, form,
15667 // h1, h2, h3, h4, h5, h6, hgroup, hr, main, nav, ol, p, pre, section, table, ul
15668 if (!$closed && $this->blk[$this->blklvl]['tag']=='P' && ($tag == 'P' || $tag == 'DIV' || $tag == 'H1' || $tag == 'H2' || $tag == 'H3' || $tag == 'H4' || $tag == 'H5' || $tag == 'H6' || $tag == 'UL' || $tag == 'OL' || $tag == 'TABLE' || $tag=='PRE' || $tag=='FORM' || $tag=='ADDRESS' || $tag=='BLOCKQUOTE' || $tag=='CENTER' || $tag=='DL' || $tag == 'HR' || $tag=='ARTICLE' || $tag=='ASIDE' || $tag=='FIELDSET' || $tag=='HGROUP' || $tag=='MAIN' || $tag=='NAV' || $tag=='SECTION')) { $this->CloseTag('P',$ahtml,$ihtml); $closed = true; }
15669 // option end tag may be omitted if immediately followed by another option element (or if it is immediately followed by an optgroup element)
15670 if (!$closed && $this->blk[$this->blklvl]['tag']=='OPTION' && $tag=='OPTION') { $this->CloseTag('OPTION',$ahtml,$ihtml); $closed = true; }
15671 // Table elements - see also WriteHTML()
15672 if (!$closed && ($tag == 'TD' || $tag == 'TH') && $this->lastoptionaltag == 'TD') { $this->CloseTag($this->lastoptionaltag,$ahtml,$ihtml); $closed = true; } // *TABLES*
15673 if (!$closed && ($tag == 'TD' || $tag == 'TH') && $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag,$ahtml,$ihtml); $closed = true; } // *TABLES*
15674 if (!$closed && $tag == 'TR' && $this->lastoptionaltag == 'TR') { $this->CloseTag($this->lastoptionaltag,$ahtml,$ihtml); $closed = true; } // *TABLES*
15675 if (!$closed && $tag == 'TR' && $this->lastoptionaltag == 'TD') { $this->CloseTag($this->lastoptionaltag,$ahtml,$ihtml); $this->CloseTag('TR',$ahtml,$ihtml); $this->CloseTag('THEAD',$ahtml,$ihtml); $closed = true; } // *TABLES*
15676 if (!$closed && $tag == 'TR' && $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag,$ahtml,$ihtml); $this->CloseTag('TR',$ahtml,$ihtml); $this->CloseTag('THEAD',$ahtml,$ihtml); $closed = true; } // *TABLES*
15677 }
15678 }
15679
15680 $align = array('left'=>'L','center'=>'C','right'=>'R','top'=>'T','text-top'=>'TT','middle'=>'M','baseline'=>'BS','bottom'=>'B','text-bottom'=>'TB','justify'=>'J');
15681
15682
15683
15684 switch($tag){
15685
15686 case 'DOTTAB':
15687 $objattr = array();
15688 $objattr['type'] = 'dottab';
15689 $dots=str_repeat('.', 3)." "; // minimum number of dots
15690 $objattr['width'] = $this->GetStringWidth($dots);
15691 $objattr['margin_top'] = 0;
15692 $objattr['margin_bottom'] = 0;
15693 $objattr['margin_left'] = 0;
15694 $objattr['margin_right'] = 0;
15695 $objattr['height'] = 0;
15696 $objattr['colorarray'] = $this->colorarray;
15697 $objattr['border_top']['w'] = 0;
15698 $objattr['border_bottom']['w'] = 0;
15699 $objattr['border_left']['w'] = 0;
15700 $objattr['border_right']['w'] = 0;
15701 $objattr['vertical_align'] = 'BS'; // mPDF 6 DOTTAB
15702
15703 $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr);
15704 if (isset($properties['OUTDENT'])) {
15705 $objattr['outdent'] = $this->ConvertSize($properties['OUTDENT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15706 }
15707 else if (isset($attr['OUTDENT'])) {
15708 $objattr['outdent'] = $this->ConvertSize($attr['OUTDENT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15709 }
15710 else { $objattr['outdent'] = 0; }
15711
15712 $objattr['fontfamily'] = $this->FontFamily;
15713 $objattr['fontsize'] = $this->FontSizePt;
15714
15715 $e = "\xbb\xa4\xactype=dottab,objattr=".serialize($objattr)."\xbb\xa4\xac";
15716 /*-- TABLES --*/
15717 // Output it to buffers
15718 if ($this->tableLevel) {
15719 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
15720 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
15721 }
15722 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
15723 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
15724 }
15725 $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
15726 $this->_saveCellTextBuffer($e);
15727 }
15728 else {
15729 /*-- END TABLES --*/
15730 $this->_saveTextBuffer($e);
15731 } // *TABLES*
15732 break;
15733
15734 case 'PAGEHEADER':
15735 case 'PAGEFOOTER':
15736 $this->ignorefollowingspaces = true;
15737 if ($attr['NAME']) { $pname = $attr['NAME']; }
15738 else { $pname = '_nonhtmldefault'; } // mPDF 6
15739
15740 $p=array(); // mPDF 6
15741 $p['L']=array();
15742 $p['C']=array();
15743 $p['R']=array();
15744 $p['L']['font-style'] = '';
15745 $p['C']['font-style'] = '';
15746 $p['R']['font-style'] = '';
15747
15748 if (isset($attr['CONTENT-LEFT'])) {
15749 $p['L']['content'] = $attr['CONTENT-LEFT'];
15750 }
15751 if (isset($attr['CONTENT-CENTER'])) {
15752 $p['C']['content'] = $attr['CONTENT-CENTER'];
15753 }
15754 if (isset($attr['CONTENT-RIGHT'])) {
15755 $p['R']['content'] = $attr['CONTENT-RIGHT'];
15756 }
15757
15758 if (isset($attr['HEADER-STYLE']) || isset($attr['FOOTER-STYLE'])) { // font-family,size,weight,style,color
15759 if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE']); }
15760 else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE']); }
15761 if (isset($properties['FONT-FAMILY'])) {
15762 $p['L']['font-family'] = $properties['FONT-FAMILY'];
15763 $p['C']['font-family'] = $properties['FONT-FAMILY'];
15764 $p['R']['font-family'] = $properties['FONT-FAMILY'];
15765 }
15766 if (isset($properties['FONT-SIZE'])) {
15767 $p['L']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK;
15768 $p['C']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK;
15769 $p['R']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK;
15770 }
15771 if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') {
15772 $p['L']['font-style'] = 'B';
15773 $p['C']['font-style'] = 'B';
15774 $p['R']['font-style'] = 'B';
15775 }
15776 if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') {
15777 $p['L']['font-style'] .= 'I';
15778 $p['C']['font-style'] .= 'I';
15779 $p['R']['font-style'] .= 'I';
15780 }
15781 if (isset($properties['COLOR'])) {
15782 $p['L']['color'] = $properties['COLOR'];
15783 $p['C']['color'] = $properties['COLOR'];
15784 $p['R']['color'] = $properties['COLOR'];
15785 }
15786 }
15787 if (isset($attr['HEADER-STYLE-LEFT']) || isset($attr['FOOTER-STYLE-LEFT'])) {
15788 if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE-LEFT']); }
15789 else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE-LEFT']); }
15790 if (isset($properties['FONT-FAMILY'])) { $p['L']['font-family'] = $properties['FONT-FAMILY']; }
15791 if (isset($properties['FONT-SIZE'])) { $p['L']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK; }
15792 if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') { $p['L']['font-style'] ='B'; }
15793 if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') { $p['L']['font-style'] .='I'; }
15794 if (isset($properties['COLOR'])) { $p['L']['color'] = $properties['COLOR']; }
15795 }
15796 if (isset($attr['HEADER-STYLE-CENTER']) || isset($attr['FOOTER-STYLE-CENTER'])) {
15797 if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE-CENTER']); }
15798 else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE-CENTER']); }
15799 if (isset($properties['FONT-FAMILY'])) { $p['C']['font-family'] = $properties['FONT-FAMILY']; }
15800 if (isset($properties['FONT-SIZE'])) { $p['C']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK; }
15801 if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') { $p['C']['font-style'] = 'B'; }
15802 if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') { $p['C']['font-style'] .= 'I'; }
15803 if (isset($properties['COLOR'])) { $p['C']['color'] = $properties['COLOR']; }
15804 }
15805 if (isset($attr['HEADER-STYLE-RIGHT']) || isset($attr['FOOTER-STYLE-RIGHT'])) {
15806 if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE-RIGHT']); }
15807 else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE-RIGHT']); }
15808 if (isset($properties['FONT-FAMILY'])) { $p['R']['font-family'] = $properties['FONT-FAMILY']; }
15809 if (isset($properties['FONT-SIZE'])) { $p['R']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK; }
15810 if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') { $p['R']['font-style'] = 'B'; }
15811 if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') { $p['R']['font-style'] .= 'I'; }
15812 if (isset($properties['COLOR'])) { $p['R']['color'] = $properties['COLOR']; }
15813 }
15814 if (isset($attr['LINE']) && $attr['LINE']) { // 0|1|on|off
15815 if ($attr['LINE']=='1' || strtoupper($attr['LINE'])=='ON') { $lineset=1; }
15816 else { $lineset=0; }
15817 $p['line'] = $lineset;
15818 }
15819 // mPDF 6
15820 if ($tag=='PAGEHEADER') { $this->DefHeaderByName($pname,$p); }
15821 else { $this->DefFooterByName($pname,$p); }
15822 break;
15823
15824
15825 case 'SETPAGEHEADER': // mPDF 6
15826 case 'SETPAGEFOOTER':
15827 case 'SETHTMLPAGEHEADER':
15828 case 'SETHTMLPAGEFOOTER':
15829 $this->ignorefollowingspaces = true;
15830 if (isset($attr['NAME']) && $attr['NAME']) { $pname = $attr['NAME']; }
15831 else if ($tag=='SETPAGEHEADER' || $tag=='SETPAGEFOOTER') { $pname = '_nonhtmldefault'; } // mPDF 6
15832 else { $pname = '_default'; }
15833 if (isset($attr['PAGE']) && $attr['PAGE']) { // O|odd|even|E|ALL|[blank]
15834 if (strtoupper($attr['PAGE'])=='O' || strtoupper($attr['PAGE'])=='ODD') { $side='odd'; }
15835 else if (strtoupper($attr['PAGE'])=='E' || strtoupper($attr['PAGE'])=='EVEN') { $side='even'; }
15836 else if (strtoupper($attr['PAGE'])=='ALL') { $side='both'; }
15837 else { $side='odd'; }
15838 }
15839 else { $side='odd'; }
15840 if (isset($attr['VALUE']) && $attr['VALUE']) { // -1|1|on|off
15841 if ($attr['VALUE']=='1' || strtoupper($attr['VALUE'])=='ON') { $set=1; }
15842 else if ($attr['VALUE']=='-1' || strtoupper($attr['VALUE'])=='OFF') { $set=0; }
15843 else { $set=1; }
15844 }
15845 else { $set=1; }
15846 if (isset($attr['SHOW-THIS-PAGE']) && $attr['SHOW-THIS-PAGE'] && ($tag=='SETHTMLPAGEHEADER' || $tag=='SETPAGEHEADER')) { $write = 1; }
15847 else { $write = 0; }
15848 if ($side=='odd' || $side=='both') {
15849 if ($set && ($tag=='SETHTMLPAGEHEADER' || $tag=='SETPAGEHEADER')) { $this->SetHTMLHeader($this->pageHTMLheaders[$pname],'O',$write); }
15850 else if ($set && ($tag=='SETHTMLPAGEFOOTER' || $tag=='SETPAGEFOOTER')) { $this->SetHTMLFooter($this->pageHTMLfooters[$pname],'O'); }
15851 else if ($tag=='SETHTMLPAGEHEADER' || $tag=='SETPAGEHEADER') { $this->SetHTMLHeader('','O'); }
15852 else { $this->SetHTMLFooter('','O'); }
15853 }
15854 if ($side=='even' || $side=='both') {
15855 if ($set && ($tag=='SETHTMLPAGEHEADER' || $tag=='SETPAGEHEADER')) { $this->SetHTMLHeader($this->pageHTMLheaders[$pname],'E',$write); }
15856 else if ($set && ($tag=='SETHTMLPAGEFOOTER' || $tag=='SETPAGEFOOTER')) { $this->SetHTMLFooter($this->pageHTMLfooters[$pname],'E'); }
15857 else if ($tag=='SETHTMLPAGEHEADER' || $tag=='SETPAGEHEADER') { $this->SetHTMLHeader('','E'); }
15858 else { $this->SetHTMLFooter('','E'); }
15859 }
15860 break;
15861
15862
15863
15864 /*-- TOC --*/
15865 case 'TOC': //added custom-tag - set Marker for insertion later of ToC
15866 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
15867 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
15868 $this->tocontents->openTagTOC($attr);
15869 break;
15870
15871
15872
15873 case 'TOCPAGEBREAK': // custom-tag - set Marker for insertion later of ToC AND adds PAGEBREAK
15874 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
15875 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
15876 list($isbreak,$toc_id) = $this->tocontents->openTagTOCPAGEBREAK($attr);
15877 if ($isbreak) break;
15878 if (!isset($attr['RESETPAGENUM']) || $attr['RESETPAGENUM']<1) { $attr['RESETPAGENUM']=1; } // mPDF 6
15879 // No break - continues as PAGEBREAK...
15880 /*-- END TOC --*/
15881
15882
15883 case 'PAGE_BREAK': //custom-tag
15884 case 'PAGEBREAK': //custom-tag
15885 case 'NEWPAGE': //custom-tag
15886 case 'FORMFEED': //custom-tag
15887
15888 if (isset($attr['SHEET-SIZE'])) {
15889 // Convert to same types as accepted in initial mPDF() A4, A4-L, or array(w,h)
15890 $prop = preg_split('/\s+/',trim($attr['SHEET-SIZE']));
15891 if (count($prop) == 2 ) {
15892 $newformat = array($this->ConvertSize($prop[0]), $this->ConvertSize($prop[1]));
15893 }
15894 else { $newformat = $attr['SHEET-SIZE']; }
15895 }
15896 else { $newformat = ''; }
15897
15898 $save_blklvl = $this->blklvl;
15899 $save_blk = $this->blk;
15900 $save_silp = $this->saveInlineProperties();
15901 $save_ilp = $this->InlineProperties;
15902 $save_bflp = $this->InlineBDF;
15903 $save_bflpc = $this->InlineBDFctr; // mPDF 6
15904
15905 $mgr = $mgl = $mgt = $mgb = $mgh = $mgf = '';
15906 if (isset($attr['MARGIN-RIGHT'])) { $mgr = $this->ConvertSize($attr['MARGIN-RIGHT'],$this->w,$this->FontSize,false); }
15907 if (isset($attr['MARGIN-LEFT'])) { $mgl = $this->ConvertSize($attr['MARGIN-LEFT'],$this->w,$this->FontSize,false); }
15908 if (isset($attr['MARGIN-TOP'])) { $mgt = $this->ConvertSize($attr['MARGIN-TOP'],$this->w,$this->FontSize,false); }
15909 if (isset($attr['MARGIN-BOTTOM'])) { $mgb = $this->ConvertSize($attr['MARGIN-BOTTOM'],$this->w,$this->FontSize,false); }
15910 if (isset($attr['MARGIN-HEADER'])) { $mgh = $this->ConvertSize($attr['MARGIN-HEADER'],$this->w,$this->FontSize,false); }
15911 if (isset($attr['MARGIN-FOOTER'])) { $mgf = $this->ConvertSize($attr['MARGIN-FOOTER'],$this->w,$this->FontSize,false); }
15912 $ohname = $ehname = $ofname = $efname = '';
15913 if (isset($attr['ODD-HEADER-NAME'])) { $ohname = $attr['ODD-HEADER-NAME']; }
15914 if (isset($attr['EVEN-HEADER-NAME'])) { $ehname = $attr['EVEN-HEADER-NAME']; }
15915 if (isset($attr['ODD-FOOTER-NAME'])) { $ofname = $attr['ODD-FOOTER-NAME']; }
15916 if (isset($attr['EVEN-FOOTER-NAME'])) { $efname = $attr['EVEN-FOOTER-NAME']; }
15917 $ohvalue = $ehvalue = $ofvalue = $efvalue = 0;
15918 if (isset($attr['ODD-HEADER-VALUE']) && ($attr['ODD-HEADER-VALUE']=='1' || strtoupper($attr['ODD-HEADER-VALUE'])=='ON')) { $ohvalue = 1; }
15919 else if (isset($attr['ODD-HEADER-VALUE']) && ($attr['ODD-HEADER-VALUE']=='-1' || strtoupper($attr['ODD-HEADER-VALUE'])=='OFF')) { $ohvalue = -1; }
15920 if (isset($attr['EVEN-HEADER-VALUE']) && ($attr['EVEN-HEADER-VALUE']=='1' || strtoupper($attr['EVEN-HEADER-VALUE'])=='ON')) { $ehvalue = 1; }
15921 else if (isset($attr['EVEN-HEADER-VALUE']) && ($attr['EVEN-HEADER-VALUE']=='-1' || strtoupper($attr['EVEN-HEADER-VALUE'])=='OFF')) { $ehvalue = -1; }
15922 if (isset($attr['ODD-FOOTER-VALUE']) && ($attr['ODD-FOOTER-VALUE']=='1' || strtoupper($attr['ODD-FOOTER-VALUE'])=='ON')) { $ofvalue = 1; }
15923 else if (isset($attr['ODD-FOOTER-VALUE']) && ($attr['ODD-FOOTER-VALUE']=='-1' || strtoupper($attr['ODD-FOOTER-VALUE'])=='OFF')) { $ofvalue = -1; }
15924 if (isset($attr['EVEN-FOOTER-VALUE']) && ($attr['EVEN-FOOTER-VALUE']=='1' || strtoupper($attr['EVEN-FOOTER-VALUE'])=='ON')) { $efvalue = 1; }
15925 else if (isset($attr['EVEN-FOOTER-VALUE']) && ($attr['EVEN-FOOTER-VALUE']=='-1' || strtoupper($attr['EVEN-FOOTER-VALUE'])=='OFF')) { $efvalue = -1; }
15926
15927 if (isset($attr['ORIENTATION']) && (strtoupper($attr['ORIENTATION'])=='L' || strtoupper($attr['ORIENTATION'])=='LANDSCAPE')) { $orient = 'L'; }
15928 else if (isset($attr['ORIENTATION']) && (strtoupper($attr['ORIENTATION'])=='P' || strtoupper($attr['ORIENTATION'])=='PORTRAIT')) { $orient = 'P'; }
15929 else { $orient = $this->CurOrientation; }
15930
15931 if (isset($attr['PAGE-SELECTOR']) && $attr['PAGE-SELECTOR']) { $pagesel = $attr['PAGE-SELECTOR']; }
15932 else { $pagesel = ''; }
15933
15934 // mPDF 6 pagebreaktype
15935 $pagebreaktype = $this->defaultPagebreakType;
15936 if ($tag == 'FORMFEED') { $pagebreaktype = 'slice'; } // can be overridden by PAGE-BREAK-TYPE
15937 $startpage = $this->page;
15938 if (isset($attr['PAGE-BREAK-TYPE'])) {
15939 if (strtolower($attr['PAGE-BREAK-TYPE'])=='cloneall' || strtolower($attr['PAGE-BREAK-TYPE'])=='clonebycss' || strtolower($attr['PAGE-BREAK-TYPE'])=='slice') {
15940 $pagebreaktype = strtolower($attr['PAGE-BREAK-TYPE']);
15941 }
15942 }
15943 if ($tag == 'TOCPAGEBREAK') { $pagebreaktype = 'cloneall'; }
15944 else if ($this->ColActive) { $pagebreaktype = 'cloneall'; }
15945 // Any change in headers/footers (may need to _getHtmlHeight), or page size/orientation, @page selector, or margins - force cloneall
15946 else if ($mgr!=='' || $mgl!=='' || $mgt!=='' || $mgb!=='' || $mgh!=='' || $mgf!=='' ||
15947 $ohname!=='' || $ehname!=='' || $ofname!=='' || $efname!=='' ||
15948 $ohvalue || $ehvalue || $ofvalue || $efvalue ||
15949 $orient != $this->CurOrientation || $newformat || $pagesel) {
15950 $pagebreaktype = 'cloneall';
15951 }
15952
15953 // mPDF 6 pagebreaktype
15954 $this->_preForcedPagebreak($pagebreaktype);
15955
15956 $this->ignorefollowingspaces = true;
15957
15958
15959 $resetpagenum = '';
15960 $pagenumstyle = '';
15961 $suppress = '';
15962 if (isset($attr['RESETPAGENUM'])) { $resetpagenum = $attr['RESETPAGENUM']; }
15963 if (isset($attr['PAGENUMSTYLE'])) { $pagenumstyle = $attr['PAGENUMSTYLE']; }
15964 if (isset($attr['SUPPRESS'])) { $suppress = $attr['SUPPRESS']; }
15965
15966 if ($tag == 'TOCPAGEBREAK') { $type = 'NEXT-ODD'; }
15967 else if(isset($attr['TYPE'])) { $type = strtoupper($attr['TYPE']); }
15968 else { $type = ''; }
15969
15970 if ($type == 'E' || $type == 'EVEN') { $this->AddPage($orient,'E', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat); }
15971 else if ($type == 'O' || $type == 'ODD') { $this->AddPage($orient,'O', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat); }
15972 else if ($type == 'NEXT-ODD') { $this->AddPage($orient,'NEXT-ODD', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat); }
15973 else if ($type == 'NEXT-EVEN') { $this->AddPage($orient,'NEXT-EVEN', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat); }
15974 else { $this->AddPage($orient,'', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat); }
15975
15976 /*-- TOC --*/
15977 if ($tag == 'TOCPAGEBREAK') {
15978 if ($toc_id) { $this->tocontents->m_TOC[$toc_id]['TOCmark'] = $this->page; }
15979 else { $this->tocontents->TOCmark = $this->page; }
15980 }
15981 /*-- END TOC --*/
15982
15983 // mPDF 6 pagebreaktype
15984 $this->_postForcedPagebreak($pagebreaktype, $startpage, $save_blk, $save_blklvl);
15985
15986 $this->InlineProperties = $save_ilp;
15987 $this->InlineBDF = $save_bflp;
15988 $this->InlineBDFctr = $save_bflpc; // mPDF 6
15989 $this->restoreInlineProperties($save_silp);
15990
15991 break;
15992
15993
15994 /*-- TOC --*/
15995 case 'TOCENTRY':
15996 if (isset($attr['CONTENT']) && $attr['CONTENT']) {
15997 $objattr = array();
15998 $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES);
15999 $objattr['type'] = 'toc';
16000 $objattr['vertical-align'] = 'T';
16001 if (isset($attr['LEVEL']) && $attr['LEVEL']) { $objattr['toclevel'] = $attr['LEVEL']; } else { $objattr['toclevel'] = 0; }
16002 if (isset($attr['NAME']) && $attr['NAME']) { $objattr['toc_id'] = $attr['NAME']; } else { $objattr['toc_id'] = 0; }
16003 $e = "\xbb\xa4\xactype=toc,objattr=".serialize($objattr)."\xbb\xa4\xac";
16004 if($this->tableLevel) { $this->cell[$this->row][$this->col]['textbuffer'][] = array($e); } // *TABLES*
16005 else { // *TABLES*
16006 $this->textbuffer[] = array($e);
16007 } // *TABLES*
16008 }
16009 break;
16010 /*-- END TOC --*/
16011
16012 /*-- INDEX --*/
16013 case 'INDEXENTRY':
16014 if (isset($attr['CONTENT']) && $attr['CONTENT']) {
16015 if (isset($attr['XREF']) && $attr['XREF']) {
16016 $this->IndexEntry(htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES),$attr['XREF']);
16017 break;
16018 }
16019 $objattr = array();
16020 $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES);
16021 $objattr['type'] = 'indexentry';
16022 $objattr['vertical-align'] = 'T';
16023 $e = "\xbb\xa4\xactype=indexentry,objattr=".serialize($objattr)."\xbb\xa4\xac";
16024 if($this->tableLevel) { $this->cell[$this->row][$this->col]['textbuffer'][] = array($e); } // *TABLES*
16025 else { // *TABLES*
16026 $this->textbuffer[] = array($e);
16027 } // *TABLES*
16028 }
16029 break;
16030
16031
16032 case 'INDEXINSERT':
16033 if (isset($attr['COLLATION'])) { $indexCollationLocale = $attr['COLLATION']; } else { $indexCollationLocale = ''; }
16034 if (isset($attr['COLLATION-GROUP'])) { $indexCollationGroup = $attr['COLLATION-GROUP']; } else { $indexCollationGroup = ''; }
16035 if (isset($attr['USEDIVLETTERS']) && (strtoupper($attr['USEDIVLETTERS'])=='OFF' || $attr['USEDIVLETTERS']==-1 || $attr['USEDIVLETTERS']==='0')) { $usedivletters = 0; }
16036 else { $usedivletters = 1; }
16037 if (isset($attr['LINKS']) && (strtoupper($attr['LINKS'])=='ON' || $attr['LINKS']==1)) { $links = true; }
16038 else { $links = false; }
16039 $this->InsertIndex($usedivletters, $links, $indexCollationLocale, $indexCollationGroup);
16040
16041 break;
16042 /*-- END INDEX --*/
16043
16044 /*-- WATERMARK --*/
16045
16046 case 'WATERMARKTEXT':
16047 if (isset($attr['CONTENT']) && $attr['CONTENT']) { $txt = htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES); } else { $txt = ''; }
16048 if (isset($attr['ALPHA']) && $attr['ALPHA']>0) { $alpha = $attr['ALPHA']; } else { $alpha = -1; }
16049 $this->SetWatermarkText($txt, $alpha);
16050 break;
16051
16052
16053 case 'WATERMARKIMAGE':
16054 if (isset($attr['SRC'])) { $src = $attr['SRC']; } else { $src = ''; }
16055 if (isset($attr['ALPHA']) && $attr['ALPHA']>0) { $alpha = $attr['ALPHA']; } else { $alpha = -1; }
16056 if (isset($attr['SIZE']) && $attr['SIZE']) {
16057 $size = $attr['SIZE'];
16058 if (strpos($size,',')) { $size = explode(',',$size); }
16059 }
16060 else { $size = 'D'; }
16061 if (isset($attr['POSITION']) && $attr['POSITION']) { // mPDF 5.7.2
16062 $pos = $attr['POSITION'];
16063 if (strpos($pos,',')) { $pos = explode(',',$pos); }
16064 }
16065 else { $pos = 'P'; }
16066 $this->SetWatermarkImage($src, $alpha, $size, $pos);
16067 break;
16068 /*-- END WATERMARK --*/
16069
16070 /*-- BOOKMARKS --*/
16071 case 'BOOKMARK':
16072 if (isset($attr['CONTENT'])) {
16073 $objattr = array();
16074 $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES);
16075 $objattr['type'] = 'bookmark';
16076 if (isset($attr['LEVEL']) && $attr['LEVEL']) { $objattr['bklevel'] = $attr['LEVEL']; } else { $objattr['bklevel'] = 0; }
16077 $e = "\xbb\xa4\xactype=bookmark,objattr=".serialize($objattr)."\xbb\xa4\xac";
16078 if($this->tableLevel) { $this->cell[$this->row][$this->col]['textbuffer'][] = array($e); } // *TABLES*
16079 else { // *TABLES*
16080 $this->textbuffer[] = array($e);
16081 } // *TABLES*
16082 }
16083 break;
16084 /*-- END BOOKMARKS --*/
16085
16086 /*-- ANNOTATIONS --*/
16087 case 'ANNOTATION':
16088
16089 //if (isset($attr['CONTENT']) && !$this->writingHTMLheader && !$this->writingHTMLfooter) { // Stops annotations in FixedPos
16090 if (isset($attr['CONTENT'])) {
16091 $objattr = array();
16092 $objattr['margin_top'] = 0;
16093 $objattr['margin_bottom'] = 0;
16094 $objattr['margin_left'] = 0;
16095 $objattr['margin_right'] = 0;
16096 $objattr['width'] = 0;
16097 $objattr['height'] = 0;
16098 $objattr['border_top']['w'] = 0;
16099 $objattr['border_bottom']['w'] = 0;
16100 $objattr['border_left']['w'] = 0;
16101 $objattr['border_right']['w'] = 0;
16102 $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES);
16103 $objattr['type'] = 'annot';
16104 $objattr['POPUP'] = '';
16105 }
16106 else { break; }
16107 if (isset($attr['POS-X'])) { $objattr['POS-X'] = $attr['POS-X']; } else { $objattr['POS-X'] = 0; }
16108 if (isset($attr['POS-Y'])) { $objattr['POS-Y'] = $attr['POS-Y']; } else { $objattr['POS-Y'] = 0; }
16109 if (isset($attr['ICON'])) { $objattr['ICON'] = $attr['ICON']; } else { $objattr['ICON'] = 'Note'; }
16110 if (isset($attr['AUTHOR'])) { $objattr['AUTHOR'] = $attr['AUTHOR']; }
16111 else if (isset($attr['TITLE'])) { $objattr['AUTHOR'] = $attr['TITLE']; } else { $objattr['AUTHOR'] = ''; }
16112 if (isset($attr['FILE'])) { $objattr['FILE'] = $attr['FILE']; } else { $objattr['FILE'] = ''; }
16113 if (isset($attr['SUBJECT'])) { $objattr['SUBJECT'] = $attr['SUBJECT']; } else { $objattr['SUBJECT'] = ''; }
16114 if (isset($attr['OPACITY']) && $attr['OPACITY']>0 && $attr['OPACITY']<=1) { $objattr['OPACITY'] = $attr['OPACITY']; }
16115 else if ($this->annotMargin) { $objattr['OPACITY'] = 1; }
16116 else { $objattr['OPACITY'] = $this->annotOpacity; }
16117 if (isset($attr['COLOR'])) {
16118 $cor = $this->ConvertColor($attr['COLOR']);
16119 if ($cor) { $objattr['COLOR'] = $cor; }
16120 else { $objattr['COLOR'] = $this->ConvertColor('yellow'); }
16121 }
16122 else { $objattr['COLOR'] = $this->ConvertColor('yellow'); }
16123
16124 if (isset($attr['POPUP']) && !empty($attr['POPUP'])) {
16125 $pop = preg_split('/\s+/',trim($attr['POPUP']));
16126 if (count($pop)>1) { $objattr['POPUP'] = $pop; }
16127 else { $objattr['POPUP'] = true; }
16128 }
16129 $e = "\xbb\xa4\xactype=annot,objattr=".serialize($objattr)."\xbb\xa4\xac";
16130 if($this->tableLevel) { $this->cell[$this->row][$this->col]['textbuffer'][] = array($e); } // *TABLES*
16131 else { // *TABLES*
16132 $this->textbuffer[] = array($e);
16133 } // *TABLES*
16134 break;
16135 /*-- END ANNOTATIONS --*/
16136
16137
16138 /*-- COLUMNS --*/
16139 case 'COLUMNS': //added custom-tag
16140 if (isset($attr['COLUMN-COUNT']) && ($attr['COLUMN-COUNT'] || $attr['COLUMN-COUNT']==='0')) {
16141 // Close any open block tags
16142 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag'],$ahtml,$ihtml); }
16143 if(!empty($this->textbuffer)) { //Output previously buffered content
16144 $this->printbuffer($this->textbuffer);
16145 $this->textbuffer=array();
16146 }
16147
16148 if (isset($attr['VALIGN']) && $attr['VALIGN']) {
16149 if ($attr['VALIGN'] == 'J') { $valign = 'J'; }
16150 else { $valign = $align[$attr['VALIGN']]; }
16151 }
16152 else { $valign = ''; }
16153 if (isset($attr['COLUMN-GAP']) && $attr['COLUMN-GAP']) { $this->SetColumns($attr['COLUMN-COUNT'],$valign,$attr['COLUMN-GAP']); }
16154 else { $this->SetColumns($attr['COLUMN-COUNT'],$valign); }
16155 }
16156 $this->ignorefollowingspaces = true;
16157 break;
16158
16159 case 'COLUMN_BREAK': //custom-tag
16160 case 'COLUMNBREAK': //custom-tag
16161 case 'NEWCOLUMN': //custom-tag
16162 $this->ignorefollowingspaces = true;
16163 $this->NewColumn();
16164 $this->ColumnAdjust = false; // disables all column height adjustment for the page.
16165 break;
16166
16167 /*-- END COLUMNS --*/
16168
16169
16170 case 'TTZ':
16171 $this->ttz = true;
16172 $this->InlineProperties[$tag] = $this->saveInlineProperties();
16173 $this->setCSS(array('FONT-FAMILY'=>'czapfdingbats','FONT-WEIGHT'=>'normal','FONT-STYLE'=>'normal'),'INLINE');
16174 break;
16175
16176 case 'TTS':
16177 $this->tts = true;
16178 $this->InlineProperties[$tag] = $this->saveInlineProperties();
16179 $this->setCSS(array('FONT-FAMILY'=>'csymbol','FONT-WEIGHT'=>'normal','FONT-STYLE'=>'normal'),'INLINE');
16180 break;
16181
16182 case 'TTA':
16183 $this->tta = true;
16184 $this->InlineProperties[$tag] = $this->saveInlineProperties();
16185
16186 if (in_array($this->FontFamily,$this->mono_fonts)) {
16187 $this->setCSS(array('FONT-FAMILY'=>'ccourier'),'INLINE');
16188 }
16189 else if (in_array($this->FontFamily,$this->serif_fonts)) {
16190 $this->setCSS(array('FONT-FAMILY'=>'ctimes'),'INLINE');
16191 }
16192 else {
16193 $this->setCSS(array('FONT-FAMILY'=>'chelvetica'),'INLINE');
16194 }
16195 break;
16196
16197
16198
16199 // INLINE PHRASES OR STYLES
16200 case 'SUB':
16201 case 'SUP':
16202 case 'ACRONYM':
16203 case 'BIG':
16204 case 'SMALL':
16205 case 'INS':
16206 case 'S':
16207 case 'STRIKE':
16208 case 'DEL':
16209 case 'STRONG':
16210 case 'CITE':
16211 case 'Q':
16212 case 'EM':
16213 case 'B':
16214 case 'I':
16215 case 'U':
16216 case 'SAMP':
16217 case 'CODE':
16218 case 'KBD':
16219 case 'TT':
16220 case 'VAR':
16221 case 'FONT':
16222 case 'MARK':
16223 case 'TIME':
16224 case 'BDO': // mPDF 6
16225 case 'BDI': // mPDF 6
16226
16227 case 'SPAN':
16228 /*-- ANNOTATIONS --*/
16229 if ($this->title2annots && isset($attr['TITLE'])) {
16230 $objattr = array();
16231 $objattr['margin_top'] = 0;
16232 $objattr['margin_bottom'] = 0;
16233 $objattr['margin_left'] = 0;
16234 $objattr['margin_right'] = 0;
16235 $objattr['width'] = 0;
16236 $objattr['height'] = 0;
16237 $objattr['border_top']['w'] = 0;
16238 $objattr['border_bottom']['w'] = 0;
16239 $objattr['border_left']['w'] = 0;
16240 $objattr['border_right']['w'] = 0;
16241
16242 $objattr['CONTENT'] = $attr['TITLE'];
16243 $objattr['type'] = 'annot';
16244 $objattr['POS-X'] = 0;
16245 $objattr['POS-Y'] = 0;
16246 $objattr['ICON'] = 'Comment';
16247 $objattr['AUTHOR'] = '';
16248 $objattr['SUBJECT'] = '';
16249 $objattr['OPACITY'] = $this->annotOpacity;
16250 $objattr['COLOR'] = $this->ConvertColor('yellow');
16251 $annot = "\xbb\xa4\xactype=annot,objattr=".serialize($objattr)."\xbb\xa4\xac";
16252 }
16253 /*-- END ANNOTATIONS --*/
16254
16255 // mPDF 5.7.3 Inline tags
16256 if (!isset($this->InlineProperties[$tag])) { $this->InlineProperties[$tag] = array($this->saveInlineProperties()); }
16257 else { $this->InlineProperties[$tag][] = $this->saveInlineProperties(); }
16258 if (isset($annot)) { // *ANNOTATIONS*
16259 if (!isset($this->InlineAnnots[$tag])) { $this->InlineAnnots[$tag] = array($annot); } // *ANNOTATIONS*
16260 else { $this->InlineAnnots[$tag][] = $annot; } // *ANNOTATIONS*
16261 } // *ANNOTATIONS*
16262
16263 $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr);
16264 if (!empty($properties)) $this->setCSS($properties,'INLINE');
16265
16266 // mPDF 6 Bidirectional formatting for inline elements
16267 $bdf = false;
16268 $bdf2 = '';
16269 $popd = '';
16270
16271 // Get current direction
16272 if (isset($this->blk[$this->blklvl]['direction'])) { $currdir = $this->blk[$this->blklvl]['direction']; }
16273 else { $currdir = 'ltr'; }
16274 if($this->tableLevel && isset($this->cell[$this->row][$this->col]['direction']) && $this->cell[$this->row][$this->col]['direction'] == 'rtl') {
16275 $currdir = 'rtl';
16276 }
16277 if (isset($attr['DIR']) and $attr['DIR'] != '') { $currdir = strtolower($attr['DIR']); }
16278 if(isset($properties['DIRECTION'])) { $currdir = strtolower($properties['DIRECTION']); }
16279
16280 // mPDF 6 bidi
16281 // cf. http://www.w3.org/TR/css3-writing-modes/#unicode-bidi
16282 if ($tag == 'BDO') {
16283 if (isset($attr['DIR']) and strtolower($attr['DIR']) == 'rtl') { $bdf = 0x202E; $popd = 'RLOPDF'; } // U+202E RLO
16284 else if (isset($attr['DIR']) and strtolower($attr['DIR']) == 'ltr') { $bdf = 0x202D; $popd = 'LROPDF'; } // U+202D LRO
16285 }
16286 else if ($tag == 'BDI') {
16287 if (isset($attr['DIR']) and strtolower($attr['DIR']) == 'rtl') { $bdf = 0x2067; $popd = 'RLIPDI'; } // U+2067 RLI
16288 else if (isset($attr['DIR']) and strtolower($attr['DIR']) == 'ltr') { $bdf = 0x2066; $popd = 'LRIPDI'; } // U+2066 LRI
16289 else { $bdf = 0x2068; $popd = 'FSIPDI'; } // U+2068 FSI
16290 }
16291 else if(isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI'])=='bidi-override') {
16292 if ($currdir == 'rtl') { $bdf = 0x202E; $popd = 'RLOPDF';} // U+202E RLO
16293 else { $bdf = 0x202D; $popd = 'LROPDF'; } // U+202D LRO
16294 }
16295 else if(isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI'])=='embed') {
16296 if ($currdir == 'rtl') { $bdf = 0x202B; $popd = 'RLEPDF';} // U+202B RLE
16297 else { $bdf = 0x202A; $popd = 'LREPDF'; } // U+202A LRE
16298 }
16299 else if(isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI'])=='isolate') {
16300 if ($currdir == 'rtl') { $bdf = 0x2067; $popd = 'RLIPDI'; } // U+2067 RLI
16301 else { $bdf = 0x2066; $popd = 'LRIPDI'; } // U+2066 LRI
16302 }
16303 else if(isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI'])=='isolate-override') {
16304 if ($currdir == 'rtl') { $bdf = 0x2067; $bdf2 = 0x202E; $popd = 'RLIRLOPDFPDI'; } // U+2067 RLI // U+202E RLO
16305 else { $bdf = 0x2066; $bdf2 = 0x202D; $popd = 'LRILROPDFPDI'; } // U+2066 LRI // U+202D LRO
16306 }
16307 else if(isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI'])=='plaintext') {
16308 $bdf = 0x2068; $popd = 'FSIPDI'; // U+2068 FSI
16309 }
16310 else {
16311 if (isset($attr['DIR']) and strtolower($attr['DIR']) == 'rtl') { $bdf = 0x202B; $popd = 'RLEPDF'; } // U+202B RLE
16312 else if (isset($attr['DIR']) and strtolower($attr['DIR']) == 'ltr') { $bdf = 0x202A; $popd = 'LREPDF'; } // U+202A LRE
16313 }
16314
16315 if ($bdf) {
16316 // mPDF 5.7.3 Inline tags
16317 if (!isset($this->InlineBDF[$tag])) { $this->InlineBDF[$tag] = array(array($popd, $this->InlineBDFctr)); }
16318 else { $this->InlineBDF[$tag][] = array($popd, $this->InlineBDFctr); }
16319 $this->InlineBDFctr++;
16320 if ($bdf2) { $bdf2 = code2utf($bdf); }
16321 $this->OTLdata = array();
16322 if($this->tableLevel) { $this->_saveCellTextBuffer(code2utf($bdf).$bdf2); }
16323 else { $this->_saveTextBuffer(code2utf($bdf).$bdf2); }
16324 $this->biDirectional = true;
16325 }
16326
16327 break;
16328
16329
16330 case 'A':
16331 if (isset($attr['NAME']) and $attr['NAME'] != '') {
16332 $e = '';
16333 /*-- BOOKMARKS --*/
16334 if ($this->anchor2Bookmark) {
16335 $objattr = array();
16336 $objattr['CONTENT'] = htmlspecialchars_decode($attr['NAME'],ENT_QUOTES);
16337 $objattr['type'] = 'bookmark';
16338 if (isset($attr['LEVEL']) && $attr['LEVEL']) { $objattr['bklevel'] = $attr['LEVEL']; } else { $objattr['bklevel'] = 0; }
16339 $e = "\xbb\xa4\xactype=bookmark,objattr=".serialize($objattr)."\xbb\xa4\xac";
16340 }
16341 /*-- END BOOKMARKS --*/
16342 if($this->tableLevel) { // *TABLES*
16343 $this->_saveCellTextBuffer($e, '', $attr['NAME']); // *TABLES*
16344 } // *TABLES*
16345 else { // *TABLES*
16346 $this->_saveTextBuffer($e, '', $attr['NAME']); //an internal link (adds a space for recognition)
16347 } // *TABLES*
16348 }
16349 if (isset($attr['HREF'])) {
16350 $this->InlineProperties['A'] = $this->saveInlineProperties();
16351 $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr);
16352 if (!empty($properties)) $this->setCSS($properties,'INLINE');
16353 $this->HREF=$attr['HREF']; // mPDF 5.7.4 URLs
16354 }
16355 break;
16356
16357 case 'LEGEND':
16358 $this->InlineProperties['LEGEND'] = $this->saveInlineProperties();
16359 $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr);
16360 if (!empty($properties)) $this->setCSS($properties,'INLINE');
16361 break;
16362
16363
16364
16365 case 'PROGRESS':
16366 case 'METER':
16367 $this->inMeter = true;
16368
16369 if (isset($attr['MAX']) && $attr['MAX']) { $max = $attr['MAX']; }
16370 else { $max = 1; }
16371 if (isset($attr['MIN']) && $attr['MIN'] && $tag=='METER') { $min = $attr['MIN']; }
16372 else { $min = 0; }
16373 if ($max < $min) { $max = $min; }
16374
16375 if (isset($attr['VALUE']) && ($attr['VALUE'] || $attr['VALUE']==='0')) {
16376 $value = $attr['VALUE'];
16377 if ($value < $min) { $value = $min; }
16378 else if ($value > $max) { $value = $max; }
16379 }
16380 else { $value = ''; }
16381
16382 if (isset($attr['LOW']) && $attr['LOW']) { $low = $attr['LOW']; }
16383 else { $low = $min; }
16384 if ($low < $min) { $low = $min; }
16385 else if ($low > $max) { $low = $max; }
16386 if (isset($attr['HIGH']) && $attr['HIGH']) { $high = $attr['HIGH']; }
16387 else { $high = $max; }
16388 if ($high < $low) { $high = $low; }
16389 else if ($high > $max) { $high = $max; }
16390 if (isset($attr['OPTIMUM']) && $attr['OPTIMUM']) { $optimum = $attr['OPTIMUM']; }
16391 else { $optimum = $min + (($max-$min)/2); }
16392 if ($optimum < $min) { $optimum = $min; }
16393 else if ($optimum > $max) { $optimum = $max; }
16394 if (isset($attr['TYPE']) && $attr['TYPE']) { $type = $attr['TYPE']; }
16395 else { $type = ''; }
16396 $objattr = array();
16397 $objattr['margin_top'] = 0;
16398 $objattr['margin_bottom'] = 0;
16399 $objattr['margin_left'] = 0;
16400 $objattr['margin_right'] = 0;
16401 $objattr['padding_top'] = 0;
16402 $objattr['padding_bottom'] = 0;
16403 $objattr['padding_left'] = 0;
16404 $objattr['padding_right'] = 0;
16405 $objattr['width'] = 0;
16406 $objattr['height'] = 0;
16407 $objattr['border_top']['w'] = 0;
16408 $objattr['border_bottom']['w'] = 0;
16409 $objattr['border_left']['w'] = 0;
16410 $objattr['border_right']['w'] = 0;
16411
16412 $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr);
16413 if(isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY'])=='none') {
16414 return;
16415 }
16416 $objattr['visibility'] = 'visible';
16417 if (isset($properties['VISIBILITY'])) {
16418 $v = strtolower($properties['VISIBILITY']);
16419 if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible') {
16420 $objattr['visibility'] = $v;
16421 }
16422 }
16423
16424 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16425 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16426 if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16427 if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16428
16429 if (isset($properties['PADDING-TOP'])) { $objattr['padding_top']=$this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16430 if (isset($properties['PADDING-BOTTOM'])) { $objattr['padding_bottom'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16431 if (isset($properties['PADDING-LEFT'])) { $objattr['padding_left'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16432 if (isset($properties['PADDING-RIGHT'])) { $objattr['padding_right'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16433
16434 if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
16435 if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
16436 if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
16437 if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
16438
16439 if (isset($properties['VERTICAL-ALIGN'])) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
16440 $w = 0;
16441 $h = 0;
16442 if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16443 else if(isset($attr['WIDTH'])) $w = $this->ConvertSize($attr['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16444
16445 if(isset($properties['HEIGHT'])) $h = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16446 else if(isset($attr['HEIGHT'])) $h = $this->ConvertSize($attr['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16447
16448 if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { $objattr['opacity'] = $properties['OPACITY']; }
16449 if ($this->HREF) {
16450 if (strpos($this->HREF,".") === false && strpos($this->HREF,"@") !== 0) {
16451 $href = $this->HREF;
16452 while(array_key_exists($href,$this->internallink)) $href="#".$href;
16453 $this->internallink[$href] = $this->AddLink();
16454 $objattr['link'] = $this->internallink[$href];
16455 }
16456 else { $objattr['link'] = $this->HREF; }
16457 }
16458 $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
16459 $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
16460
16461 // Image file
16462 if (!class_exists('meter', false)) {
16463 include(_MPDF_PATH.'classes/meter.php');
16464 }
16465 $this->meter = new meter();
16466 $svg = $this->meter->makeSVG(strtolower($tag), $type, $value, $max, $min, $optimum, $low, $high);
16467 //Save to local file
16468 $srcpath= _MPDF_TEMP_PATH.'_tempSVG'.uniqid(rand(1,100000),true).'_'.strtolower($tag).'.svg';
16469 file_put_contents($srcpath, $svg);
16470 $orig_srcpath = $srcpath;
16471 $this->GetFullPath($srcpath);
16472
16473 $info=$this->_getImage($srcpath, true, true, $orig_srcpath);
16474 if(!$info) {
16475 $info = $this->_getImage($this->noImageFile);
16476 if ($info) {
16477 $srcpath = $this->noImageFile;
16478 $w = ($info['w'] * (25.4/$this->dpi));
16479 $h = ($info['h'] * (25.4/$this->dpi));
16480 }
16481 }
16482 if(!$info) break;
16483
16484 $objattr['file'] = $srcpath;
16485 //Default width and height calculation if needed
16486 if($w==0 and $h==0) {
16487 // SVG units are pixels
16488 $w = $this->FontSize/(10/_MPDFK) * abs($info['w'])/_MPDFK;
16489 $h = $this->FontSize/(10/_MPDFK) * abs($info['h'])/_MPDFK;
16490 }
16491 // IF WIDTH OR HEIGHT SPECIFIED
16492 if($w==0) $w=abs($h*$info['w']/$info['h']);
16493 if($h==0) $h=abs($w*$info['h']/$info['w']);
16494
16495 // Resize to maximum dimensions of page
16496 $maxWidth = $this->blk[$this->blklvl]['inner_width'];
16497 $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 1) ;
16498 if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
16499 if (($w + $extrawidth) > ($maxWidth + 0.0001) ) { // mPDF 5.7.4 0.0001 to allow for rounding errors when w==maxWidth
16500 $w = $maxWidth - $extrawidth;
16501 $h=abs($w*$info['h']/$info['w']);
16502 }
16503
16504 if ($h + $extraheight > $maxHeight ) {
16505 $h = $maxHeight - $extraheight;
16506 $w=abs($h*$info['w']/$info['h']);
16507 }
16508 $objattr['type'] = 'image';
16509 $objattr['itype'] = $info['type'];
16510
16511 $objattr['orig_h'] = $info['h'];
16512 $objattr['orig_w'] = $info['w'];
16513 $objattr['wmf_x'] = $info['x'];
16514 $objattr['wmf_y'] = $info['y'];
16515 $objattr['height'] = $h + $extraheight;
16516 $objattr['width'] = $w + $extrawidth;
16517 $objattr['image_height'] = $h;
16518 $objattr['image_width'] = $w;
16519 $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
16520 $properties = array();
16521 if ($this->tableLevel) {
16522 $this->_saveCellTextBuffer($e, $this->HREF);
16523 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
16524 }
16525 else {
16526 $this->_saveTextBuffer($e, $this->HREF);
16527 }
16528
16529 break;
16530
16531
16532 case 'BR':
16533 // Added mPDF 3.0 Float DIV - CLEAR
16534 if (isset($attr['STYLE'])) {
16535 $properties = $this->cssmgr->readInlineCSS($attr['STYLE']);
16536 if (isset($properties['CLEAR'])) { $this->ClearFloats(strtoupper($properties['CLEAR']),$this->blklvl); } // *CSS-FLOAT*
16537 }
16538
16539 // mPDF 6 bidi
16540 // Inline
16541 // If unicode-bidi set, any embedding levels, isolates, or overrides started by the inline box are closed at the br and reopened on the other side
16542 $blockpre = '';
16543 $blockpost = '';
16544 if (isset($this->blk[$this->blklvl]['bidicode'])) {
16545 $blockpre = $this->_setBidiCodes('end', $this->blk[$this->blklvl]['bidicode']);
16546 $blockpost = $this->_setBidiCodes('start', $this->blk[$this->blklvl]['bidicode']);
16547 }
16548
16549 // Inline
16550 // If unicode-bidi set, any embedding levels, isolates, or overrides started by the inline box are closed at the br and reopened on the other side
16551 $inlinepre = '';
16552 $inlinepost = '';
16553 $iBDF = array();
16554 if (count($this->InlineBDF)) {
16555 foreach($this->InlineBDF AS $k => $ib) {
16556 foreach($ib AS $ib2) { $iBDF[$ib2[1]] = $ib2[0]; }
16557 }
16558 if (count($iBDF)) {
16559 ksort($iBDF);
16560 for($i=count($iBDF)-1;$i>=0;$i--) {
16561 $inlinepre .= $this->_setBidiCodes('end', $iBDF[$i]);
16562 }
16563 for($i=0;$i<count($iBDF);$i++) {
16564 $inlinepost .= $this->_setBidiCodes('start', $iBDF[$i]);
16565 }
16566 }
16567 }
16568
16569 /*-- TABLES --*/
16570 if($this->tableLevel) {
16571
16572 if ($this->blockjustfinished) {
16573 $this->_saveCellTextBuffer($blockpre.$inlinepre."\n".$inlinepost.$blockpost);
16574 }
16575
16576 $this->_saveCellTextBuffer($blockpre.$inlinepre."\n".$inlinepost.$blockpost);
16577 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
16578 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
16579 }
16580 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
16581 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
16582 }
16583 $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
16584 }
16585 else {
16586 /*-- END TABLES --*/
16587 if (count($this->textbuffer)) {
16588 $this->textbuffer[count($this->textbuffer)-1][0] = preg_replace('/ $/','',$this->textbuffer[count($this->textbuffer)-1][0]);
16589 if (!empty($this->textbuffer[count($this->textbuffer)-1][18])) { $this->otl->trimOTLdata($this->textbuffer[count($this->textbuffer)-1][18], false, true); } // *OTL*
16590 }
16591 $this->_saveTextBuffer($blockpre.$inlinepre."\n".$inlinepost.$blockpost);
16592 } // *TABLES*
16593 $this->ignorefollowingspaces = true;
16594 $this->blockjustfinished=false;
16595
16596 $this->linebreakjustfinished=true;
16597 break;
16598
16599
16600 // *********** BLOCKS ********************
16601
16602
16603 case 'PRE':
16604 $this->ispre=true; // ADDED - Prevents left trim of textbuffer in printbuffer()
16605
16606 case 'DIV':
16607 case 'FORM':
16608 case 'CENTER':
16609
16610 case 'BLOCKQUOTE':
16611 case 'ADDRESS':
16612
16613 case 'CAPTION':
16614 case 'P':
16615 case 'H1':
16616 case 'H2':
16617 case 'H3':
16618 case 'H4':
16619 case 'H5':
16620 case 'H6':
16621 case 'DL':
16622 case 'DT':
16623 case 'DD':
16624 case 'UL': // mPDF 6 Lists
16625 case 'OL': // mPDF 6
16626 case 'LI': // mPDF 6
16627 case 'FIELDSET':
16628 case 'DETAILS':
16629 case 'SUMMARY':
16630 case 'ARTICLE':
16631 case 'ASIDE':
16632 case 'FIGURE':
16633 case 'FIGCAPTION':
16634 case 'FOOTER':
16635 case 'HEADER':
16636 case 'HGROUP':
16637 case 'NAV':
16638 case 'SECTION':
16639 case 'MAIN':
16640 // mPDF 6 Lists
16641 $this->lastoptionaltag = '';
16642
16643 // mPDF 6 bidi
16644 // Block
16645 // If unicode-bidi set on current clock, any embedding levels, isolates, or overrides are closed (not inherited)
16646 if (isset($this->blk[$this->blklvl]['bidicode'])) {
16647 $blockpost = $this->_setBidiCodes('end', $this->blk[$this->blklvl]['bidicode']);
16648 if ($blockpost) {
16649 $this->OTLdata = array();
16650 if($this->tableLevel) { $this->_saveCellTextBuffer($blockpost); }
16651 else { $this->_saveTextBuffer($blockpost); }
16652 }
16653 }
16654
16655
16656 $p = $this->cssmgr->PreviewBlockCSS($tag,$attr);
16657 if(isset($p['DISPLAY']) && strtolower($p['DISPLAY'])=='none') {
16658 $this->blklvl++;
16659 $this->blk[$this->blklvl]['hide'] = true;
16660 $this->blk[$this->blklvl]['tag'] = $tag; // mPDF 6
16661 return;
16662 }
16663 if($tag == 'CAPTION') {
16664 // position is written in AdjstHTML
16665 if (isset($attr['POSITION']) && strtolower($attr['POSITION'])=='bottom') { $divpos = 'B'; }
16666 else { $divpos = 'T'; }
16667 if (isset($attr['ALIGN']) && strtolower($attr['ALIGN'])=='bottom') { $cappos = 'B'; }
16668 else if (isset($p['CAPTION-SIDE']) && strtolower($p['CAPTION-SIDE'])=='bottom') { $cappos = 'B'; }
16669 else { $cappos = 'T'; }
16670 if (isset($attr['ALIGN'])) { unset($attr['ALIGN']); }
16671 if ($cappos != $divpos) {
16672 $this->blklvl++;
16673 $this->blk[$this->blklvl]['hide'] = true;
16674 $this->blk[$this->blklvl]['tag'] = $tag; // mPDF 6
16675 return;
16676 }
16677 }
16678
16679 /*-- FORMS --*/
16680 if($tag == 'FORM') {
16681 if (isset($attr['METHOD']) && strtolower($attr['METHOD'])=='get') { $this->mpdfform->formMethod = 'GET'; }
16682 else { $this->mpdfform->formMethod = 'POST'; }
16683 if (isset($attr['ACTION'])) { $this->mpdfform->formAction = $attr['ACTION']; }
16684 else { $this->mpdfform->formAction = ''; }
16685 }
16686 /*-- END FORMS --*/
16687
16688
16689 /*-- CSS-POSITION --*/
16690 if ((isset($p['POSITION']) && (strtolower($p['POSITION'])=='fixed' || strtolower($p['POSITION'])=='absolute')) && $this->blklvl==0) {
16691 if ($this->inFixedPosBlock) {
16692 $this->Error("Cannot nest block with position:fixed or position:absolute");
16693 }
16694 $this->inFixedPosBlock = true;
16695 return;
16696 }
16697 /*-- END CSS-POSITION --*/
16698 // Start Block
16699 $this->ignorefollowingspaces = true;
16700
16701 if ($this->blockjustfinished && !count($this->textbuffer) && $this->y != $this->tMargin && $this->collapseBlockMargins) { $lastbottommargin = $this->lastblockbottommargin; }
16702 else { $lastbottommargin = 0; }
16703 $this->lastblockbottommargin = 0;
16704 $this->blockjustfinished=false;
16705
16706
16707 $this->InlineBDF=array(); // mPDF 6
16708 $this->InlineBDFctr= 0; // mPDF 6
16709 $this->InlineProperties = array();
16710 $this->divbegin=true;
16711
16712 $this->linebreakjustfinished=false;
16713
16714 /*-- TABLES --*/
16715 if ($this->tableLevel) {
16716 // If already something on the line
16717 if ($this->cell[$this->row][$this->col]['s'] > 0 && !$this->nestedtablejustfinished ) {
16718 $this->_saveCellTextBuffer("\n");
16719 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
16720 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
16721 }
16722 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
16723 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
16724 }
16725 $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
16726 }
16727 // Cannot set block properties inside table - use Bold to indicate h1-h6
16728 if ($tag == 'CENTER' && $this->tdbegin) { $this->cell[$this->row][$this->col]['a'] = $align['center']; }
16729
16730 $this->InlineProperties['BLOCKINTABLE'] = $this->saveInlineProperties();
16731 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
16732 if (!empty($properties)) $this->setCSS($properties,'INLINE');
16733
16734 // mPDF 6 Lists
16735 if ($tag == 'UL' || $tag == 'OL') {
16736 $this->listlvl++;
16737 if (isset($attr['START'])) { $this->listcounter[$this->listlvl] = intval($attr['START'])-1; }
16738 else { $this->listcounter[$this->listlvl] = 0; }
16739 $this->listitem = array();
16740 if ($tag == 'OL') $this->listtype[$this->listlvl] = 'decimal';
16741 else if ($tag == 'UL') {
16742 if ($this->listlvl % 3 == 1) $this->listtype[$this->listlvl] = 'disc';
16743 elseif ($this->listlvl % 3 == 2) $this->listtype[$this->listlvl] = 'circle';
16744 else $this->listtype[$this->listlvl] = 'square';
16745 }
16746 }
16747
16748 // mPDF 6 Lists - in Tables
16749 if ($tag == 'LI') {
16750 if ($this->listlvl == 0) { //in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...)
16751 $this->listlvl++; // first depth level
16752 $this->listcounter[$this->listlvl] = 0;
16753 }
16754 $this->listcounter[$this->listlvl]++;
16755 $this->listitem = array();
16756 //if in table - output here as a tabletextbuffer
16757 //position:inside OR position:outside (always output in table as position:inside)
16758 switch($this->listtype[$this->listlvl]) {
16759 case 'upper-alpha':
16760 case 'upper-latin':
16761 case 'A':
16762 $blt = $this->dec2alpha($this->listcounter[$this->listlvl],true).$this->list_number_suffix;
16763 break;
16764 case 'lower-alpha':
16765 case 'lower-latin':
16766 case 'a':
16767 $blt = $this->dec2alpha($this->listcounter[$this->listlvl],false).$this->list_number_suffix;
16768 break;
16769 case 'upper-roman':
16770 case 'I':
16771 $blt = $this->dec2roman($this->listcounter[$this->listlvl],true).$this->list_number_suffix;
16772 break;
16773 case 'lower-roman':
16774 case 'i':
16775 $blt = $this->dec2roman($this->listcounter[$this->listlvl],false).$this->list_number_suffix;
16776 break;
16777 case 'decimal':
16778 case '1':
16779 $blt = $this->listcounter[$this->listlvl].$this->list_number_suffix;
16780 break;
16781 default:
16782 if ($this->listlvl % 3 == 1 && $this->_charDefined($this->CurrentFont['cw'],8226)) { $blt = "\xe2\x80\xa2"; } // &#8226;
16783 else if ($this->listlvl % 3 == 2 && $this->_charDefined($this->CurrentFont['cw'],9900)) { $blt = "\xe2\x9a\xac"; } // &#9900;
16784 else if ($this->listlvl % 3 == 0 && $this->_charDefined($this->CurrentFont['cw'],9642)) { $blt = "\xe2\x96\xaa"; } // &#9642;
16785 else { $blt = '-'; }
16786 break;
16787 }
16788
16789 // change to &nbsp; spaces
16790 if ($this->usingCoreFont) {
16791 $ls = str_repeat(chr(160).chr(160),($this->listlvl-1)*2) . $blt . ' ';
16792 }
16793 else {
16794 $ls = str_repeat("\xc2\xa0\xc2\xa0",($this->listlvl-1)*2) . $blt . ' ';
16795 }
16796 $this->_saveCellTextBuffer($ls);
16797 $this->cell[$this->row][$this->col]['s'] += $this->GetStringWidth($ls);
16798 }
16799
16800 break;
16801 }
16802 /*-- END TABLES --*/
16803
16804 if ($this->lastblocklevelchange == 1) { $blockstate = 1; } // Top margins/padding only
16805 else if ($this->lastblocklevelchange < 1) { $blockstate = 0; } // NO margins/padding
16806 $this->printbuffer($this->textbuffer,$blockstate);
16807 $this->textbuffer=array();
16808
16809 $save_blklvl = $this->blklvl;
16810 $save_blk = $this->blk;
16811
16812 $this->Reset();
16813
16814 $pagesel = '';
16815 /*-- CSS-PAGE --*/
16816 if (isset($p['PAGE'])) { $pagesel = $p['PAGE']; } // mPDF 6 (uses $p - preview of properties so blklvl can be incremented after page-break)
16817 /*-- END CSS-PAGE --*/
16818
16819 // If page-box has changed AND/OR PAGE-BREAK-BEFORE
16820 // mPDF 6 (uses $p - preview of properties so blklvl can be imcremented after page-break)
16821 if (!$this->tableLevel && (($pagesel && (!isset($this->page_box['current']) || $pagesel != $this->page_box['current'])) || (isset($p['PAGE-BREAK-BEFORE']) && $p['PAGE-BREAK-BEFORE']))) {
16822 // mPDF 6 pagebreaktype
16823 $startpage = $this->page;
16824 $pagebreaktype = $this->defaultPagebreakType;
16825 $this->lastblocklevelchange=-1;
16826 if ($this->ColActive) { $pagebreaktype = 'cloneall'; }
16827 if ($pagesel && (!isset($this->page_box['current']) || $pagesel != $this->page_box['current'])) { $pagebreaktype = 'cloneall'; }
16828 $this->_preForcedPagebreak($pagebreaktype);
16829
16830 if (isset($p['PAGE-BREAK-BEFORE'])) {
16831 if (strtoupper($p['PAGE-BREAK-BEFORE']) == 'RIGHT') { $this->AddPage($this->CurOrientation,'NEXT-ODD','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
16832 else if (strtoupper($p['PAGE-BREAK-BEFORE']) == 'LEFT') { $this->AddPage($this->CurOrientation,'NEXT-EVEN','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
16833 else if (strtoupper($p['PAGE-BREAK-BEFORE']) == 'ALWAYS') { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
16834 else if ($this->page_box['current'] != $pagesel) { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); } // *CSS-PAGE*
16835 }
16836 /*-- CSS-PAGE --*/
16837 // Must Add new page if changed page properties
16838 else if (!isset($this->page_box['current']) || $pagesel != $this->page_box['current']) {
16839 $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel);
16840 }
16841 /*-- END CSS-PAGE --*/
16842
16843 // mPDF 6 pagebreaktype
16844 $this->_postForcedPagebreak($pagebreaktype, $startpage, $save_blk, $save_blklvl);
16845
16846 }
16847
16848 // mPDF 6 pagebreaktype - moved after pagebreak
16849 $this->blklvl++;
16850 $currblk =& $this->blk[$this->blklvl];
16851 $this->initialiseBlock($currblk);
16852 $prevblk =& $this->blk[$this->blklvl-1];
16853 $currblk['tag'] = $tag;
16854 $currblk['attr'] = $attr;
16855
16856 $properties = $this->cssmgr->MergeCSS('BLOCK',$tag,$attr); // mPDF 6 - moved to after page-break-before
16857
16858 // mPDF 6 page-break-inside:avoid
16859 if (isset($properties['PAGE-BREAK-INSIDE']) && strtoupper($properties['PAGE-BREAK-INSIDE']) == 'AVOID' && !$this->ColActive && !$this->keep_block_together && !isset($attr['PAGEBREAKAVOIDCHECKED'])) { // avoid re-iterating using PAGEBREAKAVOIDCHECKED; set in CloseTag
16860 $currblk['keep_block_together'] = 1;
16861 $currblk['array_i'] = $ihtml; // mPDF 6
16862 $this->kt_y00 = $this->y;
16863 $this->kt_p00 = $this->page;
16864 $this->keep_block_together = 1;
16865 }
16866 if ($lastbottommargin && isset($properties['MARGIN-TOP']) && $properties['MARGIN-TOP'] && empty($properties['FLOAT'])) { $currblk['lastbottommargin'] = $lastbottommargin; }
16867
16868 if (isset($properties['Z-INDEX']) && $this->current_layer==0) {
16869 $v = intval($properties['Z-INDEX']);
16870 if ($v > 0) {
16871 $currblk['z-index'] = $v;
16872 $this->BeginLayer($v);
16873 }
16874 }
16875
16876
16877 // mPDF 6 Lists
16878 // List-type set by attribute
16879 if ($tag == 'OL' || $tag == 'UL' || $tag == 'LI') {
16880 if (isset($attr['TYPE']) && $attr['TYPE']) {
16881 $listtype = $attr['TYPE'];
16882 switch($listtype) {
16883 case 'A':
16884 $listtype = 'upper-latin';
16885 break;
16886 case 'a':
16887 $listtype = 'lower-latin';
16888 break;
16889 case 'I':
16890 $listtype = 'upper-roman';
16891 break;
16892 case 'i':
16893 $listtype = 'lower-roman';
16894 break;
16895 case '1':
16896 $listtype = 'decimal';
16897 break;
16898 }
16899 $currblk['list_style_type'] = $listtype;
16900 }
16901 }
16902
16903 $this->setCSS($properties,'BLOCK',$tag); //name(id/class/style) found in the CSS array!
16904 $currblk['InlineProperties'] = $this->saveInlineProperties();
16905
16906 if (isset($properties['VISIBILITY'])) {
16907 $v = strtolower($properties['VISIBILITY']);
16908 if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible' && !$this->tableLevel) {
16909 $currblk['visibility'] = $v;
16910 $this->SetVisibility($v);
16911 }
16912 }
16913
16914 // mPDF 6
16915 if(isset($attr['ALIGN']) && $attr['ALIGN']) { $currblk['block-align'] = $align[strtolower($attr['ALIGN'])]; }
16916
16917
16918 if (isset($properties['HEIGHT'])) {
16919 $currblk['css_set_height'] = $this->ConvertSize($properties['HEIGHT'],($this->h - $this->tMargin - $this->bMargin),$this->FontSize,false);
16920 if (($currblk['css_set_height'] + $this->y) > $this->PageBreakTrigger && $this->y > $this->tMargin+5 && $currblk['css_set_height'] < ($this->h - ($this->tMargin + $this->bMargin))) { $this->AddPage($this->CurOrientation); }
16921 }
16922 else { $currblk['css_set_height'] = false; }
16923
16924
16925 // Added mPDF 3.0 Float DIV
16926 if (isset($prevblk['blockContext'])) { $currblk['blockContext'] = $prevblk['blockContext'] ; } // *CSS-FLOAT*
16927
16928 if (isset($properties['CLEAR'])) { $this->ClearFloats(strtoupper($properties['CLEAR']), $this->blklvl-1); } // *CSS-FLOAT*
16929
16930 $container_w = $prevblk['inner_width'];
16931 $bdr = $currblk['border_right']['w'];
16932 $bdl = $currblk['border_left']['w'];
16933 $pdr = $currblk['padding_right'];
16934 $pdl = $currblk['padding_left'];
16935
16936 if (isset($currblk['css_set_width'])) { $setwidth = $currblk['css_set_width']; }
16937 else { $setwidth = 0; }
16938
16939 /*-- CSS-FLOAT --*/
16940 if (isset($properties['FLOAT']) && strtoupper($properties['FLOAT']) == 'RIGHT' && !$this->ColActive) {
16941 // Cancel Keep-Block-together
16942 $currblk['keep_block_together'] = false;
16943 $this->kt_y00 = '';
16944 $this->keep_block_together = 0;
16945
16946 $this->blockContext++;
16947 $currblk['blockContext'] = $this->blockContext;
16948
16949 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
16950
16951 // DIV is too narrow for text to fit!
16952 $maxw = $container_w - $l_width - $r_width;
16953 if (($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) > $maxw || ($maxw - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) < (2*$this->GetCharWidth('W',false))) {
16954 // Too narrow to fit - try to move down past L or R float
16955 if ($l_max < $r_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width) && (($container_w - $r_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
16956 $this->ClearFloats('LEFT', $this->blklvl-1);
16957 }
16958 else if ($r_max < $l_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width) && (($container_w - $l_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
16959 $this->ClearFloats('RIGHT', $this->blklvl-1);
16960 }
16961 else { $this->ClearFloats('BOTH', $this->blklvl-1); }
16962 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
16963 }
16964
16965 if ($r_exists) { $currblk['margin_right'] += $r_width; }
16966
16967 $currblk['float'] = 'R';
16968 $currblk['float_start_y'] = $this->y;
16969 if ($currblk['css_set_width']) {
16970 $currblk['margin_left'] = $container_w - ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
16971 $currblk['float_width'] = ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
16972 }
16973 else {
16974 // *** If no width set - would need to buffer and keep track of max width, then Right-align if not full width
16975 // and do borders and backgrounds - For now - just set to maximum width left
16976
16977 if ($l_exists) { $currblk['margin_left'] += $l_width; }
16978 $currblk['css_set_width'] = $container_w - ($currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr);
16979
16980 $currblk['float_width'] = ($currblk['css_set_width'] + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
16981 }
16982 }
16983 else if (isset($properties['FLOAT']) && strtoupper($properties['FLOAT']) == 'LEFT' && !$this->ColActive) {
16984 // Cancel Keep-Block-together
16985 $currblk['keep_block_together'] = false;
16986 $this->kt_y00 = '';
16987 $this->keep_block_together = 0;
16988
16989 $this->blockContext++;
16990 $currblk['blockContext'] = $this->blockContext;
16991
16992 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
16993
16994 // DIV is too narrow for text to fit!
16995 $maxw = $container_w - $l_width - $r_width;
16996 if (($setwidth + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr) > $maxw || ($maxw - ($currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) < (2*$this->GetCharWidth('W',false))) {
16997 // Too narrow to fit - try to move down past L or R float
16998 if ($l_max < $r_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width) && (($container_w - $r_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
16999 $this->ClearFloats('LEFT', $this->blklvl-1);
17000 }
17001 else if ($r_max < $l_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width) && (($container_w - $l_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
17002 $this->ClearFloats('RIGHT', $this->blklvl-1);
17003 }
17004 else { $this->ClearFloats('BOTH', $this->blklvl-1); }
17005 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
17006 }
17007
17008 if ($l_exists) { $currblk['margin_left'] += $l_width; }
17009
17010 $currblk['float'] = 'L';
17011 $currblk['float_start_y'] = $this->y;
17012 if ($setwidth) {
17013 $currblk['margin_right'] = $container_w - ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
17014 $currblk['float_width'] = ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
17015 }
17016 else {
17017 // *** If no width set - would need to buffer and keep track of max width, then Right-align if not full width
17018 // and do borders and backgrounds - For now - just set to maximum width left
17019
17020 if ($r_exists) { $currblk['margin_right'] += $r_width; }
17021 $currblk['css_set_width'] = $container_w - ($currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr);
17022
17023 $currblk['float_width'] = ($currblk['css_set_width'] + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
17024 }
17025 }
17026
17027 else {
17028 // Don't allow overlap - if floats present - adjust padding to avoid overlap with Floats
17029 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
17030 $maxw = $container_w - $l_width - $r_width;
17031 if (($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) > $maxw || ($maxw - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) < (2*$this->GetCharWidth('W',false))) {
17032 // Too narrow to fit - try to move down past L or R float
17033 if ($l_max < $r_max && ($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width) && (($container_w - $r_width) - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
17034 $this->ClearFloats('LEFT', $this->blklvl-1);
17035 }
17036 else if ($r_max < $l_max && ($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width) && (($container_w - $l_width) - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) > (2*$this->GetCharWidth('W',false))) {
17037 $this->ClearFloats('RIGHT', $this->blklvl-1);
17038 }
17039 else { $this->ClearFloats('BOTH', $this->blklvl-1); }
17040 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
17041 }
17042 if ($r_exists) { $currblk['padding_right'] = max(($r_width-$currblk['margin_right']-$bdr), $pdr); }
17043 if ($l_exists) { $currblk['padding_left'] = max(($l_width-$currblk['margin_left']-$bdl), $pdl); }
17044 }
17045 /*-- END CSS-FLOAT --*/
17046
17047
17048 /*-- BORDER-RADIUS --*/
17049 // Automatically increase padding if required for border-radius
17050 if ($this->autoPadding && !$this->ColActive) {
17051 if ($currblk['border_radius_TL_H']>$currblk['padding_left'] && $currblk['border_radius_TL_V']>$currblk['padding_top']) {
17052 if ($currblk['border_radius_TL_H']>$currblk['border_radius_TL_V']) {
17053 $this->_borderPadding($currblk['border_radius_TL_H'],$currblk['border_radius_TL_V'], $currblk['padding_left'], $currblk['padding_top']);
17054 }
17055 else {
17056 $this->_borderPadding($currblk['border_radius_TL_V'],$currblk['border_radius_TL_H'], $currblk['padding_top'], $currblk['padding_left']);
17057 }
17058 }
17059 if ($currblk['border_radius_TR_H']>$currblk['padding_right'] && $currblk['border_radius_TR_V']>$currblk['padding_top']) {
17060 if ($currblk['border_radius_TR_H']>$currblk['border_radius_TR_V']) {
17061 $this->_borderPadding($currblk['border_radius_TR_H'],$currblk['border_radius_TR_V'], $currblk['padding_right'], $currblk['padding_top']);
17062 }
17063 else {
17064 $this->_borderPadding($currblk['border_radius_TR_V'],$currblk['border_radius_TR_H'], $currblk['padding_top'], $currblk['padding_right']);
17065 }
17066 }
17067 if ($currblk['border_radius_BL_H']>$currblk['padding_left'] && $currblk['border_radius_BL_V']>$currblk['padding_bottom']) {
17068 if ($currblk['border_radius_BL_H']>$currblk['border_radius_BL_V']) {
17069 $this->_borderPadding($currblk['border_radius_BL_H'],$currblk['border_radius_BL_V'], $currblk['padding_left'], $currblk['padding_bottom']);
17070 }
17071 else {
17072 $this->_borderPadding($currblk['border_radius_BL_V'],$currblk['border_radius_BL_H'], $currblk['padding_bottom'], $currblk['padding_left']);
17073 }
17074 }
17075 if ($currblk['border_radius_BR_H']>$currblk['padding_right'] && $currblk['border_radius_BR_V']>$currblk['padding_bottom']) {
17076 if ($currblk['border_radius_BR_H']>$currblk['border_radius_BR_V']) {
17077 $this->_borderPadding($currblk['border_radius_BR_H'],$currblk['border_radius_BR_V'], $currblk['padding_right'], $currblk['padding_bottom']);
17078 }
17079 else {
17080 $this->_borderPadding($currblk['border_radius_BR_V'],$currblk['border_radius_BR_H'], $currblk['padding_bottom'], $currblk['padding_right']);
17081 }
17082 }
17083 }
17084 /*-- END BORDER-RADIUS --*/
17085
17086
17087 // Hanging indent - if negative indent: ensure padding is >= indent
17088 if(!isset($currblk['text_indent'])) { $currblk['text_indent'] = null; }
17089 if(!isset($currblk['inner_width'])) { $currblk['inner_width'] = null; }
17090 $cbti = $this->ConvertSize($currblk['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17091 if ($cbti < 0) {
17092 $hangind = -($cbti);
17093 if (isset($currblk['direction']) && $currblk['direction'] == 'rtl') { // *OTL*
17094 $currblk['padding_right'] = max($currblk['padding_right'],$hangind); // *OTL*
17095 } // *OTL*
17096 else { // *OTL*
17097 $currblk['padding_left'] = max($currblk['padding_left'],$hangind);
17098 } // *OTL*
17099 }
17100
17101 if (isset($currblk['css_set_width'])) {
17102 if (isset($properties['MARGIN-LEFT']) && isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-LEFT'])=='auto' && strtolower($properties['MARGIN-RIGHT'])=='auto') {
17103 // Try to reduce margins to accomodate - if still too wide, set margin-right/left=0 (reduces width)
17104 $anyextra = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']);
17105 if ($anyextra>0) {
17106 $currblk['margin_left'] = $currblk['margin_right'] = $anyextra /2;
17107 }
17108 else {
17109 $currblk['margin_left'] = $currblk['margin_right'] = 0;
17110 }
17111 }
17112 else if (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
17113 // Try to reduce margin-left to accomodate - if still too wide, set margin-left=0 (reduces width)
17114 $currblk['margin_left'] = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right'] + $currblk['margin_right']);
17115 if ($currblk['margin_left'] < 0) {
17116 $currblk['margin_left'] = 0;
17117 }
17118 }
17119 else if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto') {
17120 // Try to reduce margin-right to accomodate - if still too wide, set margin-right=0 (reduces width)
17121 $currblk['margin_right'] = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right'] + $currblk['margin_left']);
17122 if ($currblk['margin_right'] < 0) {
17123 $currblk['margin_right'] = 0;
17124 }
17125 }
17126 else {
17127 if ($currblk['direction'] == 'rtl') { // *OTL*
17128 // Try to reduce margin-left to accomodate - if still too wide, set margin-left=0 (reduces width)
17129 $currblk['margin_left'] = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right'] + $currblk['margin_right']); // *OTL*
17130 if ($currblk['margin_left'] < 0) { // *OTL*
17131 $currblk['margin_left'] = 0; // *OTL*
17132 } // *OTL*
17133 } // *OTL*
17134 else { // *OTL*
17135 // Try to reduce margin-right to accomodate - if still too wide, set margin-right=0 (reduces width)
17136 $currblk['margin_right'] = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right'] + $currblk['margin_left']);
17137 if ($currblk['margin_right'] < 0) {
17138 $currblk['margin_right'] = 0;
17139 }
17140 } // *OTL*
17141 }
17142 }
17143
17144 $currblk['outer_left_margin'] = $prevblk['outer_left_margin'] + $currblk['margin_left'] + $prevblk['border_left']['w'] + $prevblk['padding_left'];
17145 $currblk['outer_right_margin'] = $prevblk['outer_right_margin'] + $currblk['margin_right'] + $prevblk['border_right']['w'] + $prevblk['padding_right'];
17146
17147 $currblk['width'] = $this->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin']);
17148 $currblk['inner_width'] = $currblk['width'] - ($currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']);
17149
17150 // Check DIV is not now too narrow to fit text
17151 $mw = 2*$this->GetCharWidth('W',false);
17152 if ($currblk['inner_width'] < $mw) {
17153 $currblk['padding_left'] = 0;
17154 $currblk['padding_right'] = 0;
17155 $currblk['border_left']['w'] = 0.2;
17156 $currblk['border_right']['w'] = 0.2;
17157 $currblk['margin_left'] = 0;
17158 $currblk['margin_right'] = 0;
17159 $currblk['outer_left_margin'] = $prevblk['outer_left_margin'] + $currblk['margin_left'] + $prevblk['border_left']['w'] + $prevblk['padding_left'];
17160 $currblk['outer_right_margin'] = $prevblk['outer_right_margin'] + $currblk['margin_right'] + $prevblk['border_right']['w'] + $prevblk['padding_right'];
17161 $currblk['width'] = $this->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin']);
17162 $currblk['inner_width'] = $this->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']);
17163 // if ($currblk['inner_width'] < $mw) { $this->Error("DIV is too narrow for text to fit!"); }
17164 }
17165
17166 $this->x = $this->lMargin + $currblk['outer_left_margin'];
17167
17168 /*-- BACKGROUNDS --*/
17169 if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->kwt && !$this->ColActive && !$this->keep_block_together) {
17170 $ret = $this->SetBackground($properties, $currblk['inner_width']);
17171 if ($ret) { $currblk['background-image'] = $ret; }
17172 }
17173 /*-- END BACKGROUNDS --*/
17174
17175 /*-- TABLES --*/
17176 if ($this->use_kwt && isset($attr['KEEP-WITH-TABLE']) && !$this->ColActive && !$this->keep_block_together) {
17177 $this->kwt = true;
17178 $this->kwt_y0 = $this->y;
17179 //$this->kwt_x0 = $this->x;
17180 $this->kwt_x0 = $this->lMargin; // mPDF 6
17181 $this->kwt_height = 0;
17182 $this->kwt_buffer = array();
17183 $this->kwt_Links = array();
17184 $this->kwt_Annots = array();
17185 $this->kwt_moved = false;
17186 $this->kwt_saved = false;
17187 $this->kwt_Reference = array();
17188 $this->kwt_BMoutlines = array();
17189 $this->kwt_toc = array();
17190 }
17191 else {
17192 /*-- END TABLES --*/
17193 $this->kwt = false;
17194 } // *TABLES*
17195
17196 //Save x,y coords in case we need to print borders...
17197 $currblk['y0'] = $this->y;
17198 $currblk['initial_y0'] = $this->y; // mPDF 6
17199 $currblk['x0'] = $this->x;
17200 $currblk['initial_x0'] = $this->x; // mPDF 6
17201 $currblk['initial_startpage'] = $this->page;
17202 $currblk['startpage'] = $this->page; // mPDF 6
17203 $this->oldy = $this->y;
17204
17205 $this->lastblocklevelchange = 1 ;
17206
17207
17208 // mPDF 6 Lists
17209 if ($tag == 'OL' || $tag == 'UL') {
17210 $this->listlvl++;
17211 if (isset($attr['START']) && $attr['START']) { $this->listcounter[$this->listlvl] = intval($attr['START'])-1; }
17212 else { $this->listcounter[$this->listlvl] = 0; }
17213 $this->listitem = array();
17214
17215 // List-type
17216 if (!isset($currblk['list_style_type']) || !$currblk['list_style_type']) {
17217 if ($tag == 'OL') $currblk['list_style_type'] = 'decimal';
17218 else if ($tag == 'UL') {
17219 if ($this->listlvl % 3 == 1) $currblk['list_style_type'] = 'disc';
17220 elseif ($this->listlvl % 3 == 2) $currblk['list_style_type'] = 'circle';
17221 else $currblk['list_style_type'] = 'square';
17222 }
17223 }
17224
17225 // List-image
17226 if (!isset($currblk['list_style_image']) || !$currblk['list_style_image']) { $currblk['list_style_image'] = 'none'; }
17227
17228 // List-position
17229 if (!isset($currblk['list_style_position']) || !$currblk['list_style_position']) { $currblk['list_style_position'] = 'outside'; }
17230
17231 // Default indentation using padding
17232 if (strtolower($this->list_auto_mode) == 'mpdf' && isset($currblk['list_style_position']) && $currblk['list_style_position'] == 'outside' && isset($currblk['list_style_image']) && $currblk['list_style_image'] == 'none' && (!isset($currblk['list_style_type']) ||!preg_match('/U\+([a-fA-F0-9]+)/i',$currblk['list_style_type'])) ) {
17233 $autopadding = $this->_getListMarkerWidth($currblk,$ahtml,$ihtml);
17234 if ($this->listlvl > 1 || $this->list_indent_first_level) { $autopadding += $this->ConvertSize($this->list_indent_default_mpdf,$currblk['inner_width'],$this->FontSize,false); }
17235 // autopadding value is applied to left or right according
17236 // to dir of block. Once a CSS value is set for padding it overrides this default value.
17237 if (isset($properties['PADDING-RIGHT']) && $properties['PADDING-RIGHT']=='auto' && isset($currblk['direction']) && $currblk['direction'] == 'rtl') { $currblk['padding_right'] = $autopadding; }
17238 else if (isset($properties['PADDING-LEFT']) && $properties['PADDING-LEFT']=='auto') { $currblk['padding_left'] = $autopadding; }
17239 }
17240 else {
17241 // Initial default value is set by $this->list_indent_default in config.php; this value is applied to left or right according
17242 // to dir of block. Once a CSS value is set for padding it overrides this default value.
17243 if (isset($properties['PADDING-RIGHT']) && $properties['PADDING-RIGHT']=='auto' && isset($currblk['direction']) && $currblk['direction'] == 'rtl') { $currblk['padding_right'] = $this->ConvertSize($this->list_indent_default,$currblk['inner_width'],$this->FontSize,false); }
17244 else if (isset($properties['PADDING-LEFT']) && $properties['PADDING-LEFT']=='auto') { $currblk['padding_left'] = $this->ConvertSize($this->list_indent_default,$currblk['inner_width'],$this->FontSize,false); }
17245 }
17246 }
17247
17248
17249 // mPDF 6 Lists
17250 if ($tag == 'LI') {
17251 if ($this->listlvl == 0) { //in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...)
17252 $this->listlvl++; // first depth level
17253 $this->listcounter[$this->listlvl] = 0;
17254 }
17255 $this->listcounter[$this->listlvl]++;
17256 $this->listitem = array();
17257
17258 // Listitem-type
17259 $this->_setListMarker($currblk['list_style_type'], $currblk['list_style_image'], $currblk['list_style_position']);
17260 }
17261
17262 // mPDF 6 Bidirectional formatting for block elements
17263 $bdf = false;
17264 $bdf2 = '';
17265 $popd = '';
17266
17267 // Get current direction
17268 if (isset($currblk['direction'])) { $currdir = $currblk['direction']; }
17269 else { $currdir = 'ltr'; }
17270 if (isset($attr['DIR']) and $attr['DIR'] != '') { $currdir = strtolower($attr['DIR']); }
17271 if(isset($properties['DIRECTION'])) { $currdir = strtolower($properties['DIRECTION']); }
17272
17273 // mPDF 6 bidi
17274 // cf. http://www.w3.org/TR/css3-writing-modes/#unicode-bidi
17275 if(isset($properties ['UNICODE-BIDI']) && (strtolower($properties ['UNICODE-BIDI'])=='bidi-override' || strtolower($properties ['UNICODE-BIDI'])=='isolate-override')) {
17276 if ($currdir == 'rtl') { $bdf = 0x202E; $popd = 'RLOPDF';} // U+202E RLO
17277 else { $bdf = 0x202D; $popd = 'LROPDF'; } // U+202D LRO
17278 }
17279 else if(isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI'])=='plaintext') {
17280 $bdf = 0x2068; $popd = 'FSIPDI'; // U+2068 FSI
17281 }
17282 if ($bdf) {
17283 if ($bdf2) { $bdf2 = code2utf($bdf); }
17284 $this->OTLdata = array();
17285 if($this->tableLevel) { $this->_saveCellTextBuffer(code2utf($bdf).$bdf2); }
17286 else { $this->_saveTextBuffer(code2utf($bdf).$bdf2); }
17287 $this->biDirectional = true;
17288 $currblk['bidicode'] = $popd;
17289 }
17290
17291 break;
17292
17293 case 'HR':
17294 // Added mPDF 3.0 Float DIV - CLEAR
17295 if (isset($attr['STYLE'])) {
17296 $properties = $this->cssmgr->readInlineCSS($attr['STYLE']);
17297 if (isset($properties['CLEAR'])) { $this->ClearFloats(strtoupper($properties['CLEAR']),$this->blklvl); } // *CSS-FLOAT*
17298 }
17299
17300 $this->ignorefollowingspaces = true;
17301
17302 $objattr = array();
17303 $objattr['margin_top'] = 0;
17304 $objattr['margin_bottom'] = 0;
17305 $objattr['margin_left'] = 0;
17306 $objattr['margin_right'] = 0;
17307 $objattr['width'] = 0;
17308 $objattr['height'] = 0;
17309 $objattr['border_top']['w'] = 0;
17310 $objattr['border_bottom']['w'] = 0;
17311 $objattr['border_left']['w'] = 0;
17312 $objattr['border_right']['w'] = 0;
17313 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
17314 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top'] = $this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17315 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17316 if (isset($properties['WIDTH'])) { $objattr['width'] = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width']); }
17317 else if(isset($attr['WIDTH']) && $attr['WIDTH'] != '') $objattr['width'] = $this->ConvertSize($attr['WIDTH'],$this->blk[$this->blklvl]['inner_width']);
17318 if (isset($properties['TEXT-ALIGN'])) { $objattr['align'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
17319 else if(isset($attr['ALIGN']) && $attr['ALIGN'] != '') $objattr['align'] = $align[strtolower($attr['ALIGN'])];
17320
17321 if (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
17322 $objattr['align'] = 'R';
17323 }
17324 if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto') {
17325 $objattr['align'] = 'L';
17326 if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto' && isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
17327 $objattr['align'] = 'C';
17328 }
17329 }
17330 if (isset($properties['COLOR'])) { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
17331 else if(isset($attr['COLOR']) && $attr['COLOR'] != '') $objattr['color'] = $this->ConvertColor($attr['COLOR']);
17332 if (isset($properties['HEIGHT'])) { $objattr['linewidth'] = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17333
17334
17335 /*-- TABLES --*/
17336 if ($this->tableLevel) {
17337 $objattr['W-PERCENT'] = 100;
17338 if (isset($properties['WIDTH']) && stristr($properties['WIDTH'],'%')) {
17339 $properties['WIDTH'] += 0; //make "90%" become simply "90"
17340 $objattr['W-PERCENT'] = $properties['WIDTH'];
17341 }
17342 if (isset($attr['WIDTH']) && stristr($attr['WIDTH'],'%')) {
17343 $attr['WIDTH'] += 0; //make "90%" become simply "90"
17344 $objattr['W-PERCENT'] = $attr['WIDTH'];
17345 }
17346 }
17347 /*-- END TABLES --*/
17348
17349 $objattr['type'] = 'hr';
17350 $objattr['height'] = $objattr['linewidth'] + $objattr['margin_top'] + $objattr['margin_bottom'];
17351 $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
17352
17353 // Clear properties - tidy up
17354 $properties = array();
17355
17356 /*-- TABLES --*/
17357 // Output it to buffers
17358 if ($this->tableLevel) {
17359 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
17360 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
17361 }
17362 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
17363 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
17364 }
17365 $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
17366 $this->_saveCellTextBuffer($e, $this->HREF);
17367 }
17368 else {
17369 /*-- END TABLES --*/
17370 $this->_saveTextBuffer($e, $this->HREF);
17371 } // *TABLES*
17372
17373 break;
17374
17375
17376 /*-- BARCODES --*/
17377
17378 case 'BARCODE':
17379 $this->ignorefollowingspaces = false;
17380 if(isset($attr['CODE']) && $attr['CODE']) {
17381 $objattr = array();
17382 $objattr['margin_top'] = 0;
17383 $objattr['margin_bottom'] = 0;
17384 $objattr['margin_left'] = 0;
17385 $objattr['margin_right'] = 0;
17386 $objattr['padding_top'] = 0;
17387 $objattr['padding_bottom'] = 0;
17388 $objattr['padding_left'] = 0;
17389 $objattr['padding_right'] = 0;
17390 $objattr['width'] = 0;
17391 $objattr['height'] = 0;
17392 $objattr['border_top']['w'] = 0;
17393 $objattr['border_bottom']['w'] = 0;
17394 $objattr['border_left']['w'] = 0;
17395 $objattr['border_right']['w'] = 0;
17396 $objattr['code'] = $attr['CODE'];
17397
17398 if(isset($attr['TYPE'])) {
17399 $objattr['btype'] = trim(strtoupper($attr['TYPE']));
17400 }
17401 else { $objattr['btype'] = 'EAN13'; } // default
17402 if (preg_match('/^(EAN13|ISBN|ISSN|EAN8|UPCA|UPCE)P([25])$/',$objattr['btype'],$m)) {
17403 $objattr['btype'] = $m[1];
17404 $objattr['bsupp'] = $m[2];
17405 if (preg_match('/^(\S+)\s+(.*)$/',$objattr['code'],$mm)) {
17406 $objattr['code'] = $mm[1];
17407 $objattr['bsupp_code'] = $mm[2];
17408 }
17409 }
17410 else { $objattr['bsupp'] = 0; }
17411
17412 if(isset($attr['TEXT']) && $attr['TEXT']==1) { $objattr['showtext'] = 1; }
17413 else { $objattr['showtext'] = 0; }
17414 if(isset($attr['SIZE']) && $attr['SIZE']>0) { $objattr['bsize'] = $attr['SIZE']; }
17415 else { $objattr['bsize'] = 1; }
17416 if(isset($attr['HEIGHT']) && $attr['HEIGHT']>0) { $objattr['bheight'] = $attr['HEIGHT']; }
17417 else { $objattr['bheight'] = 1; }
17418 if(isset($attr['PR']) && $attr['PR']>0) { $objattr['pr_ratio'] = $attr['PR']; }
17419 else { $objattr['pr_ratio'] = ''; }
17420 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
17421 if(isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY'])=='none') {
17422 return;
17423 }
17424 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17425 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17426 if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17427 if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17428
17429 if (isset($properties['PADDING-TOP'])) { $objattr['padding_top']=$this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17430 if (isset($properties['PADDING-BOTTOM'])) { $objattr['padding_bottom'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17431 if (isset($properties['PADDING-LEFT'])) { $objattr['padding_left'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17432 if (isset($properties['PADDING-RIGHT'])) { $objattr['padding_right'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17433
17434 if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
17435 if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
17436 if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
17437 if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
17438
17439 if (isset($properties['VERTICAL-ALIGN'])) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
17440 if (isset($properties['COLOR']) && $properties['COLOR'] != '') { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
17441 else { $objattr['color'] = false; }
17442 if (isset($properties['BACKGROUND-COLOR']) && $properties['BACKGROUND-COLOR'] != '') { $objattr['bgcolor'] = $this->ConvertColor($properties['BACKGROUND-COLOR']); }
17443 else { $objattr['bgcolor'] = false; }
17444
17445 if (!class_exists('PDFBarcode', false)) {
17446 include(_MPDF_PATH.'classes/barcode.php');
17447 }
17448 $this->barcode = new PDFBarcode();
17449
17450 if ($objattr['btype'] == 'EAN13' || $objattr['btype'] == 'ISBN' || $objattr['btype'] == 'ISSN' || $objattr['btype'] == 'UPCA' || $objattr['btype'] == 'UPCE' || $objattr['btype'] == 'EAN8') {
17451 $code = preg_replace('/\-/','',$objattr['code']);
17452 if ($objattr['btype'] == 'ISSN' || $objattr['btype'] == 'ISBN') {
17453 $arrcode = $this->barcode->getBarcodeArray($code, 'EAN13');
17454 }
17455 else { $arrcode = $this->barcode->getBarcodeArray($code, $objattr['btype'] ); }
17456 if ($arrcode === false) { $this->Error('Error in barcode string.'); }
17457
17458 if ($objattr['bsupp'] == 2 || $objattr['bsupp'] == 5) { // EAN-2 or -5 Supplement
17459 $supparrcode = $this->barcode->getBarcodeArray($objattr['bsupp_code'], 'EAN'.$objattr['bsupp'] );
17460 $w = ($arrcode["maxw"] + $arrcode['lightmL'] + $arrcode['lightmR'] + $supparrcode["maxw"] + $supparrcode['sepM']) * $arrcode['nom-X'] * $objattr['bsize'];
17461 }
17462 else {
17463 $w = ($arrcode["maxw"] + $arrcode['lightmL'] + $arrcode['lightmR']) * $arrcode['nom-X'] * $objattr['bsize'];
17464 }
17465 $h = $arrcode['nom-H'] * $objattr['bsize'] * $objattr['bheight'];
17466 // Add height for ISBN string + margin from top of bars
17467 if (($objattr['showtext'] && $objattr['btype'] == 'EAN13') || $objattr['btype'] == 'ISBN' || $objattr['btype'] == 'ISSN') {
17468 $tisbnm = 1.5 * $objattr['bsize']; // Top margin between TOP TEXT (isbn - if shown) & bars
17469 $isbn_fontsize = 2.1 * $objattr['bsize'];
17470 $h += $isbn_fontsize + $tisbnm ;
17471 }
17472 }
17473 // QR-code
17474 else if ($objattr['btype'] == 'QR') {
17475 $w = $h = $objattr['bsize']*25; // Factor of 25mm (default)
17476 $objattr['errorlevel'] = 'L';
17477 if (isset($attr['ERROR'])) { $objattr['errorlevel'] = $attr['ERROR']; }
17478 }
17479 else if ($objattr['btype'] == 'IMB' || $objattr['btype'] == 'RM4SCC' || $objattr['btype'] == 'KIX' || $objattr['btype'] == 'POSTNET' || $objattr['btype'] == 'PLANET') {
17480 $arrcode = $this->barcode->getBarcodeArray($objattr['code'], $objattr['btype'] );
17481 if ($arrcode === false) { $this->Error('Error in barcode string.'); }
17482 $w = ($arrcode["maxw"] * $arrcode['nom-X'] * $objattr['bsize']) + $arrcode['quietL'] + $arrcode['quietR'];
17483 $h = ($arrcode['nom-H'] * $objattr['bsize']) + (2*$arrcode['quietTB']);
17484 }
17485 else if (in_array($objattr['btype'], array('C128A','C128B','C128C','EAN128A','EAN128B','EAN128C','C39','C39+','C39E','C39E+','S25','S25+','I25','I25+','I25B','I25B+','C93','MSI','MSI+','CODABAR','CODE11'))) {
17486 $arrcode = $this->barcode->getBarcodeArray($objattr['code'], $objattr['btype'], $objattr['pr_ratio'] );
17487 if ($arrcode === false) { $this->Error('Error in barcode string.'); }
17488 $w = ($arrcode["maxw"] + $arrcode['lightmL'] + $arrcode['lightmR']) * $arrcode['nom-X'] * $objattr['bsize'];
17489 $h = ((2*$arrcode['lightTB'] * $arrcode['nom-X']) + $arrcode['nom-H']) * $objattr['bsize'] * $objattr['bheight'];
17490 }
17491 else { break; }
17492
17493 $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
17494 $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
17495
17496 $objattr['type'] = 'barcode';
17497 $objattr['height'] = $h + $extraheight;
17498 $objattr['width'] = $w + $extrawidth;
17499 $objattr['barcode_height'] = $h;
17500 $objattr['barcode_width'] = $w;
17501 /*-- CSS-IMAGE-FLOAT --*/
17502 if (!$this->ColActive && !$this->tableLevel && !$this->listlvl && !$this->kwt) {
17503 if (isset($properties['FLOAT']) && (strtoupper($properties['FLOAT']) == 'RIGHT' || strtoupper($properties['FLOAT']) == 'LEFT')) {
17504 $objattr['float'] = substr(strtoupper($properties['FLOAT']),0,1);
17505 }
17506 }
17507 /*-- END CSS-IMAGE-FLOAT --*/
17508
17509 $e = "\xbb\xa4\xactype=barcode,objattr=".serialize($objattr)."\xbb\xa4\xac";
17510
17511 // Clear properties - tidy up
17512 $properties = array();
17513
17514 /*-- TABLES --*/
17515 // Output it to buffers
17516 if ($this->tableLevel) {
17517 $this->_saveCellTextBuffer($e, $this->HREF);
17518 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
17519 }
17520 else {
17521 /*-- END TABLES --*/
17522 $this->_saveTextBuffer($e, $this->HREF);
17523
17524 } // *TABLES*
17525 }
17526 break;
17527 /*-- END BARCODES --*/
17528
17529
17530 // *********** FORM ELEMENTS ********************
17531
17532 /*-- FORMS --*/
17533 case 'SELECT':
17534 $this->lastoptionaltag = ''; // Save current HTML specified optional endtag
17535 $this->InlineProperties[$tag] = $this->saveInlineProperties();
17536 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
17537 if (isset($properties['FONT-FAMILY'])) {
17538 $this->SetFont($properties['FONT-FAMILY'],$this->FontStyle,0,false);
17539 }
17540 if (isset($properties['FONT-SIZE'])) {
17541 $mmsize = $this->ConvertSize($properties['FONT-SIZE'],$this->default_font_size/_MPDFK);
17542 $this->SetFontSize($mmsize*_MPDFK,false);
17543 }
17544 if (isset($attr['SPELLCHECK']) && strtolower($attr['SPELLCHECK'])=='true') {
17545 $this->selectoption['SPELLCHECK'] = true;
17546 }
17547
17548 if (isset($properties['COLOR'])) { $this->selectoption['COLOR'] = $this->ConvertColor($properties['COLOR']); }
17549 $this->specialcontent = "type=select";
17550 if(isset($attr['DISABLED'])) { $this->selectoption['DISABLED'] = $attr['DISABLED']; }
17551 if(isset($attr['READONLY'])) { $this->selectoption['READONLY'] = $attr['READONLY']; }
17552 if(isset($attr['REQUIRED'])) { $this->selectoption['REQUIRED'] = $attr['REQUIRED']; }
17553 if(isset($attr['EDITABLE'])) { $this->selectoption['EDITABLE'] = $attr['EDITABLE']; }
17554 if(isset($attr['TITLE'])) { $this->selectoption['TITLE'] = $attr['TITLE']; }
17555 if(isset($attr['MULTIPLE'])) { $this->selectoption['MULTIPLE'] = $attr['MULTIPLE']; }
17556 if(isset($attr['SIZE']) && $attr['SIZE']>1) { $this->selectoption['SIZE'] = $attr['SIZE']; }
17557 if ($this->useActiveForms) {
17558 if(isset($attr['NAME'])) { $this->selectoption['NAME'] = $attr['NAME']; }
17559 if (isset($attr['ONCHANGE'])) { $this->selectoption['ONCHANGE'] = $attr['ONCHANGE']; }
17560 }
17561
17562 $properties = array();
17563 break;
17564
17565 case 'OPTION':
17566 $this->lastoptionaltag = '';
17567 $this->selectoption['ACTIVE'] = true;
17568 $this->selectoption['currentSEL'] = false;
17569 if (empty($this->selectoption)) {
17570 $this->selectoption['MAXWIDTH'] = '';
17571 $this->selectoption['SELECTED'] = '';
17572 }
17573 if (isset($attr['SELECTED'])) {
17574 $this->selectoption['SELECTED'] = '';
17575 $this->selectoption['currentSEL'] = true;
17576 }
17577 if(isset($attr['VALUE'])) {
17578 $attr['VALUE'] = strcode2utf($attr['VALUE']);
17579 $attr['VALUE'] = $this->lesser_entity_decode($attr['VALUE']);
17580 if ($this->onlyCoreFonts)
17581 $attr['VALUE'] = mb_convert_encoding($attr['VALUE'], $this->mb_enc,'UTF-8');
17582 }
17583 $this->selectoption['currentVAL'] = $attr['VALUE'];
17584 break;
17585
17586 case 'TEXTAREA':
17587 $objattr = array();
17588 $objattr['margin_top'] = 0;
17589 $objattr['margin_bottom'] = 0;
17590 $objattr['margin_left'] = 0;
17591 $objattr['margin_right'] = 0;
17592 $objattr['width'] = 0;
17593 $objattr['height'] = 0;
17594 $objattr['border_top']['w'] = 0;
17595 $objattr['border_bottom']['w'] = 0;
17596 $objattr['border_left']['w'] = 0;
17597 $objattr['border_right']['w'] = 0;
17598 if(isset($attr['DISABLED'])) { $objattr['disabled'] = true; }
17599 if(isset($attr['READONLY'])) { $objattr['readonly'] = true; }
17600 if(isset($attr['REQUIRED'])) { $objattr['required'] = true; }
17601 if(isset($attr['SPELLCHECK']) && strtolower($attr['SPELLCHECK'])=='true') { $objattr['spellcheck'] = true; }
17602 if(isset($attr['TITLE'])) {
17603 $objattr['title'] = $attr['TITLE'];
17604 if ($this->onlyCoreFonts)
17605 $objattr['title'] = mb_convert_encoding($objattr['title'], $this->mb_enc,'UTF-8');
17606 }
17607 if ($this->useActiveForms) {
17608 if(isset($attr['NAME'])) { $objattr['fieldname'] = $attr['NAME']; }
17609 $this->mpdfform->form_element_spacing['textarea']['outer']['v'] = 0;
17610 $this->mpdfform->form_element_spacing['textarea']['inner']['v'] = 0;
17611 if (isset($attr['ONCALCULATE'])) { $objattr['onCalculate'] = $attr['ONCALCULATE']; }
17612 else if (isset($attr['ONCHANGE'])) { $objattr['onCalculate'] = $attr['ONCHANGE']; }
17613 if (isset($attr['ONVALIDATE'])) { $objattr['onValidate'] = $attr['ONVALIDATE']; }
17614 if (isset($attr['ONKEYSTROKE'])) { $objattr['onKeystroke'] = $attr['ONKEYSTROKE']; }
17615 if (isset($attr['ONFORMAT'])) { $objattr['onFormat'] = $attr['ONFORMAT']; }
17616 }
17617 $this->InlineProperties[$tag] = $this->saveInlineProperties();
17618 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
17619 if (isset($properties['FONT-FAMILY'])) {
17620 $this->SetFont($properties['FONT-FAMILY'],'',0,false);
17621 }
17622 if (isset($properties['FONT-SIZE'])) {
17623 $mmsize = $this->ConvertSize($properties['FONT-SIZE'],$this->default_font_size/_MPDFK);
17624 $this->SetFontSize($mmsize*_MPDFK,false);
17625 }
17626 if (isset($properties['COLOR'])) { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
17627 $objattr['fontfamily'] = $this->FontFamily;
17628 $objattr['fontsize'] = $this->FontSizePt;
17629 if ($this->useActiveForms) {
17630 if(isset($properties['TEXT-ALIGN'])) { $objattr['text_align'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
17631 else if(isset($attr['ALIGN'])) { $objattr['text_align'] = $align[strtolower($attr['ALIGN'])]; }
17632 if (isset($properties['OVERFLOW']) && strtolower($properties['OVERFLOW'])=='hidden') { $objattr['donotscroll'] = true; }
17633 if (isset($properties['BORDER-TOP-COLOR'])) { $objattr['border-col'] = $this->ConvertColor($properties['BORDER-TOP-COLOR']); }
17634 if (isset($properties['BACKGROUND-COLOR'])) { $objattr['background-col'] = $this->ConvertColor($properties['BACKGROUND-COLOR']); }
17635 }
17636 $this->SetLineHeight('',$this->mpdfform->textarea_lineheight);
17637
17638 $w = 0;
17639 $h = 0;
17640 if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17641 if(isset($properties['HEIGHT'])) $h = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17642 if (isset($properties['VERTICAL-ALIGN'])) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
17643
17644 $colsize = 20; //HTML default value
17645 $rowsize = 2; //HTML default value
17646 if (isset($attr['COLS'])) $colsize = intval($attr['COLS']);
17647 if (isset($attr['ROWS'])) $rowsize = intval($attr['ROWS']);
17648
17649 $charsize = $this->GetCharWidth('w',false);
17650 if ($w) { $colsize = round(($w-($this->mpdfform->form_element_spacing['textarea']['outer']['h']*2)-($this->mpdfform->form_element_spacing['textarea']['inner']['h']*2))/$charsize); }
17651 if ($h) { $rowsize = round(($h-($this->mpdfform->form_element_spacing['textarea']['outer']['v']*2)-($this->mpdfform->form_element_spacing['textarea']['inner']['v']*2))/$this->lineheight); }
17652
17653 $objattr['type'] = 'textarea';
17654 $objattr['width'] = ($colsize * $charsize) + ($this->mpdfform->form_element_spacing['textarea']['outer']['h']*2)+($this->mpdfform->form_element_spacing['textarea']['inner']['h']*2);
17655 $objattr['height'] = ($rowsize * $this->lineheight) + ($this->mpdfform->form_element_spacing['textarea']['outer']['v']*2)+($this->mpdfform->form_element_spacing['textarea']['inner']['v']*2);
17656 $objattr['rows'] = $rowsize;
17657 $objattr['cols'] = $colsize;
17658
17659 $this->specialcontent = serialize($objattr);
17660
17661 if ($this->tableLevel) { // *TABLES*
17662 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ; // *TABLES*
17663 } // *TABLES*
17664
17665 // Clear properties - tidy up
17666 $properties = array();
17667 break;
17668
17669
17670
17671 // *********** FORM - INPUT ********************
17672
17673 case 'INPUT':
17674 $this->ignorefollowingspaces = false;
17675 if (!isset($attr['TYPE'])) $attr['TYPE'] == 'TEXT';
17676 $objattr = array();
17677 $objattr['margin_top'] = 0;
17678 $objattr['margin_bottom'] = 0;
17679 $objattr['margin_left'] = 0;
17680 $objattr['margin_right'] = 0;
17681 $objattr['width'] = 0;
17682 $objattr['height'] = 0;
17683 $objattr['border_top']['w'] = 0;
17684 $objattr['border_bottom']['w'] = 0;
17685 $objattr['border_left']['w'] = 0;
17686 $objattr['border_right']['w'] = 0;
17687 $objattr['type'] = 'input';
17688 if(isset($attr['DISABLED'])) { $objattr['disabled'] = true; }
17689 if(isset($attr['READONLY'])) { $objattr['readonly'] = true; }
17690 if(isset($attr['REQUIRED'])) { $objattr['required'] = true; }
17691 if(isset($attr['SPELLCHECK']) && strtolower($attr['SPELLCHECK'])=='true') { $objattr['spellcheck'] = true; }
17692 if(isset($attr['TITLE'])) { $objattr['title'] = $attr['TITLE']; }
17693 else if(isset($attr['ALT'])) { $objattr['title'] = $attr['ALT']; }
17694 else $objattr['title'] = '';
17695 $objattr['title'] = strcode2utf($objattr['title']);
17696 $objattr['title'] = $this->lesser_entity_decode($objattr['title']);
17697 if ($this->onlyCoreFonts)
17698 $objattr['title'] = mb_convert_encoding($objattr['title'], $this->mb_enc,'UTF-8');
17699 if ($this->useActiveForms) {
17700 if(isset($attr['NAME'])) { $objattr['fieldname'] = $attr['NAME']; }
17701 }
17702 if(isset($attr['VALUE'])) {
17703 $attr['VALUE'] = strcode2utf($attr['VALUE']);
17704 $attr['VALUE'] = $this->lesser_entity_decode($attr['VALUE']);
17705 if ($this->onlyCoreFonts)
17706 $attr['VALUE'] = mb_convert_encoding($attr['VALUE'], $this->mb_enc,'UTF-8');
17707 $objattr['value'] = $attr['VALUE'];
17708 }
17709
17710 $this->InlineProperties[$tag] = $this->saveInlineProperties();
17711 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
17712 $objattr['vertical-align'] = '';
17713
17714 if (isset($properties['FONT-FAMILY'])) {
17715 $this->SetFont($properties['FONT-FAMILY'],$this->FontStyle,0,false);
17716 }
17717 if (isset($properties['FONT-SIZE'])) {
17718 $mmsize = $this->ConvertSize($properties['FONT-SIZE'],($this->default_font_size/_MPDFK));
17719 $this->SetFontSize($mmsize*_MPDFK,false);
17720 }
17721 if (isset($properties['COLOR'])) { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
17722 $objattr['fontfamily'] = $this->FontFamily;
17723 $objattr['fontsize'] = $this->FontSizePt;
17724 if ($this->useActiveForms) {
17725 if(isset($attr['ALIGN'])) { $objattr['text_align'] = $align[strtolower($attr['ALIGN'])]; }
17726 else if(isset($properties['TEXT-ALIGN'])) { $objattr['text_align'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
17727 if (isset($properties['BORDER-TOP-COLOR'])) { $objattr['border-col'] = $this->ConvertColor($properties['BORDER-TOP-COLOR']); }
17728 if (isset($properties['BACKGROUND-COLOR'])) { $objattr['background-col'] = $this->ConvertColor($properties['BACKGROUND-COLOR']); }
17729 }
17730
17731 $type = '';
17732 $texto='';
17733 $height = $this->FontSize;
17734 $width = 0;
17735 $spacesize = $this->GetCharWidth(' ',false);
17736
17737 $w = 0;
17738 if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width']);
17739
17740 if ($properties['VERTICAL-ALIGN']) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
17741
17742 switch(strtoupper($attr['TYPE'])){
17743 case 'HIDDEN':
17744 $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
17745 if ($this->useActiveForms) {
17746 $this->mpdfform->SetFormText( 0, 0, $objattr['fieldname'], $objattr['value'], $objattr['value'], '', 0, '', true );
17747 }
17748 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
17749 unset($this->InlineProperties[$tag]);
17750 break 2;
17751 case 'CHECKBOX': //Draw Checkbox
17752 $type = 'CHECKBOX';
17753 if (isset($attr['CHECKED'])) { $objattr['checked'] = true; }
17754 else { $objattr['checked'] = false; }
17755 $width = $this->FontSize;
17756 $height = $this->FontSize;
17757 break;
17758
17759 case 'RADIO': //Draw Radio button
17760 $type = 'RADIO';
17761 if (isset($attr['CHECKED'])) $objattr['checked'] = true;
17762 $width = $this->FontSize;
17763 $height = $this->FontSize;
17764 break;
17765
17766 /*-- IMAGES-CORE --*/
17767 case 'IMAGE': // Draw an Image button
17768 if(isset($attr['SRC'])) {
17769 $type = 'IMAGE';
17770 $srcpath = $attr['SRC'];
17771 $orig_srcpath = $attr['ORIG_SRC'];
17772 // VSPACE and HSPACE converted to margins in MergeCSS
17773 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17774 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17775 if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17776 if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17777
17778
17779 if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
17780 if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
17781 if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
17782 if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
17783
17784 $objattr['padding_top'] = 0;
17785 $objattr['padding_bottom'] = 0;
17786 $objattr['padding_left'] = 0;
17787 $objattr['padding_right'] = 0;
17788
17789 if (isset($properties['VERTICAL-ALIGN'])) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
17790
17791 $w = 0;
17792 $h = 0;
17793 if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width']);
17794 if(isset($properties['HEIGHT'])) $h = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width']);
17795
17796 $extraheight = $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
17797 $extrawidth = $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
17798
17799 // Image file
17800 $info=$this->_getImage($srcpath, true, true, $orig_srcpath);
17801 if(!$info) {
17802 $info = $this->_getImage($this->noImageFile);
17803 if ($info) {
17804 $srcpath = $this->noImageFile;
17805 $w = ($info['w'] * (25.4/$this->dpi));
17806 $h = ($info['h'] * (25.4/$this->dpi));
17807 }
17808 }
17809 if(!$info) break;
17810 if ($info['cs']=='Indexed') { $objattr['Indexed'] = true; }
17811 $objattr['file'] = $srcpath;
17812 //Default width and height calculation if needed
17813 if($w==0 and $h==0) {
17814 /*-- IMAGES-WMF --*/
17815 if ($info['type']=='wmf') {
17816 // WMF units are twips (1/20pt)
17817 // divide by 20 to get points
17818 // divide by k to get user units
17819 $w = abs($info['w'])/(20*_MPDFK);
17820 $h = abs($info['h']) / (20*_MPDFK);
17821 }
17822 else
17823 /*-- END IMAGES-WMF --*/
17824 if ($info['type']=='svg') {
17825 // SVG units are pixels
17826 $w = abs($info['w'])/_MPDFK;
17827 $h = abs($info['h'])/_MPDFK;
17828 }
17829 else {
17830 //Put image at default image dpi
17831 $w=($info['w']/_MPDFK) * (72/$this->img_dpi);
17832 $h=($info['h']/_MPDFK) * (72/$this->img_dpi);
17833 }
17834 if (isset($properties['IMAGE-RESOLUTION'])) {
17835 if (preg_match('/from-image/i', $properties['IMAGE-RESOLUTION']) && isset($info['set-dpi']) && $info['set-dpi']>0) {
17836 $w *= $this->img_dpi / $info['set-dpi'];
17837 $h *= $this->img_dpi / $info['set-dpi'];
17838 }
17839 else if (preg_match('/(\d+)dpi/i', $properties['IMAGE-RESOLUTION'], $m)) {
17840 $dpi = $m[1];
17841 if ($dpi > 0) {
17842 $w *= $this->img_dpi / $dpi;
17843 $h *= $this->img_dpi / $dpi;
17844 }
17845 }
17846 }
17847 }
17848 // IF WIDTH OR HEIGHT SPECIFIED
17849 if($w==0) $w=$h*$info['w']/$info['h'];
17850 if($h==0) $h=$w*$info['h']/$info['w'];
17851 // Resize to maximum dimensions of page
17852 $maxWidth = $this->blk[$this->blklvl]['inner_width'];
17853 $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 10) ;
17854 if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
17855 if (($w + $extrawidth) > ($maxWidth + 0.0001) ) { // mPDF 5.7.4 0.0001 to allow for rounding errors when w==maxWidth
17856 $w = $maxWidth - $extrawidth;
17857 $h=$w*$info['h']/$info['w'];
17858 }
17859 if ($h + $extraheight > $maxHeight ) {
17860 $h = $maxHeight - $extraheight;
17861 $w=$h*$info['w']/$info['h'];
17862 }
17863 $height = $h + $extraheight;
17864 $width = $w + $extrawidth;
17865 $objattr['type'] = 'image';
17866 $objattr['itype'] = $info['type'];
17867 $objattr['orig_h'] = $info['h'];
17868 $objattr['orig_w'] = $info['w'];
17869 /*-- IMAGES-WMF --*/
17870 if ($info['type']=='wmf') {
17871 $objattr['wmf_x'] = $info['x'];
17872 $objattr['wmf_y'] = $info['y'];
17873 }
17874 else
17875 /*-- END IMAGES-WMF --*/
17876 if ($info['type']=='svg') {
17877 $objattr['wmf_x'] = $info['x'];
17878 $objattr['wmf_y'] = $info['y'];
17879 }
17880 $objattr['height'] = $h + $extraheight;
17881 $objattr['width'] = $w + $extrawidth;
17882
17883 $objattr['image_height'] = $h;
17884 $objattr['image_width'] = $w;
17885 $objattr['ID'] = $info['i'];
17886 $texto = 'X';
17887 if ($this->useActiveForms) {
17888 if (isset($attr['ONCLICK'])) { $objattr['onClick'] = $attr['ONCLICK']; }
17889 $objattr['type'] = 'input';
17890 $type = 'IMAGE';
17891 }
17892 break;
17893 }
17894 /*-- END IMAGES-CORE --*/
17895
17896 case 'BUTTON': // Draw a button
17897 case 'SUBMIT':
17898 case 'RESET':
17899 $type = strtoupper($attr['TYPE']);
17900 if ($type=='IMAGE') { $type = 'BUTTON'; } // src path not found
17901 if(isset($attr['NOPRINT'])) { $objattr['noprint'] = true; }
17902 if (!isset($attr['VALUE'])) {
17903 $objattr['value'] = ucfirst(strtolower($type));
17904 }
17905
17906 $texto = " " . $objattr['value'] . " ";
17907 $width = $this->GetStringWidth($texto) + ($this->mpdfform->form_element_spacing['button']['outer']['h']*2)+($this->mpdfform->form_element_spacing['button']['inner']['h']*2);
17908 $height = $this->FontSize + ($this->mpdfform->form_element_spacing['button']['outer']['v']*2)+($this->mpdfform->form_element_spacing['button']['inner']['v']*2);
17909 if ($this->useActiveForms) {
17910 if (isset($attr['ONCLICK'])) { $objattr['onClick'] = $attr['ONCLICK']; }
17911 }
17912 break;
17913
17914 case 'PASSWORD':
17915 case 'TEXT':
17916 default:
17917 if ($type == '') { $type = 'TEXT'; }
17918 if(strtoupper($attr['TYPE'])=='PASSWORD') { $type = 'PASSWORD'; }
17919 if (isset($attr['VALUE'])) {
17920 if ($type == 'PASSWORD') {
17921 $num_stars = mb_strlen($attr['VALUE'],$this->mb_enc );
17922 $texto = str_repeat('*',$num_stars);
17923 }
17924 else { $texto = $attr['VALUE']; }
17925 }
17926 $xw = ($this->mpdfform->form_element_spacing['input']['outer']['h']*2)+($this->mpdfform->form_element_spacing['input']['inner']['h']*2);
17927 $xh = ($this->mpdfform->form_element_spacing['input']['outer']['v']*2)+($this->mpdfform->form_element_spacing['input']['inner']['v']*2);
17928 if ($w) { $width = $w + $xw; }
17929 else { $width = (20 * $spacesize) + $xw; } // Default width in chars
17930 if (isset($attr['SIZE']) and ctype_digit($attr['SIZE']) ) $width = ($attr['SIZE'] * $spacesize) + $xw;
17931 $height = $this->FontSize + $xh;
17932 if (isset($attr['MAXLENGTH']) and ctype_digit($attr['MAXLENGTH']) ) $objattr['maxlength'] = $attr['MAXLENGTH'];
17933 if ($this->useActiveForms) {
17934 if (isset($attr['ONCALCULATE'])) { $objattr['onCalculate'] = $attr['ONCALCULATE']; }
17935 else if (isset($attr['ONCHANGE'])) { $objattr['onCalculate'] = $attr['ONCHANGE']; }
17936 if (isset($attr['ONVALIDATE'])) { $objattr['onValidate'] = $attr['ONVALIDATE']; }
17937 if (isset($attr['ONKEYSTROKE'])) { $objattr['onKeystroke'] = $attr['ONKEYSTROKE']; }
17938 if (isset($attr['ONFORMAT'])) { $objattr['onFormat'] = $attr['ONFORMAT']; }
17939 }
17940 break;
17941 }
17942
17943 $objattr['subtype'] = $type;
17944 $objattr['text'] = $texto;
17945 $objattr['width'] = $width;
17946 $objattr['height'] = $height;
17947 $e = "\xbb\xa4\xactype=input,objattr=".serialize($objattr)."\xbb\xa4\xac";
17948
17949 // Clear properties - tidy up
17950 $properties = array();
17951
17952 /*-- TABLES --*/
17953 // Output it to buffers
17954 if ($this->tableLevel) {
17955 $this->_saveCellTextBuffer($e, $this->HREF);
17956 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
17957
17958 }
17959 else {
17960 /*-- END TABLES --*/
17961 $this->_saveTextBuffer($e, $this->HREF);
17962 } // *TABLES*
17963
17964 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
17965 unset($this->InlineProperties[$tag]);
17966
17967 break; // END of INPUT
17968 /*-- END FORMS --*/
17969
17970
17971 // *********** GRAPH ********************
17972 case 'JPGRAPH':
17973 if (!$this->useGraphs) { break; }
17974 if ($attr['TABLE']) { $gid = strtoupper($attr['TABLE']); }
17975 else { $gid = '0'; }
17976 if (!is_array($this->graphs[$gid]) || count($this->graphs[$gid])==0 ) { break; }
17977 $this->ignorefollowingspaces = false;
17978 include_once(_MPDF_PATH.'graph.php');
17979 $this->graphs[$gid]['attr'] = $attr;
17980
17981
17982 if (isset($this->graphs[$gid]['attr']['WIDTH']) && $this->graphs[$gid]['attr']['WIDTH']) {
17983 $this->graphs[$gid]['attr']['cWIDTH']=$this->ConvertSize($this->graphs[$gid]['attr']['WIDTH'],$this->blk[$this->blklvl]['inner_width']);
17984 } // mm
17985 if (isset($this->graphs[$gid]['attr']['HEIGHT']) && $this->graphs[$gid]['attr']['HEIGHT']) {
17986 $this->graphs[$gid]['attr']['cHEIGHT']=$this->ConvertSize($this->graphs[$gid]['attr']['HEIGHT'],$this->blk[$this->blklvl]['inner_width']);
17987 }
17988
17989 $graph_img = print_graph($this->graphs[$gid],$this->blk[$this->blklvl]['inner_width']);
17990 if ($graph_img) {
17991 if(isset($attr['ROTATE'])) {
17992 if ($attr['ROTATE']==90 || $attr['ROTATE']==-90) {
17993 $tmpw = $graph_img['w'];
17994 $graph_img['w']= $graph_img['h'];
17995 $graph_img['h']= $tmpw;
17996 }
17997 }
17998 $attr['SRC'] = $graph_img['file'];
17999 $attr['WIDTH'] = $graph_img['w'];
18000 $attr['HEIGHT'] = $graph_img['h'];
18001 }
18002 else { break; }
18003
18004 // *********** IMAGE ********************
18005 /*-- IMAGES-CORE --*/
18006 case 'IMG':
18007 $this->ignorefollowingspaces = false;
18008 if ($this->progressBar) { $this->UpdateProgressBar(1,'','IMG'); } // *PROGRESS-BAR*
18009 $objattr = array();
18010 $objattr['margin_top'] = 0;
18011 $objattr['margin_bottom'] = 0;
18012 $objattr['margin_left'] = 0;
18013 $objattr['margin_right'] = 0;
18014 $objattr['padding_top'] = 0;
18015 $objattr['padding_bottom'] = 0;
18016 $objattr['padding_left'] = 0;
18017 $objattr['padding_right'] = 0;
18018 $objattr['width'] = 0;
18019 $objattr['height'] = 0;
18020 $objattr['border_top']['w'] = 0;
18021 $objattr['border_bottom']['w'] = 0;
18022 $objattr['border_left']['w'] = 0;
18023 $objattr['border_right']['w'] = 0;
18024 if(isset($attr['SRC'])) {
18025 $srcpath = $attr['SRC'];
18026 $orig_srcpath = (isset($attr['ORIG_SRC']) ? $attr['ORIG_SRC'] : '');
18027 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
18028 if(isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY'])=='none') {
18029 return;
18030 }
18031 if (isset($properties['Z-INDEX']) && $this->current_layer==0) {
18032 $v = intval($properties['Z-INDEX']);
18033 if ($v > 0) {
18034 $objattr['z-index'] = $v;
18035 }
18036 }
18037
18038 $objattr['visibility'] = 'visible';
18039 if (isset($properties['VISIBILITY'])) {
18040 $v = strtolower($properties['VISIBILITY']);
18041 if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible') {
18042 $objattr['visibility'] = $v;
18043 }
18044 }
18045
18046 // VSPACE and HSPACE converted to margins in MergeCSS
18047 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18048 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18049 if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18050 if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18051
18052 if (isset($properties['PADDING-TOP'])) { $objattr['padding_top']=$this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18053 if (isset($properties['PADDING-BOTTOM'])) { $objattr['padding_bottom'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18054 if (isset($properties['PADDING-LEFT'])) { $objattr['padding_left'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18055 if (isset($properties['PADDING-RIGHT'])) { $objattr['padding_right'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18056
18057 if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
18058 if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
18059 if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
18060 if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
18061
18062 if (isset($properties['VERTICAL-ALIGN'])) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
18063 $w = 0;
18064 $h = 0;
18065 if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18066 else if(isset($attr['WIDTH'])) $w = $this->ConvertSize($attr['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18067 if(isset($properties['HEIGHT'])) $h = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18068 else if(isset($attr['HEIGHT'])) $h = $this->ConvertSize($attr['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18069 $maxw=$maxh=$minw=$minh=false;
18070 if(isset($properties['MAX-WIDTH'])) $maxw = $this->ConvertSize($properties['MAX-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18071 else if(isset($attr['MAX-WIDTH'])) $maxw = $this->ConvertSize($attr['MAX-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18072 if(isset($properties['MAX-HEIGHT'])) $maxh = $this->ConvertSize($properties['MAX-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18073 else if(isset($attr['MAX-HEIGHT'])) $maxh = $this->ConvertSize($attr['MAX-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18074 if(isset($properties['MIN-WIDTH'])) $minw = $this->ConvertSize($properties['MIN-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18075 else if(isset($attr['MIN-WIDTH'])) $minw = $this->ConvertSize($attr['MIN-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18076 if(isset($properties['MIN-HEIGHT'])) $minh = $this->ConvertSize($properties['MIN-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18077 else if(isset($attr['MIN-HEIGHT'])) $minh = $this->ConvertSize($attr['MIN-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18078
18079 if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { $objattr['opacity'] = $properties['OPACITY']; }
18080 if ($this->HREF) {
18081 if (strpos($this->HREF,".") === false && strpos($this->HREF,"@") !== 0) {
18082 $href = $this->HREF;
18083 while(array_key_exists($href,$this->internallink)) $href="#".$href;
18084 $this->internallink[$href] = $this->AddLink();
18085 $objattr['link'] = $this->internallink[$href];
18086 }
18087 else { $objattr['link'] = $this->HREF; }
18088 }
18089 $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
18090 $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
18091
18092 // mPDF 5.7.3 TRANSFORMS
18093 if (isset($properties['BACKGROUND-COLOR']) && $properties['BACKGROUND-COLOR'] != '') { $objattr['bgcolor'] = $this->ConvertColor($properties['BACKGROUND-COLOR']); }
18094
18095 /*-- BACKGROUNDS --*/
18096 if(isset($properties['GRADIENT-MASK']) && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/',$properties['GRADIENT-MASK'])) {
18097 $objattr['GRADIENT-MASK'] = $properties['GRADIENT-MASK'];
18098 }
18099 /*-- END BACKGROUNDS --*/
18100
18101 // mPDF 6
18102 $interpolation = false;
18103 if (isset($properties['IMAGE-RENDERING']) && $properties['IMAGE-RENDERING']) {
18104 if (strtolower($properties['IMAGE-RENDERING']) == 'crisp-edges') { $interpolation = false; }
18105 else if (strtolower($properties['IMAGE-RENDERING']) == 'optimizequality') { $interpolation = true; }
18106 else if (strtolower($properties['IMAGE-RENDERING']) == 'smooth') { $interpolation = true; }
18107 else if (strtolower($properties['IMAGE-RENDERING']) == 'auto') { $interpolation = $this->interpolateImages; }
18108 else { $interpolation = false; }
18109 $info['interpolation'] = $interpolation;
18110 }
18111
18112 // Image file
18113 $info=$this->_getImage($srcpath, true, true, $orig_srcpath, $interpolation); // mPDF 6
18114 if(!$info) {
18115 $info = $this->_getImage($this->noImageFile);
18116 if ($info) {
18117 $srcpath = $this->noImageFile;
18118 $w = ($info['w'] * (25.4/$this->dpi));
18119 $h = ($info['h'] * (25.4/$this->dpi));
18120 }
18121 }
18122 if(!$info) break;
18123
18124 if(isset($attr['ROTATE'])) { $image_orientation = $attr['ROTATE']; }
18125 else if(isset($properties['IMAGE-ORIENTATION'])) { $image_orientation = $properties['IMAGE-ORIENTATION']; }
18126 else { $image_orientation = 0; }
18127 if($image_orientation) {
18128 if ($image_orientation==90 || $image_orientation==-90 || $image_orientation==270) {
18129 $tmpw = $info['w'];
18130 $info['w'] = $info['h'];
18131 $info['h'] = $tmpw;
18132 }
18133 $objattr['ROTATE'] = $image_orientation;
18134 }
18135
18136 $objattr['file'] = $srcpath;
18137 //Default width and height calculation if needed
18138 if($w==0 and $h==0) {
18139 /*-- IMAGES-WMF --*/
18140 if ($info['type']=='wmf') {
18141 // WMF units are twips (1/20pt)
18142 // divide by 20 to get points
18143 // divide by k to get user units
18144 $w = abs($info['w'])/(20*_MPDFK);
18145 $h = abs($info['h']) / (20*_MPDFK);
18146 }
18147 else
18148 /*-- END IMAGES-WMF --*/
18149 if ($info['type']=='svg') {
18150 // SVG units are pixels
18151 $w = abs($info['w'])/_MPDFK;
18152 $h = abs($info['h'])/_MPDFK;
18153 }
18154 else {
18155 //Put image at default image dpi
18156 $w=($info['w']/_MPDFK) * (72/$this->img_dpi);
18157 $h=($info['h']/_MPDFK) * (72/$this->img_dpi);
18158 }
18159 if (isset($properties['IMAGE-RESOLUTION'])) {
18160 if (preg_match('/from-image/i', $properties['IMAGE-RESOLUTION']) && isset($info['set-dpi']) && $info['set-dpi']>0) {
18161 $w *= $this->img_dpi / $info['set-dpi'];
18162 $h *= $this->img_dpi / $info['set-dpi'];
18163 }
18164 else if (preg_match('/(\d+)dpi/i', $properties['IMAGE-RESOLUTION'], $m)) {
18165 $dpi = $m[1];
18166 if ($dpi > 0) {
18167 $w *= $this->img_dpi / $dpi;
18168 $h *= $this->img_dpi / $dpi;
18169 }
18170 }
18171 }
18172 }
18173 // IF WIDTH OR HEIGHT SPECIFIED
18174 if($w==0) $w=abs($h*$info['w']/$info['h']);
18175 if($h==0) $h=abs($w*$info['h']/$info['w']);
18176
18177 if ($minw && $w<$minw) { $w = $minw; $h=abs($w*$info['h']/$info['w']); }
18178 if ($maxw && $w>$maxw) { $w = $maxw; $h=abs($w*$info['h']/$info['w']); }
18179 if ($minh && $h<$minh) { $h = $minh; $w=abs($h*$info['w']/$info['h']); }
18180 if ($maxh && $h>$maxh) { $h = $maxh; $w=abs($h*$info['w']/$info['h']); }
18181
18182 // Resize to maximum dimensions of page
18183 $maxWidth = $this->blk[$this->blklvl]['inner_width'];
18184 $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 1) ;
18185 if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
18186 if (($w + $extrawidth) > ($maxWidth + 0.0001) ) { // mPDF 5.7.4 0.0001 to allow for rounding errors when w==maxWidth
18187 $w = $maxWidth - $extrawidth;
18188 $h=abs($w*$info['h']/$info['w']);
18189 }
18190
18191 if ($h + $extraheight > $maxHeight ) {
18192 $h = $maxHeight - $extraheight;
18193 $w=abs($h*$info['w']/$info['h']);
18194 }
18195 $objattr['type'] = 'image';
18196 $objattr['itype'] = $info['type'];
18197
18198 $objattr['orig_h'] = $info['h'];
18199 $objattr['orig_w'] = $info['w'];
18200 /*-- IMAGES-WMF --*/
18201 if ($info['type']=='wmf') {
18202 $objattr['wmf_x'] = $info['x'];
18203 $objattr['wmf_y'] = $info['y'];
18204 }
18205 else
18206 /*-- END IMAGES-WMF --*/
18207 if ($info['type']=='svg') {
18208 $objattr['wmf_x'] = $info['x'];
18209 $objattr['wmf_y'] = $info['y'];
18210 }
18211 $objattr['height'] = $h + $extraheight;
18212 $objattr['width'] = $w + $extrawidth;
18213 $objattr['image_height'] = $h;
18214 $objattr['image_width'] = $w;
18215 /*-- CSS-IMAGE-FLOAT --*/
18216 if (!$this->ColActive && !$this->tableLevel && !$this->listlvl && !$this->kwt) {
18217 if (isset($properties['FLOAT']) && (strtoupper($properties['FLOAT']) == 'RIGHT' || strtoupper($properties['FLOAT']) == 'LEFT')) {
18218 $objattr['float'] = substr(strtoupper($properties['FLOAT']),0,1);
18219 }
18220 }
18221 /*-- END CSS-IMAGE-FLOAT --*/
18222 // mPDF 5.7.3 TRANSFORMS
18223 if (isset($properties['TRANSFORM']) && !$this->ColActive && !$this->kwt) {
18224 $objattr['transform'] = $properties['TRANSFORM'];
18225 }
18226
18227 $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
18228
18229 // Clear properties - tidy up
18230 $properties = array();
18231
18232 /*-- TABLES --*/
18233 // Output it to buffers
18234 if ($this->tableLevel) {
18235 $this->_saveCellTextBuffer($e, $this->HREF);
18236 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
18237 }
18238 else {
18239 /*-- END TABLES --*/
18240 $this->_saveTextBuffer($e, $this->HREF);
18241 } // *TABLES*
18242 /*-- ANNOTATIONS --*/
18243 if ($this->title2annots && isset($attr['TITLE'])) {
18244 $objattr = array();
18245 $objattr['margin_top'] = 0;
18246 $objattr['margin_bottom'] = 0;
18247 $objattr['margin_left'] = 0;
18248 $objattr['margin_right'] = 0;
18249 $objattr['width'] = 0;
18250 $objattr['height'] = 0;
18251 $objattr['border_top']['w'] = 0;
18252 $objattr['border_bottom']['w'] = 0;
18253 $objattr['border_left']['w'] = 0;
18254 $objattr['border_right']['w'] = 0;
18255 $objattr['CONTENT'] = $attr['TITLE'];
18256 $objattr['type'] = 'annot';
18257 $objattr['POS-X'] = 0;
18258 $objattr['POS-Y'] = 0;
18259 $objattr['ICON'] = 'Comment';
18260 $objattr['AUTHOR'] = '';
18261 $objattr['SUBJECT'] = '';
18262 $objattr['OPACITY'] = $this->annotOpacity;
18263 $objattr['COLOR'] = $this->ConvertColor('yellow');
18264 $e = "\xbb\xa4\xactype=annot,objattr=".serialize($objattr)."\xbb\xa4\xac";
18265 if($this->tableLevel) { // *TABLES*
18266 $this->cell[$this->row][$this->col]['textbuffer'][] = array($e); // *TABLES*
18267 } // *TABLES*
18268 else { // *TABLES*
18269 $this->textbuffer[] = array($e);
18270 } // *TABLES*
18271 }
18272 /*-- END ANNOTATIONS --*/
18273 }
18274 break;
18275 /*-- END IMAGES-CORE --*/
18276
18277
18278 // *********** CIRCULAR TEXT = TEXTCIRCLE ********************
18279 case 'TEXTCIRCLE':
18280 $objattr = array();
18281 $objattr['margin_top'] = 0;
18282 $objattr['margin_bottom'] = 0;
18283 $objattr['margin_left'] = 0;
18284 $objattr['margin_right'] = 0;
18285 $objattr['padding_top'] = 0;
18286 $objattr['padding_bottom'] = 0;
18287 $objattr['padding_left'] = 0;
18288 $objattr['padding_right'] = 0;
18289 $objattr['width'] = 0;
18290 $objattr['height'] = 0;
18291 $objattr['border_top']['w'] = 0;
18292 $objattr['border_bottom']['w'] = 0;
18293 $objattr['border_left']['w'] = 0;
18294 $objattr['border_right']['w'] = 0;
18295 $objattr['top-text'] = '';
18296 $objattr['bottom-text'] = '';
18297 $objattr['r'] = 20; // radius (default value here for safety)
18298 $objattr['space-width'] = 120;
18299 $objattr['char-width'] = 100;
18300
18301 $this->InlineProperties[$tag] = $this->saveInlineProperties();
18302 $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr);
18303
18304 if(isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY'])=='none') {
18305 return;
18306 }
18307 if (isset($attr['R'])) { $objattr['r']=$this->ConvertSize($attr['R'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18308 if(isset($attr['TOP-TEXT'])) {
18309 $objattr['top-text'] = strcode2utf($attr['TOP-TEXT']);
18310 $objattr['top-text'] = $this->lesser_entity_decode($objattr['top-text']);
18311 if ($this->onlyCoreFonts)
18312 $objattr['top-text'] = mb_convert_encoding($objattr['top-text'], $this->mb_enc,'UTF-8');
18313 }
18314 if(isset($attr['BOTTOM-TEXT'])) {
18315 $objattr['bottom-text'] = strcode2utf($attr['BOTTOM-TEXT']);
18316 $objattr['bottom-text'] = $this->lesser_entity_decode($objattr['bottom-text']);
18317 if ($this->onlyCoreFonts)
18318 $objattr['bottom-text'] = mb_convert_encoding($objattr['bottom-text'], $this->mb_enc,'UTF-8');
18319 }
18320 if(isset($attr['SPACE-WIDTH']) && $attr['SPACE-WIDTH']) { $objattr['space-width'] = $attr['SPACE-WIDTH']; }
18321 if(isset($attr['CHAR-WIDTH']) && $attr['CHAR-WIDTH']) { $objattr['char-width'] = $attr['CHAR-WIDTH']; }
18322
18323 // VISIBILITY
18324 $objattr['visibility'] = 'visible';
18325 if (isset($properties['VISIBILITY'])) {
18326 $v = strtolower($properties['VISIBILITY']);
18327 if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible') {
18328 $objattr['visibility'] = $v;
18329 }
18330 }
18331 if (isset($properties['FONT-SIZE'])) {
18332 if (strtolower($properties['FONT-SIZE'])=='auto') {
18333 if ($objattr['top-text'] && $objattr['bottom-text']) {
18334 $objattr['fontsize'] = -2;
18335 }
18336 else {
18337 $objattr['fontsize'] = -1;
18338 }
18339 }
18340 else {
18341 $mmsize = $this->ConvertSize($properties['FONT-SIZE'],($this->default_font_size/_MPDFK));
18342 $this->SetFontSize($mmsize*_MPDFK,false);
18343 $objattr['fontsize'] = $this->FontSizePt;
18344 }
18345 }
18346 if(isset($attr['DIVIDER'])) {
18347 $objattr['divider'] = strcode2utf($attr['DIVIDER']);
18348 $objattr['divider'] = $this->lesser_entity_decode($objattr['divider']);
18349 if ($this->onlyCoreFonts)
18350 $objattr['divider'] = mb_convert_encoding($objattr['divider'], $this->mb_enc,'UTF-8');
18351
18352 }
18353
18354 if (isset($properties['COLOR'])) { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
18355
18356 $objattr['fontstyle'] = '';
18357 if (isset($properties['FONT-WEIGHT'])) {
18358 if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $objattr['fontstyle'] .= 'B'; }
18359 }
18360 if (isset($properties['FONT-STYLE'])) {
18361 if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $objattr['fontstyle'] .= 'I'; }
18362 }
18363
18364 if (isset($properties['FONT-FAMILY'])) {
18365 $this->SetFont($properties['FONT-FAMILY'],$this->FontStyle,0,false);
18366 }
18367 $objattr['fontfamily'] = $this->FontFamily;
18368
18369 // VSPACE and HSPACE converted to margins in MergeCSS
18370 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18371 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18372 if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18373 if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18374
18375 if (isset($properties['PADDING-TOP'])) { $objattr['padding_top']=$this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18376 if (isset($properties['PADDING-BOTTOM'])) { $objattr['padding_bottom'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18377 if (isset($properties['PADDING-LEFT'])) { $objattr['padding_left'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18378 if (isset($properties['PADDING-RIGHT'])) { $objattr['padding_right'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18379
18380 if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
18381 if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
18382 if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
18383 if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
18384
18385 if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { $objattr['opacity'] = $properties['OPACITY']; }
18386 if (isset($properties['BACKGROUND-COLOR']) && $properties['BACKGROUND-COLOR'] != '') { $objattr['bgcolor'] = $this->ConvertColor($properties['BACKGROUND-COLOR']); }
18387 else { $objattr['bgcolor'] = false; }
18388 if ($this->HREF) {
18389 if (strpos($this->HREF,".") === false && strpos($this->HREF,"@") !== 0) {
18390 $href = $this->HREF;
18391 while(array_key_exists($href,$this->internallink)) $href="#".$href;
18392 $this->internallink[$href] = $this->AddLink();
18393 $objattr['link'] = $this->internallink[$href];
18394 }
18395 else { $objattr['link'] = $this->HREF; }
18396 }
18397 $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
18398 $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
18399
18400
18401 $w = $objattr['r']*2;
18402 $h = $w;
18403 $objattr['height'] = $h + $extraheight;
18404 $objattr['width'] = $w + $extrawidth;
18405 $objattr['type'] = 'textcircle';
18406
18407 $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
18408
18409 // Clear properties - tidy up
18410 $properties = array();
18411
18412 /*-- TABLES --*/
18413 // Output it to buffers
18414 if ($this->tableLevel) {
18415 $this->_saveCellTextBuffer($e, $this->HREF);
18416 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
18417 }
18418 else {
18419 /*-- END TABLES --*/
18420 $this->_saveTextBuffer($e, $this->HREF);
18421 } // *TABLES*
18422
18423 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
18424 unset($this->InlineProperties[$tag]);
18425
18426 break;
18427
18428
18429 /*-- TABLES --*/
18430
18431 case 'TABLE': // TABLE-BEGIN
18432 $this->tdbegin = false;
18433 $this->lastoptionaltag = '';
18434 // Disable vertical justification in columns
18435 if ($this->ColActive) { $this->colvAlign = ''; } // *COLUMNS*
18436 if ($this->lastblocklevelchange == 1) { $blockstate = 1; } // Top margins/padding only
18437 else if ($this->lastblocklevelchange < 1) { $blockstate = 0; } // NO margins/padding
18438 // called from block after new div e.g. <div> ... <table> ... Outputs block top margin/border and padding
18439 if (count($this->textbuffer) == 0 && $this->lastblocklevelchange == 1 && !$this->tableLevel && !$this->kwt) {
18440 $this->newFlowingBlock( $this->blk[$this->blklvl]['width'],$this->lineheight,'',false,1,true, $this->blk[$this->blklvl]['direction']);
18441 $this->finishFlowingBlock(true); // true = END of flowing block
18442 }
18443 else if (!$this->tableLevel && count($this->textbuffer)) { $this->printbuffer($this->textbuffer,$blockstate); }
18444
18445 $this->textbuffer=array();
18446 $this->lastblocklevelchange = -1;
18447
18448
18449
18450 if ($this->tableLevel) { // i.e. now a nested table coming...
18451 // Save current level table
18452 $this->cell['PARENTCELL'] = $this->saveInlineProperties();
18453 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['baseProperties']= $this->base_table_properties;
18454 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] = $this->cell;
18455 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currrow'] = $this->row;
18456 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currcol'] = $this->col;
18457 }
18458 $this->tableLevel++;
18459 $this->cssmgr->tbCSSlvl++;
18460
18461 if ($this->tableLevel>1) { // inherit table properties from cell in which nested
18462 //$this->base_table_properties['FONT-KERNING'] = ($this->textvar & FC_KERNING); // mPDF 6
18463 $this->base_table_properties['LETTER-SPACING'] = $this->lSpacingCSS ;
18464 $this->base_table_properties['WORD-SPACING'] = $this->wSpacingCSS ;
18465 // mPDF 6
18466 $direction = $this->cell[$this->row][$this->col]['direction'];
18467 $txta = $this->cell[$this->row][$this->col]['a'];
18468 $cellLineHeight = $this->cell[$this->row][$this->col]['cellLineHeight'];
18469 $cellLineStackingStrategy = $this->cell[$this->row][$this->col]['cellLineStackingStrategy'];
18470 $cellLineStackingShift = $this->cell[$this->row][$this->col]['cellLineStackingShift'];
18471 }
18472
18473 if (isset($this->tbctr[$this->tableLevel])) { $this->tbctr[$this->tableLevel]++; }
18474 else { $this->tbctr[$this->tableLevel] = 1; }
18475
18476 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['level'] = $this->tableLevel;
18477 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['levelid'] = $this->tbctr[$this->tableLevel];
18478
18479 if ($this->tableLevel > $this->innermostTableLevel) { $this->innermostTableLevel = $this->tableLevel; }
18480 if ($this->tableLevel > 1) {
18481 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nestedpos'] = array($this->row,$this->col,$this->tbctr[($this->tableLevel-1)]);
18482 }
18483 //++++++++++++++++++++++++++++
18484
18485 $this->cell = array();
18486 $this->col=-1; //int
18487 $this->row=-1; //int
18488 $table = &$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]];
18489
18490 // New table - any level
18491 $table['direction'] = $this->directionality;
18492 $table['bgcolor'] = false;
18493 $table['va'] = false;
18494 $table['txta'] = false;
18495 $table['topntail'] = false;
18496 $table['thead-underline'] = false;
18497 $table['border'] = false;
18498 $table['border_details']['R']['w'] = 0;
18499 $table['border_details']['L']['w'] = 0;
18500 $table['border_details']['T']['w'] = 0;
18501 $table['border_details']['B']['w'] = 0;
18502 $table['border_details']['R']['style'] = '';
18503 $table['border_details']['L']['style'] = '';
18504 $table['border_details']['T']['style'] = '';
18505 $table['border_details']['B']['style'] = '';
18506 $table['max_cell_border_width']['R'] = 0;
18507 $table['max_cell_border_width']['L'] = 0;
18508 $table['max_cell_border_width']['T'] = 0;
18509 $table['max_cell_border_width']['B'] = 0;
18510 $table['padding']['L'] = false;
18511 $table['padding']['R'] = false;
18512 $table['padding']['T'] = false;
18513 $table['padding']['B'] = false;
18514 $table['margin']['L'] = false;
18515 $table['margin']['R'] = false;
18516 $table['margin']['T'] = false;
18517 $table['margin']['B'] = false;
18518 $table['a'] = false;
18519 $table['border_spacing_H'] = false;
18520 $table['border_spacing_V'] = false;
18521 $table['decimal_align'] = false;
18522 $this->Reset();
18523 $this->InlineProperties = array();
18524 $this->InlineBDF=array(); // mPDF 6
18525 $this->InlineBDFctr= 0; // mPDF 6
18526 $table['nc'] = $table['nr'] = 0;
18527 $this->tablethead = 0;
18528 $this->tabletfoot = 0;
18529 $this->tabletheadjustfinished = false;
18530
18531 // mPDF 6
18532 if ($this->tableLevel>1) { // inherit table properties from cell in which nested
18533 $table['direction'] = $direction;
18534 $table['txta'] = $txta;
18535 $table['cellLineHeight'] = $cellLineHeight;
18536 $table['cellLineStackingStrategy'] = $cellLineStackingStrategy;
18537 $table['cellLineStackingShift'] = $cellLineStackingShift;
18538 }
18539
18540
18541 if ($this->blockjustfinished && !count($this->textbuffer) && $this->y != $this->tMargin && $this->collapseBlockMargins && $this->tableLevel==1) { $lastbottommargin = $this->lastblockbottommargin; }
18542 else { $lastbottommargin = 0; }
18543 $this->lastblockbottommargin = 0;
18544 $this->blockjustfinished=false;
18545
18546 if ($this->tableLevel==1) {
18547 $table['headernrows'] = 0;
18548 $table['footernrows'] = 0;
18549 $this->base_table_properties = array();
18550 }
18551
18552 // ADDED CSS FUNCIONS FOR TABLE
18553 if ($this->cssmgr->tbCSSlvl==1) {
18554 $properties = $this->cssmgr->MergeCSS('TOPTABLE',$tag,$attr);
18555 }
18556 else {
18557 $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
18558 }
18559
18560 $w = '';
18561 if (isset($properties['WIDTH'])) { $w = $properties['WIDTH']; }
18562 else if (isset($attr['WIDTH']) && $attr['WIDTH']) { $w = $attr['WIDTH']; }
18563
18564 if (isset($attr['ALIGN']) && isset($align[strtolower($attr['ALIGN'])])) { $table['a'] = $align[strtolower($attr['ALIGN'])]; }
18565 if (!$table['a']) {
18566 if ($table['direction'] == 'rtl' ) { $table['a'] = 'R'; }
18567 else { $table['a'] = 'L'; }
18568 }
18569
18570 if(isset($properties['DIRECTION']) && $properties['DIRECTION']) { $table['direction'] = strtolower($properties['DIRECTION']); }
18571 else if(isset($attr['DIR']) && $attr['DIR']) { $table['direction'] = strtolower($attr['DIR']); }
18572 else if ($this->tableLevel == 1) { $table['direction'] = $this->blk[$this->blklvl]['direction']; }
18573
18574 if (isset($properties['BACKGROUND-COLOR'])) { $table['bgcolor'][-1] = $properties['BACKGROUND-COLOR']; }
18575 else if (isset($properties['BACKGROUND'])) { $table['bgcolor'][-1] = $properties['BACKGROUND']; }
18576 else if (isset($attr['BGCOLOR'])) { $table['bgcolor'][-1] = $attr['BGCOLOR']; }
18577
18578 if (isset($properties['VERTICAL-ALIGN']) && isset($align[strtolower($properties['VERTICAL-ALIGN'])])) { $table['va'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
18579 if (isset($properties['TEXT-ALIGN']) && isset($align[strtolower($properties['TEXT-ALIGN'])])) { $table['txta'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
18580
18581 if (isset($properties['AUTOSIZE']) && $properties['AUTOSIZE'] && $this->tableLevel ==1) {
18582 $this->shrink_this_table_to_fit = $properties['AUTOSIZE'];
18583 if ($this->shrink_this_table_to_fit < 1) { $this->shrink_this_table_to_fit = 0; }
18584 }
18585 if (isset($properties['ROTATE']) && $properties['ROTATE'] && $this->tableLevel ==1) {
18586 $this->table_rotate = $properties['ROTATE'];
18587 }
18588 if (isset($properties['TOPNTAIL'])) { $table['topntail'] = $properties['TOPNTAIL']; }
18589 if (isset($properties['THEAD-UNDERLINE'])) { $table['thead-underline'] = $properties['THEAD-UNDERLINE']; }
18590
18591 if (isset($properties['BORDER'])) {
18592 $bord = $this->border_details($properties['BORDER']);
18593 if ($bord['s']) {
18594 $table['border'] = _BORDER_ALL;
18595 $table['border_details']['R'] = $bord;
18596 $table['border_details']['L'] = $bord;
18597 $table['border_details']['T'] = $bord;
18598 $table['border_details']['B'] = $bord;
18599 }
18600 }
18601 if (isset($properties['BORDER-RIGHT'])) {
18602 if ($table['direction'] == 'rtl') { // *OTL*
18603 $table['border_details']['R'] = $this->border_details($properties['BORDER-LEFT']); // *OTL*
18604 } // *OTL*
18605 else { // *OTL*
18606 $table['border_details']['R'] = $this->border_details($properties['BORDER-RIGHT']);
18607 } // *OTL*
18608 $this->setBorder($table['border'], _BORDER_RIGHT, $table['border_details']['R']['s']);
18609 }
18610 if (isset($properties['BORDER-LEFT'])) {
18611 if ($table['direction'] == 'rtl') { // *OTL*
18612 $table['border_details']['L'] = $this->border_details($properties['BORDER-RIGHT']); // *OTL*
18613 } // *OTL*
18614 else { // *OTL*
18615 $table['border_details']['L'] = $this->border_details($properties['BORDER-LEFT']);
18616 } // *OTL*
18617 $this->setBorder($table['border'], _BORDER_LEFT, $table['border_details']['L']['s']);
18618 }
18619 if (isset($properties['BORDER-BOTTOM'])) {
18620 $table['border_details']['B'] = $this->border_details($properties['BORDER-BOTTOM']);
18621 $this->setBorder($table['border'], _BORDER_BOTTOM, $table['border_details']['B']['s']);
18622 }
18623 if (isset($properties['BORDER-TOP'])) {
18624 $table['border_details']['T'] = $this->border_details($properties['BORDER-TOP']);
18625 $this->setBorder($table['border'], _BORDER_TOP, $table['border_details']['T']['s']);
18626 }
18627 if ($table['border']){
18628 $this->table_border_css_set = 1;
18629 }
18630 else {
18631 $this->table_border_css_set = 0;
18632 }
18633
18634 // mPDF 6
18635 if (isset($properties['LANG']) && $properties['LANG']) {
18636 if ($this->autoLangToFont && !$this->usingCoreFont) {
18637 if ($properties['LANG'] != $this->default_lang && $properties['LANG'] != 'UTF-8') {
18638 list ($coreSuitable,$mpdf_pdf_unifont) = GetLangOpts($properties['LANG'], $this->useAdobeCJK, $this->fontdata);
18639 if ($mpdf_pdf_unifont) { $properties['FONT-FAMILY'] = $mpdf_pdf_unifont; }
18640 }
18641 }
18642 $this->currentLang = $properties['LANG'];
18643 }
18644
18645
18646 if (isset($properties['FONT-FAMILY'])) {
18647 $this->default_font = $properties['FONT-FAMILY'];
18648 $this->SetFont($this->default_font,'',0,false);
18649 }
18650 $this->base_table_properties['FONT-FAMILY'] = $this->FontFamily;
18651
18652 if (isset($properties['FONT-SIZE'])) {
18653 if ($this->tableLevel>1) { $mmsize = $this->ConvertSize($properties['FONT-SIZE'], $this->base_table_properties['FONT-SIZE']); }
18654 else { $mmsize = $this->ConvertSize($properties['FONT-SIZE'],$this->default_font_size/_MPDFK); }
18655 if ($mmsize) {
18656 $this->default_font_size = $mmsize*(_MPDFK);
18657 $this->SetFontSize($this->default_font_size,false);
18658 }
18659 }
18660 $this->base_table_properties['FONT-SIZE'] = $this->FontSize.'mm';
18661
18662 if (isset($properties['FONT-WEIGHT'])) {
18663 if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $this->base_table_properties['FONT-WEIGHT'] = 'BOLD'; }
18664 }
18665 if (isset($properties['FONT-STYLE'])) {
18666 if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $this->base_table_properties['FONT-STYLE'] = 'ITALIC'; }
18667 }
18668 if (isset($properties['COLOR'])) {
18669 $this->base_table_properties['COLOR'] = $properties['COLOR'];
18670 }
18671 if (isset($properties['FONT-KERNING'])) {
18672 $this->base_table_properties['FONT-KERNING'] = $properties['FONT-KERNING'];
18673 }
18674 if (isset($properties['LETTER-SPACING'])) {
18675 $this->base_table_properties['LETTER-SPACING'] = $properties['LETTER-SPACING'];
18676 }
18677 if (isset($properties['WORD-SPACING'])) {
18678 $this->base_table_properties['WORD-SPACING'] = $properties['WORD-SPACING'];
18679 }
18680 // mPDF 6
18681 if (isset($properties['HYPHENS'])) {
18682 $this->base_table_properties['HYPHENS'] = $properties['HYPHENS'];
18683 }
18684 if(isset($properties['LINE-HEIGHT']) && $properties['LINE-HEIGHT']) { $table['cellLineHeight'] = $this->fixLineheight($properties['LINE-HEIGHT']); }
18685 else if ($this->tableLevel == 1) { $table['cellLineHeight'] = $this->blk[$this->blklvl]['line_height']; }
18686
18687 if(isset($properties['LINE-STACKING-STRATEGY']) && $properties['LINE-STACKING-STRATEGY']) { $table['cellLineStackingStrategy'] = strtolower($properties['LINE-STACKING-STRATEGY']); }
18688 else if ($this->tableLevel == 1 && isset($this->blk[$this->blklvl]['line_stacking_strategy'])) { $table['cellLineStackingStrategy'] = $this->blk[$this->blklvl]['line_stacking_strategy']; }
18689 else { $table['cellLineStackingStrategy'] = 'inline-line-height'; }
18690
18691 if(isset($properties['LINE-STACKING-SHIFT']) && $properties['LINE-STACKING-SHIFT']) { $table['cellLineStackingShift'] = strtolower($properties['LINE-STACKING-SHIFT']); }
18692 else if ($this->tableLevel == 1 && isset($this->blk[$this->blklvl]['line_stacking_shift'])) { $table['cellLineStackingShift'] = $this->blk[$this->blklvl]['line_stacking_shift']; }
18693 else { $table['cellLineStackingShift'] = 'consider-shifts'; }
18694
18695 if (isset($properties['PADDING-LEFT'])) {
18696 $table['padding']['L'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18697 }
18698 if (isset($properties['PADDING-RIGHT'])) {
18699 $table['padding']['R'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18700 }
18701 if (isset($properties['PADDING-TOP'])) {
18702 $table['padding']['T'] = $this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18703 }
18704 if (isset($properties['PADDING-BOTTOM'])) {
18705 $table['padding']['B'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18706 }
18707
18708 if (isset($properties['MARGIN-TOP'])) {
18709 if ($lastbottommargin) {
18710 $tmp = $this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18711 if ($tmp > $lastbottommargin) { $properties['MARGIN-TOP'] -= $lastbottommargin; }
18712 else { $properties['MARGIN-TOP'] = 0; }
18713 }
18714 $table['margin']['T'] = $this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18715 }
18716
18717 if (isset($properties['MARGIN-BOTTOM'])) {
18718 $table['margin']['B'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18719 }
18720 if (isset($properties['MARGIN-LEFT'])) {
18721 $table['margin']['L'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18722 }
18723
18724 if (isset($properties['MARGIN-RIGHT'])) {
18725 $table['margin']['R'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18726 }
18727 if (isset($properties['MARGIN-LEFT']) && isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-LEFT'])=='auto' && strtolower($properties['MARGIN-RIGHT'])=='auto') {
18728 $table['a'] = 'C';
18729 }
18730 else if (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
18731 $table['a'] = 'R';
18732 }
18733 else if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto') {
18734 $table['a'] = 'L';
18735 }
18736
18737 if (isset($properties['BORDER-COLLAPSE']) && strtoupper($properties['BORDER-COLLAPSE'])=='SEPARATE') {
18738 $table['borders_separate'] = true;
18739 }
18740 else {
18741 $table['borders_separate'] = false;
18742 }
18743
18744 // mPDF 5.7.3
18745
18746 if (isset($properties['BORDER-SPACING-H'])) {
18747 $table['border_spacing_H'] = $this->ConvertSize($properties['BORDER-SPACING-H'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18748 }
18749 if (isset($properties['BORDER-SPACING-V'])) {
18750 $table['border_spacing_V'] = $this->ConvertSize($properties['BORDER-SPACING-V'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18751 }
18752 // mPDF 5.7.3
18753 if (!$table['borders_separate']) { $table['border_spacing_H'] = $table['border_spacing_V'] = 0; }
18754
18755 if (isset($properties['EMPTY-CELLS'])) {
18756 $table['empty_cells'] = strtolower($properties['EMPTY-CELLS']); // 'hide' or 'show'
18757 }
18758 else { $table['empty_cells'] = ''; }
18759
18760 if (isset($properties['PAGE-BREAK-INSIDE']) && strtoupper($properties['PAGE-BREAK-INSIDE'])=='AVOID' && $this->tableLevel==1 && !$this->writingHTMLfooter) {
18761 $this->table_keep_together = true;
18762 }
18763 else if ($this->tableLevel==1) {
18764 $this->table_keep_together = false;
18765 }
18766 if (isset($properties['PAGE-BREAK-AFTER']) && $this->tableLevel==1) {
18767 $table['page_break_after'] = strtoupper($properties['PAGE-BREAK-AFTER']);
18768 }
18769
18770 /*-- BACKGROUNDS --*/
18771 if (isset($properties['BACKGROUND-GRADIENT']) && !$this->kwt && !$this->ColActive) { $table['gradient'] = $properties['BACKGROUND-GRADIENT']; }
18772
18773 if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->kwt && !$this->ColActive) {
18774 $ret = $this->SetBackground($properties, $currblk['inner_width']);
18775 if ($ret) { $table['background-image'] = $ret; }
18776 }
18777 /*-- END BACKGROUNDS --*/
18778
18779 if (isset($properties['OVERFLOW'])) {
18780 $table['overflow'] = strtolower($properties['OVERFLOW']); // 'hidden' 'wrap' or 'visible' or 'auto'
18781 if (($this->ColActive || $this->tableLevel>1) && $table['overflow']=='visible') { unset($table['overflow']); }
18782 }
18783
18784 $properties = array();
18785
18786
18787 if (isset($attr['CELLPADDING'])) {
18788 $table['cell_padding'] = $attr['CELLPADDING'];
18789 }
18790 else {
18791 $table['cell_padding'] = false;
18792 }
18793
18794 if (isset($attr['BORDER']) && $attr['BORDER']=='1') {
18795 $this->table_border_attr_set = 1;
18796 $bord = $this->border_details('#000000 1px solid');
18797 if ($bord['s']) {
18798 $table['border'] = _BORDER_ALL;
18799 $table['border_details']['R'] = $bord;
18800 $table['border_details']['L'] = $bord;
18801 $table['border_details']['T'] = $bord;
18802 $table['border_details']['B'] = $bord;
18803 }
18804 }
18805 else {
18806 $this->table_border_attr_set = 0;
18807 }
18808
18809 if ($w) {
18810 $maxwidth = $this->blk[$this->blklvl]['inner_width'];
18811 if ($table['borders_separate']) {
18812 $tblblw = $table['margin']['L'] + $table['margin']['R'] + $table['border_details']['L']['w']/2 + $table['border_details']['R']['w']/2;
18813 }
18814 else {
18815 $tblblw = $table['margin']['L'] + $table['margin']['R'] + $table['max_cell_border_width']['L']/2 + $table['max_cell_border_width']['R']/2;
18816 }
18817 if (strpos($w,'%') && $this->tableLevel == 1 && !$this->ignore_table_percents ) {
18818 // % needs to be of inner box without table margins etc.
18819 $maxwidth -= $tblblw ;
18820 $wmm = $this->ConvertSize($w,$maxwidth,$this->FontSize,false);
18821 $table['w'] = $wmm + $tblblw ;
18822 }
18823 if (strpos($w,'%') && $this->tableLevel > 1 && !$this->ignore_table_percents && $this->keep_table_proportions) {
18824 $table['wpercent'] = $w + 0; // makes 80% -> 80
18825 }
18826 if (!strpos($w,'%') && !$this->ignore_table_widths ) {
18827 $wmm = $this->ConvertSize($w,$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18828 $table['w'] = $wmm + $tblblw ;
18829 }
18830 if (!$this->keep_table_proportions) {
18831 if (isset($table['w']) && $table['w'] > $this->blk[$this->blklvl]['inner_width']) { $table['w'] = $this->blk[$this->blklvl]['inner_width']; }
18832 }
18833 }
18834
18835 if (isset($attr['AUTOSIZE']) && $this->tableLevel==1) {
18836 $this->shrink_this_table_to_fit = $attr['AUTOSIZE'];
18837 if ($this->shrink_this_table_to_fit < 1) { $this->shrink_this_table_to_fit = 1; }
18838 }
18839 if (isset($attr['ROTATE']) && $this->tableLevel==1) {
18840 $this->table_rotate = $attr['ROTATE'];
18841 }
18842
18843 //++++++++++++++++++++++++++++
18844 if ($this->table_rotate) {
18845 $this->tbrot_Links = array();
18846 $this->tbrot_Annots = array();
18847 $this->tbrotForms = array();
18848 $this->tbrot_BMoutlines = array();
18849 $this->tbrot_toc = array();
18850 }
18851
18852 if ($this->kwt) {
18853 if ($this->table_rotate) { $this->table_keep_together = true; }
18854 $this->kwt = false;
18855 $this->kwt_saved = true;
18856 }
18857
18858 if ($this->tableLevel==1 && $this->useGraphs) {
18859 if (isset($attr['ID']) && $attr['ID']) { $this->currentGraphId = strtoupper($attr['ID']); }
18860 else { $this->currentGraphId = '0'; }
18861 $this->graphs[$this->currentGraphId] = array();
18862 }
18863 //++++++++++++++++++++++++++++
18864 $this->plainCell_properties = array();
18865 unset($table);
18866 break;
18867
18868 case 'THEAD':
18869 $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
18870 $this->cssmgr->tbCSSlvl++;
18871 $this->tablethead = 1;
18872 $this->tabletfoot = 0;
18873 $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
18874 if (isset($properties['FONT-WEIGHT'])) {
18875 if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $this->thead_font_weight = 'B'; }
18876 else { $this->thead_font_weight = ''; }
18877 }
18878
18879 if (isset($properties['FONT-STYLE'])) {
18880 if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $this->thead_font_style = 'I'; }
18881 else { $this->thead_font_style = ''; }
18882 }
18883 if (isset($properties['FONT-VARIANT'])) {
18884 if (strtoupper($properties['FONT-VARIANT']) == 'SMALL-CAPS') { $this->thead_font_smCaps = 'S'; }
18885 else { $this->thead_font_smCaps = ''; }
18886 }
18887
18888 if (isset($properties['VERTICAL-ALIGN'])) {
18889 $this->thead_valign_default = $properties['VERTICAL-ALIGN'];
18890 }
18891 if (isset($properties['TEXT-ALIGN'])) {
18892 $this->thead_textalign_default = $properties['TEXT-ALIGN'];
18893 }
18894 $properties = array();
18895 break;
18896
18897 case 'TFOOT':
18898 $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
18899 $this->cssmgr->tbCSSlvl++;
18900 $this->tabletfoot = 1;
18901 $this->tablethead = 0;
18902 $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
18903 if (isset($properties['FONT-WEIGHT'])) {
18904 if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $this->tfoot_font_weight = 'B'; }
18905 else { $this->tfoot_font_weight = ''; }
18906 }
18907
18908 if (isset($properties['FONT-STYLE'])) {
18909 if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $this->tfoot_font_style = 'I'; }
18910 else { $this->tfoot_font_style = ''; }
18911 }
18912 if (isset($properties['FONT-VARIANT'])) {
18913 if (strtoupper($properties['FONT-VARIANT']) == 'SMALL-CAPS') { $this->tfoot_font_smCaps = 'S'; }
18914 else { $this->tfoot_font_smCaps = ''; }
18915 }
18916
18917 if (isset($properties['VERTICAL-ALIGN'])) {
18918 $this->tfoot_valign_default = $properties['VERTICAL-ALIGN'];
18919 }
18920 if (isset($properties['TEXT-ALIGN'])) {
18921 $this->tfoot_textalign_default = $properties['TEXT-ALIGN'];
18922 }
18923 $properties = array();
18924 break;
18925
18926
18927 case 'TBODY':
18928 $this->tablethead = 0;
18929 $this->tabletfoot = 0;
18930 $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
18931 $this->cssmgr->tbCSSlvl++;
18932 $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
18933 break;
18934
18935
18936 case 'TR':
18937 $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
18938 $this->cssmgr->tbCSSlvl++;
18939 $this->row++;
18940 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr']++;
18941 $this->col = -1;
18942 $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
18943
18944 if (!$this->simpleTables && (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['borders_separate']) || !$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['borders_separate'])) {
18945 if (isset($properties['BORDER-LEFT']) && $properties['BORDER-LEFT']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-left'][$this->row] = $properties['BORDER-LEFT']; }
18946 if (isset($properties['BORDER-RIGHT']) && $properties['BORDER-RIGHT']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-right'][$this->row] = $properties['BORDER-RIGHT']; }
18947 if (isset($properties['BORDER-TOP']) && $properties['BORDER-TOP']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-top'][$this->row] = $properties['BORDER-TOP']; }
18948 if (isset($properties['BORDER-BOTTOM']) && $properties['BORDER-BOTTOM']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-bottom'][$this->row] = $properties['BORDER-BOTTOM']; }
18949 }
18950
18951 if (isset($properties['BACKGROUND-COLOR'])) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$this->row] = $properties['BACKGROUND-COLOR']; }
18952 else if (isset($attr['BGCOLOR'])) $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$this->row] = $attr['BGCOLOR'];
18953
18954 /*-- BACKGROUNDS --*/
18955 if (isset($properties['BACKGROUND-GRADIENT']) && !$this->kwt && !$this->ColActive) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'][$this->row] = $properties['BACKGROUND-GRADIENT']; }
18956
18957 if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->kwt && !$this->ColActive) {
18958 $ret = $this->SetBackground($properties, $currblk['inner_width']);
18959 if ($ret) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'][$this->row] = $ret; }
18960 }
18961 /*-- END BACKGROUNDS --*/
18962
18963
18964
18965
18966 if (isset($properties['TEXT-ROTATE'])) {
18967 $this->trow_text_rotate = $properties['TEXT-ROTATE'];
18968 }
18969 if (isset($attr['TEXT-ROTATE'])) $this->trow_text_rotate = $attr['TEXT-ROTATE'];
18970
18971 if ($this->tablethead) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_thead'][$this->row] = true; }
18972 if ($this->tabletfoot) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'][$this->row] = true; }
18973 $properties = array();
18974 break;
18975
18976
18977 case 'TH':
18978 case 'TD':
18979 $this->ignorefollowingspaces = true;
18980 $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
18981 $this->cssmgr->tbCSSlvl++;
18982 $this->InlineProperties = array();
18983 $this->InlineBDF=array(); // mPDF 6
18984 $this->InlineBDFctr= 0; // mPDF 6
18985 $this->tdbegin = true;
18986 $this->col++;
18987 while (isset($this->cell[$this->row][$this->col])) { $this->col++; }
18988
18989 //Update number column
18990 if ($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'] < $this->col+1) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'] = $this->col+1; }
18991
18992 $table = &$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]];
18993
18994 $c = array('a' => false,
18995 'R' => false,
18996 'nowrap' => false,
18997 'bgcolor' => false,
18998 'padding' => array('L' => false,
18999 'R' => false,
19000 'T' => false,
19001 'B' => false
19002 )
19003 );
19004
19005 if ($this->simpleTables && $this->row==0 && $this->col==0){
19006 $table['simple']['border'] = false;
19007 $table['simple']['border_details']['R']['w'] = 0;
19008 $table['simple']['border_details']['L']['w'] = 0;
19009 $table['simple']['border_details']['T']['w'] = 0;
19010 $table['simple']['border_details']['B']['w'] = 0;
19011 $table['simple']['border_details']['R']['style'] = '';
19012 $table['simple']['border_details']['L']['style'] = '';
19013 $table['simple']['border_details']['T']['style'] = '';
19014 $table['simple']['border_details']['B']['style'] = '';
19015 }
19016 else if (!$this->simpleTables) {
19017 $c['border'] = false;
19018 $c['border_details']['R']['w'] = 0;
19019 $c['border_details']['L']['w'] = 0;
19020 $c['border_details']['T']['w'] = 0;
19021 $c['border_details']['B']['w'] = 0;
19022 $c['border_details']['mbw']['BL'] = 0;
19023 $c['border_details']['mbw']['BR'] = 0;
19024 $c['border_details']['mbw']['RT'] = 0;
19025 $c['border_details']['mbw']['RB'] = 0;
19026 $c['border_details']['mbw']['TL'] = 0;
19027 $c['border_details']['mbw']['TR'] = 0;
19028 $c['border_details']['mbw']['LT'] = 0;
19029 $c['border_details']['mbw']['LB'] = 0;
19030 $c['border_details']['R']['style'] = '';
19031 $c['border_details']['L']['style'] = '';
19032 $c['border_details']['T']['style'] = '';
19033 $c['border_details']['B']['style'] = '';
19034 $c['border_details']['R']['s'] = 0;
19035 $c['border_details']['L']['s'] = 0;
19036 $c['border_details']['T']['s'] = 0;
19037 $c['border_details']['B']['s'] = 0;
19038 $c['border_details']['R']['c'] = $this->ConvertColor(0);
19039 $c['border_details']['L']['c'] = $this->ConvertColor(0);
19040 $c['border_details']['T']['c'] = $this->ConvertColor(0);
19041 $c['border_details']['B']['c'] = $this->ConvertColor(0);
19042 $c['border_details']['R']['dom'] = 0;
19043 $c['border_details']['L']['dom'] = 0;
19044 $c['border_details']['T']['dom'] = 0;
19045 $c['border_details']['B']['dom'] = 0;
19046 $c['border_details']['cellposdom'] = 0;
19047 }
19048
19049
19050 if ($table['va']) { $c['va'] = $table['va']; }
19051 if ($table['txta']) { $c['a'] = $table['txta']; }
19052 if ($this->table_border_attr_set) {
19053 if ($table['border_details']) {
19054 if (!$this->simpleTables){
19055 $c['border_details']['R'] = $table['border_details']['R'];
19056 $c['border_details']['L'] = $table['border_details']['L'];
19057 $c['border_details']['T'] = $table['border_details']['T'];
19058 $c['border_details']['B'] = $table['border_details']['B'];
19059 $c['border'] = $table['border'];
19060 $c['border_details']['L']['dom'] = 1;
19061 $c['border_details']['R']['dom'] = 1;
19062 $c['border_details']['T']['dom'] = 1;
19063 $c['border_details']['B']['dom'] = 1;
19064 }
19065 else if ($this->simpleTables && $this->row==0 && $this->col==0){
19066 $table['simple']['border_details']['R'] = $table['border_details']['R'];
19067 $table['simple']['border_details']['L'] = $table['border_details']['L'];
19068 $table['simple']['border_details']['T'] = $table['border_details']['T'];
19069 $table['simple']['border_details']['B'] = $table['border_details']['B'];
19070 $table['simple']['border'] = $table['border'];
19071 }
19072 }
19073 }
19074 // INHERITED THEAD CSS Properties
19075 if ($this->tablethead) {
19076 if ($this->thead_valign_default) $c['va'] = $align[strtolower($this->thead_valign_default)];
19077 if ($this->thead_textalign_default) $c['a'] = $align[strtolower($this->thead_textalign_default)];
19078 if ($this->thead_font_weight == 'B') { $this->SetStyle('B',true); }
19079 if ($this->thead_font_style == 'I') { $this->SetStyle('I',true); }
19080 if ($this->thead_font_smCaps == 'S') { $this->textvar = ($this->textvar | FC_SMALLCAPS); } // mPDF 5.7.1
19081 }
19082
19083 // INHERITED TFOOT CSS Properties
19084 if ($this->tabletfoot) {
19085 if ($this->tfoot_valign_default) $c['va'] = $align[strtolower($this->tfoot_valign_default)];
19086 if ($this->tfoot_textalign_default) $c['a'] = $align[strtolower($this->tfoot_textalign_default)];
19087 if ($this->tfoot_font_weight == 'B') { $this->SetStyle('B',true); }
19088 if ($this->tfoot_font_style == 'I') { $this->SetStyle('I',true); }
19089 if ($this->tfoot_font_style == 'S') { $this->textvar = ($this->textvar | FC_SMALLCAPS); } // mPDF 5.7.1
19090 }
19091
19092
19093 if ($this->trow_text_rotate){
19094 $c['R'] = $this->trow_text_rotate;
19095 }
19096
19097 $this->cell_border_dominance_L = 0;
19098 $this->cell_border_dominance_R = 0;
19099 $this->cell_border_dominance_T = 0;
19100 $this->cell_border_dominance_B = 0;
19101
19102 $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
19103
19104 $properties = $this->cssmgr->array_merge_recursive_unique($this->base_table_properties, $properties);
19105
19106 $this->Reset(); // mPDF 6 ?????????????????????
19107
19108 $this->setCSS($properties,'TABLECELL',$tag);
19109
19110 $c['dfs'] = $this->FontSize; // Default Font size
19111
19112
19113 if (isset($properties['BACKGROUND-COLOR'])) { $c['bgcolor'] = $properties['BACKGROUND-COLOR']; }
19114 else if (isset($properties['BACKGROUND'])) { $c['bgcolor'] = $properties['BACKGROUND']; }
19115 else if (isset($attr['BGCOLOR'])) $c['bgcolor'] = $attr['BGCOLOR'];
19116
19117
19118
19119 /*-- BACKGROUNDS --*/
19120 if (isset($properties['BACKGROUND-GRADIENT'])) { $c['gradient'] = $properties['BACKGROUND-GRADIENT']; }
19121 else { $c['gradient'] = false; }
19122
19123 if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->keep_block_together) {
19124 $ret = $this->SetBackground($properties, $this->blk[$this->blklvl]['inner_width']);
19125 if ($ret) { $c['background-image'] = $ret; }
19126 }
19127 /*-- END BACKGROUNDS --*/
19128 if (isset($properties['VERTICAL-ALIGN'])) { $c['va']=$align[strtolower($properties['VERTICAL-ALIGN'])]; }
19129 else if (isset($attr['VALIGN'])) $c['va'] = $align[strtolower($attr['VALIGN'])];
19130
19131
19132 if (isset($properties['TEXT-ALIGN']) && $properties['TEXT-ALIGN']) {
19133 if (substr($properties['TEXT-ALIGN'],0,1)=='D') { $c['a'] = $properties['TEXT-ALIGN']; }
19134 else { $c['a'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
19135 }
19136 if (isset($attr['ALIGN']) && $attr['ALIGN']) {
19137 if (strtolower($attr['ALIGN']) == 'char') {
19138 if (isset($attr['CHAR']) && $attr['CHAR']) {
19139 $char = html_entity_decode($attr['CHAR']);
19140 $char = strcode2utf($char);
19141 $d = array_search($char,$this->decimal_align);
19142 if ($d !== false) { $c['a'] = $d.'R'; }
19143 }
19144 else { $c['a'] = 'DPR'; }
19145 }
19146 else { $c['a'] = $align[strtolower($attr['ALIGN'])]; }
19147 }
19148
19149 // mPDF 6
19150 $c['direction'] = $table['direction'];
19151 if (isset($attr['DIR']) and $attr['DIR'] != '') { $c['direction'] = strtolower($attr['DIR']); }
19152 if(isset($properties['DIRECTION'])) { $c['direction'] = strtolower($properties['DIRECTION']); }
19153
19154 if (!$c['a']) {
19155 if (isset($c['direction']) && $c['direction'] == 'rtl' ) { $c['a'] = 'R'; }
19156 else { $c['a'] = 'L'; }
19157 }
19158
19159 $c['cellLineHeight'] = $table['cellLineHeight'];
19160 if(isset($properties['LINE-HEIGHT'])) { $c['cellLineHeight'] = $this->fixLineheight($properties['LINE-HEIGHT']); }
19161
19162 $c['cellLineStackingStrategy'] = $table['cellLineStackingStrategy'];
19163 if(isset($properties['LINE-STACKING-STRATEGY'])) { $c['cellLineStackingStrategy'] = strtolower($properties['LINE-STACKING-STRATEGY']); }
19164
19165 $c['cellLineStackingShift'] = $table['cellLineStackingShift'];
19166 if(isset($properties['LINE-STACKING-SHIFT'])) { $c['cellLineStackingShift'] = strtolower($properties['LINE-STACKING-SHIFT']); }
19167
19168 if (isset($properties['TEXT-ROTATE']) && ($properties['TEXT-ROTATE'] || $properties['TEXT-ROTATE']==="0")){
19169 $c['R'] = $properties['TEXT-ROTATE'];
19170 }
19171 if (isset($properties['BORDER'])) {
19172 $bord = $this->border_details($properties['BORDER']);
19173 if ($bord['s']) {
19174 if (!$this->simpleTables){
19175 $c['border'] = _BORDER_ALL;
19176 $c['border_details']['R'] = $bord;
19177 $c['border_details']['L'] = $bord;
19178 $c['border_details']['T'] = $bord;
19179 $c['border_details']['B'] = $bord;
19180 $c['border_details']['L']['dom'] = $this->cell_border_dominance_L;
19181 $c['border_details']['R']['dom'] = $this->cell_border_dominance_R;
19182 $c['border_details']['T']['dom'] = $this->cell_border_dominance_T;
19183 $c['border_details']['B']['dom'] = $this->cell_border_dominance_B;
19184 }
19185 else if ($this->simpleTables && $this->row==0 && $this->col==0){
19186 $table['simple']['border'] = _BORDER_ALL;
19187 $table['simple']['border_details']['R'] = $bord;
19188 $table['simple']['border_details']['L'] = $bord;
19189 $table['simple']['border_details']['T'] = $bord;
19190 $table['simple']['border_details']['B'] = $bord;
19191 }
19192 }
19193 }
19194 if (!$this->simpleTables){
19195 if (isset($properties['BORDER-RIGHT']) && $properties['BORDER-RIGHT']) {
19196 $c['border_details']['R'] = $this->border_details($properties['BORDER-RIGHT']);
19197 $this->setBorder($c['border'], _BORDER_RIGHT, $c['border_details']['R']['s']);
19198 $c['border_details']['R']['dom'] = $this->cell_border_dominance_R;
19199 }
19200 if (isset($properties['BORDER-LEFT']) && $properties['BORDER-LEFT']) {
19201 $c['border_details']['L'] = $this->border_details($properties['BORDER-LEFT']);
19202 $this->setBorder($c['border'], _BORDER_LEFT, $c['border_details']['L']['s']);
19203 $c['border_details']['L']['dom'] = $this->cell_border_dominance_L;
19204 }
19205 if (isset($properties['BORDER-BOTTOM']) && $properties['BORDER-BOTTOM']) {
19206 $c['border_details']['B'] = $this->border_details($properties['BORDER-BOTTOM']);
19207 $this->setBorder($c['border'], _BORDER_BOTTOM, $c['border_details']['B']['s']);
19208 $c['border_details']['B']['dom'] = $this->cell_border_dominance_B;
19209 }
19210 if (isset($properties['BORDER-TOP']) && $properties['BORDER-TOP']) {
19211 $c['border_details']['T'] = $this->border_details($properties['BORDER-TOP']);
19212 $this->setBorder($c['border'], _BORDER_TOP, $c['border_details']['T']['s']);
19213 $c['border_details']['T']['dom'] = $this->cell_border_dominance_T;
19214 }
19215 }
19216 else if ($this->simpleTables && $this->row==0 && $this->col==0){
19217 if (isset($properties['BORDER-LEFT']) && $properties['BORDER-LEFT']) {
19218 $bord = $this->border_details($properties['BORDER-LEFT']);
19219 if ($bord['s']) { $table['simple']['border'] = _BORDER_ALL; }
19220 else { $table['simple']['border'] = 0; }
19221 $table['simple']['border_details']['R'] = $bord;
19222 $table['simple']['border_details']['L'] = $bord;
19223 $table['simple']['border_details']['T'] = $bord;
19224 $table['simple']['border_details']['B'] = $bord;
19225 }
19226 }
19227
19228 if ($this->simpleTables && $this->row==0 && $this->col==0 && !$table['borders_separate'] && $table['simple']['border'] ){
19229 $table['border_details'] = $table['simple']['border_details'];
19230 $table['border'] = $table['simple']['border'];
19231 }
19232
19233 // Border set on TR (if collapsed only)
19234 if (!$table['borders_separate'] && !$this->simpleTables && isset($table['trborder-left'][$this->row])) {
19235 if ($this->col==0) {
19236 $left = $this->border_details($table['trborder-left'][$this->row]);
19237 $c['border_details']['L'] = $left;
19238 $this->setBorder($c['border'], _BORDER_LEFT, $c['border_details']['L']['s']);
19239 }
19240 $c['border_details']['B'] = $this->border_details($table['trborder-bottom'][$this->row]);
19241 $this->setBorder($c['border'], _BORDER_BOTTOM, $c['border_details']['B']['s']);
19242 $c['border_details']['T'] = $this->border_details($table['trborder-top'][$this->row]);
19243 $this->setBorder($c['border'], _BORDER_TOP, $c['border_details']['T']['s']);
19244 }
19245
19246 if ($this->packTableData && !$this->simpleTables) {
19247 $c['borderbin'] = $this->_packCellBorder($c);
19248 unset($c['border']);
19249 unset($c['border_details']);
19250 }
19251
19252 if (isset($properties['PADDING-LEFT'])) {
19253 $c['padding']['L'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
19254 }
19255 if (isset($properties['PADDING-RIGHT'])) {
19256 $c['padding']['R'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
19257 }
19258 if (isset($properties['PADDING-BOTTOM'])) {
19259 $c['padding']['B'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
19260 }
19261 if (isset($properties['PADDING-TOP'])) {
19262 $c['padding']['T'] = $this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
19263 }
19264
19265 $w = '';
19266 if (isset($properties['WIDTH'])) { $w = $properties['WIDTH']; }
19267 else if (isset($attr['WIDTH'])) { $w = $attr['WIDTH']; }
19268 if ($w) {
19269 if (strpos($w,'%') && !$this->ignore_table_percents ) { $c['wpercent'] = $w + 0; } // makes 80% -> 80
19270 else if (!strpos($w,'%') && !$this->ignore_table_widths ) { $c['w'] = $this->ConvertSize($w,$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
19271 }
19272
19273 if (isset($properties['HEIGHT']) && !strpos($properties['HEIGHT'],'%')) { $c['h'] = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
19274 else if (isset($attr['HEIGHT']) && !strpos($attr['HEIGHT'],'%')) $c['h'] = $this->ConvertSize($attr['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
19275
19276 if (isset($properties['WHITE-SPACE'])) {
19277 if (strtoupper($properties['WHITE-SPACE']) == 'NOWRAP') { $c['nowrap']= 1; }
19278 }
19279 $properties = array();
19280
19281
19282 if (isset($attr['TEXT-ROTATE'])) {
19283 $c['R'] = $attr['TEXT-ROTATE'];
19284 }
19285 if (isset($attr['NOWRAP']) && $attr['NOWRAP']) $c['nowrap']= 1;
19286
19287 $this->cell[$this->row][$this->col] = $c;
19288 unset($c);
19289 $this->cell[$this->row][$this->col]['s'] = 0 ;
19290
19291 $cs = $rs = 1;
19292 if (isset($attr['COLSPAN']) && $attr['COLSPAN']>1) $cs = $this->cell[$this->row][$this->col]['colspan'] = $attr['COLSPAN'];
19293 if ($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'] < $this->col+$cs) {
19294 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'] = $this->col+$cs;
19295 } // following code moved outside if...
19296 for($l=$this->col; $l < $this->col+$cs ;$l++) {
19297 if ($l-$this->col) $this->cell[$this->row][$l] = 0;
19298 }
19299 if (isset($attr['ROWSPAN']) && $attr['ROWSPAN']>1) $rs = $this->cell[$this->row][$this->col]['rowspan'] = $attr['ROWSPAN'];
19300 for ($k=$this->row ; $k < $this->row+$rs ;$k++) {
19301 for($l=$this->col; $l < $this->col+$cs ;$l++) {
19302 if ($k-$this->row || $l-$this->col) $this->cell[$k][$l] = 0;
19303 }
19304 }
19305 unset($table);
19306 break;
19307 /*-- END TABLES --*/
19308
19309
19310
19311 }//end of switch
19312 }
19313
19314
19315 // LIST MARKERS // mPDF 6 Lists
19316 function _setListMarker($listitemtype, $listitemimage, $listitemposition) {
19317 // if position:inside (and NOT table) - output now as a textbuffer; (so if next is block, will move to new line)
19318 // else if position:outside (and NOT table) - output in front of first textbuffer output by setting listitem (cf. _saveTextBuffer)
19319 $e = '';
19320 $this->listitem = '';
19321 $spacer = ' ';
19322 // IMAGE
19323 if ($listitemimage && $listitemimage != 'none') {
19324 $listitemimage = trim(preg_replace('/url\(["\']*(.*?)["\']*\)/','\\1',$listitemimage));
19325
19326 // ? Restrict maximum height/width of list marker??
19327 $maxWidth = 100;
19328 $maxHeight = 100;
19329
19330 $objattr = array();
19331 $objattr['margin_top'] = 0;
19332 $objattr['margin_bottom'] = 0;
19333 $objattr['margin_left'] = 0;
19334 $objattr['margin_right'] = 0;
19335 $objattr['padding_top'] = 0;
19336 $objattr['padding_bottom'] = 0;
19337 $objattr['padding_left'] = 0;
19338 $objattr['padding_right'] = 0;
19339 $objattr['width'] = 0;
19340 $objattr['height'] = 0;
19341 $objattr['border_top']['w'] = 0;
19342 $objattr['border_bottom']['w'] = 0;
19343 $objattr['border_left']['w'] = 0;
19344 $objattr['border_right']['w'] = 0;
19345 $objattr['visibility'] = 'visible';
19346 $srcpath = $listitemimage;
19347 $orig_srcpath = $listitemimage;
19348
19349 $objattr['vertical-align'] = 'BS'; // vertical alignment of marker (baseline)
19350 $w = 0;
19351 $h = 0;
19352
19353 // Image file
19354 $info=$this->_getImage($srcpath, true, true, $orig_srcpath);
19355 if(!$info) return;
19356 if ($info['w']==0 && $info['h']==0) {
19357 $info['h'] = $this->ConvertSize('1em',$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
19358 }
19359 $objattr['file'] = $srcpath;
19360 //Default width and height calculation if needed
19361 if($w==0 and $h==0) {
19362 /*-- IMAGES-WMF --*/
19363 if ($info['type']=='wmf') {
19364 // WMF units are twips (1/20pt)
19365 // divide by 20 to get points
19366 // divide by k to get user units
19367 $w = abs($info['w'])/(20*_MPDFK);
19368 $h = abs($info['h']) / (20*_MPDFK);
19369 }
19370 else
19371 /*-- END IMAGES-WMF --*/
19372 if ($info['type']=='svg') {
19373 // SVG units are pixels
19374 $w = abs($info['w'])/_MPDFK;
19375 $h = abs($info['h'])/_MPDFK;
19376 }
19377 else {
19378 //Put image at default image dpi
19379 $w=($info['w']/_MPDFK) * (72/$this->img_dpi);
19380 $h=($info['h']/_MPDFK) * (72/$this->img_dpi);
19381 }
19382 }
19383 // IF WIDTH OR HEIGHT SPECIFIED
19384 if($w==0) $w=abs($h*$info['w']/$info['h']);
19385 if($h==0) $h=abs($w*$info['h']/$info['w']);
19386
19387 if ($w > $maxWidth ) {
19388 $w = $maxWidth;
19389 $h=abs($w*$info['h']/$info['w']);
19390 }
19391
19392 if ($h > $maxHeight ) {
19393 $h = $maxHeight ;
19394 $w=abs($h*$info['w']/$info['h']);
19395 }
19396 $objattr['type'] = 'image';
19397 $objattr['itype'] = $info['type'];
19398
19399 $objattr['orig_h'] = $info['h'];
19400 $objattr['orig_w'] = $info['w'];
19401 /*-- IMAGES-WMF --*/
19402 if ($info['type']=='wmf') {
19403 $objattr['wmf_x'] = $info['x'];
19404 $objattr['wmf_y'] = $info['y'];
19405 }
19406 else
19407 /*-- END IMAGES-WMF --*/
19408 if ($info['type']=='svg') {
19409 $objattr['wmf_x'] = $info['x'];
19410 $objattr['wmf_y'] = $info['y'];
19411 }
19412 $objattr['height'] = $h;
19413 $objattr['width'] = $w;
19414 $objattr['image_height'] = $h;
19415 $objattr['image_width'] = $w;
19416
19417 $objattr['dir'] = (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : 'ltr');
19418 $objattr['listmarker'] = true;
19419
19420 $objattr['listmarkerposition'] = $listitemposition;
19421
19422 $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
19423 $this->_saveTextBuffer($e);
19424
19425 if ($listitemposition == 'inside') {
19426 $e = $spacer;
19427 $this->_saveTextBuffer($e);
19428 }
19429 }
19430 // SYMBOL (needs new font)
19431 else if ($listitemtype == 'disc' || $listitemtype == 'circle' || $listitemtype == 'square') {
19432 $objattr = array();
19433 $objattr['type'] = 'listmarker';
19434 $objattr['listmarkerposition'] = $listitemposition;
19435 $objattr['width'] = 0;
19436 $size = $this->ConvertSize($this->list_symbol_size,$this->FontSize);
19437 $objattr['size'] = $size;
19438 $objattr['offset'] = $this->ConvertSize($this->list_marker_offset,$this->FontSize);
19439
19440 if ($listitemposition == 'inside') {
19441 $objattr['width'] = $size + $objattr['offset'];
19442 }
19443
19444 $objattr['height'] = $this->FontSize;
19445 $objattr['vertical-align'] = 'T';
19446 $objattr['text'] = $list_item_marker;
19447 $objattr['dir'] = (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : 'ltr');
19448 $objattr['bullet'] = $listitemtype;
19449 $objattr['colorarray'] = $this->colorarray;
19450 $objattr['fontfamily'] = $this->FontFamily;
19451 $objattr['fontsize'] = $this->FontSize;
19452 $objattr['fontsizept'] = $this->FontSizePt;
19453 $objattr['fontstyle'] = $this->FontStyle;
19454
19455 $e = "\xbb\xa4\xactype=listmarker,objattr=".serialize($objattr)."\xbb\xa4\xac";
19456 $this->listitem = $this->_saveTextBuffer($e, '', '', true); // true returns array
19457
19458 // if ($listitemposition == 'inside') {
19459 // $e = $spacer;
19460 // $this->_saveTextBuffer($e);
19461 // }
19462 }
19463 // SYMBOL 2 (needs new font)
19464 else if (preg_match('/U\+([a-fA-F0-9]+)/i',$listitemtype,$m)) {
19465 if ($this->_charDefined($this->CurrentFont['cw'],hexdec($m[1]))) { $list_item_marker = codeHex2utf($m[1]); }
19466 else { $list_item_marker = '-'; }
19467 if (preg_match('/rgb\(.*?\)/',$listitemtype,$m)) {
19468 $list_item_color = $this->ConvertColor($m[0]);
19469 }
19470 else { $list_item_color = ''; }
19471
19472 // SAVE then SET COLR
19473 $save_colorarray = $this->colorarray;
19474 if ($list_item_color) { $this->colorarray = $list_item_color; }
19475
19476 if ($listitemposition == 'inside') {
19477 $e = $list_item_marker . $spacer;
19478 $this->_saveTextBuffer($e);
19479 }
19480 else {
19481 $objattr = array();
19482 $objattr['type'] = 'listmarker';
19483 $objattr['width'] = 0;
19484 $objattr['height'] = $this->FontSize;
19485 $objattr['vertical-align'] = 'T';
19486 $objattr['text'] = $list_item_marker;
19487 $objattr['dir'] = (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : 'ltr');
19488 $objattr['colorarray'] = $this->colorarray;
19489 $objattr['fontfamily'] = $this->FontFamily;
19490 $objattr['fontsize'] = $this->FontSize;
19491 $objattr['fontsizept'] = $this->FontSizePt;
19492 $objattr['fontstyle'] = $this->FontStyle;
19493 $e = "\xbb\xa4\xactype=listmarker,objattr=".serialize($objattr)."\xbb\xa4\xac";
19494 $this->listitem = $this->_saveTextBuffer($e, '', '', true); // true returns array
19495 }
19496 // RESET COLOR
19497 $this->colorarray = $save_colorarray;
19498 }
19499 // TEXT
19500 else {
19501 $counter = $this->listcounter[$this->listlvl];
19502 if ($listitemtype=='none') { return; }
19503 $num = $this->_getStyledNumber($counter, $listitemtype, true);
19504
19505 if ($listitemposition == 'inside') {
19506 $e = $num . $this->list_number_suffix . $spacer;
19507 $this->_saveTextBuffer($e);
19508 }
19509 else {
19510 if (isset($this->blk[$this->blklvl]['direction']) && $this->blk[$this->blklvl]['direction'] == 'rtl') {
19511 // REPLACE MIRRORED RTL $this->list_number_suffix e.g. ) -> ( (NB could use UCDN::$mirror_pairs)
19512 $m = strtr($this->list_number_suffix, ")]}", "([{") . $num;
19513 }
19514 else { $m = $num . $this->list_number_suffix; }
19515
19516 $objattr = array();
19517 $objattr['type'] = 'listmarker';
19518 $objattr['width'] = 0;
19519 $objattr['height'] = $this->FontSize;
19520 $objattr['vertical-align'] = 'T';
19521 $objattr['text'] = $m;
19522 $objattr['dir'] = (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : 'ltr');
19523 $objattr['colorarray'] = $this->colorarray;
19524 $objattr['fontfamily'] = $this->FontFamily;
19525 $objattr['fontsize'] = $this->FontSize;
19526 $objattr['fontsizept'] = $this->FontSizePt;
19527 $objattr['fontstyle'] = $this->FontStyle;
19528 $e = "\xbb\xa4\xactype=listmarker,objattr=".serialize($objattr)."\xbb\xa4\xac";
19529
19530 $this->listitem = $this->_saveTextBuffer($e, '', '', true); // true returns array
19531 }
19532 }
19533
19534
19535 }
19536
19537 // mPDF Lists
19538 function _getListMarkerWidth(&$currblk,&$a,&$i) {
19539 $blt_width = 0;
19540
19541 $markeroffset = $this->ConvertSize($this->list_marker_offset,$this->FontSize);
19542
19543 // Get Maximum number in the list
19544 $maxnum = $this->listcounter[$this->listlvl];
19545 if ($currblk['list_style_type'] != 'disc' && $currblk['list_style_type'] != 'circle' && $currblk['list_style_type'] != 'square') {
19546 $lvl = 1;
19547 for($j=$i+2;$j<count($a);$j+=2) {
19548 $e = $a[$j];
19549 if (!$e) { continue; }
19550 if($e[0]=='/') { // end tag
19551 $e = strtoupper(substr($e,1));
19552 if ($e=='OL' || $e=='UL') {
19553 if ($lvl==1) { break; }
19554 $lvl--;
19555 }
19556 }
19557 else { // opening tag
19558 if (strpos($e,' ')) {
19559 $e = substr($e,0,strpos($e,' '));
19560 }
19561 $e = strtoupper($e);
19562 if ($e=='LI') {
19563 if ($lvl==1) { $maxnum++; }
19564 }
19565 else if ($e=='OL' || $e=='UL') {
19566 $lvl++;
19567 }
19568 }
19569 }
19570 }
19571
19572 switch($currblk['list_style_type']) {
19573 case 'decimal':
19574 case '1':
19575 $blt_width = $this->GetStringWidth(str_repeat('5',strlen($maxnum)).$this->list_number_suffix);
19576 break;
19577 case 'none':
19578 $blt_width = 0;
19579 break;
19580 case 'upper-alpha':
19581 case 'upper-latin':
19582 case 'A':
19583 $maxnumA = $this->dec2alpha($maxnum,true);
19584 if ($maxnum < 13) { $blt_width = $this->GetStringWidth('D'.$this->list_number_suffix); }
19585 else { $blt_width = $this->GetStringWidth(str_repeat('W',strlen($maxnumA)).$this->list_number_suffix); }
19586 break;
19587 case 'lower-alpha':
19588 case 'lower-latin':
19589 case 'a':
19590 $maxnuma = $this->dec2alpha($maxnum,false);
19591 if ($maxnum < 13) { $blt_width = $this->GetStringWidth('b'.$this->list_number_suffix); }
19592 else { $blt_width = $this->GetStringWidth(str_repeat('m',strlen($maxnuma)).$this->list_number_suffix); }
19593 break;
19594 case 'upper-roman':
19595 case 'I':
19596 if ($maxnum>87) { $bbit = 87; }
19597 else if ($maxnum>86) { $bbit = 86; }
19598 else if ($maxnum>37) { $bbit = 38; }
19599 else if ($maxnum>36) { $bbit = 37; }
19600 else if ($maxnum>27) { $bbit = 28; }
19601 else if ($maxnum>26) { $bbit = 27; }
19602 else if ($maxnum>17) { $bbit = 18; }
19603 else if ($maxnum>16) { $bbit = 17; }
19604 else if ($maxnum>7) { $bbit = 8; }
19605 else if ($maxnum>6) { $bbit = 7; }
19606 else if ($maxnum>3) { $bbit = 4; }
19607 else { $bbit = $maxnum; }
19608 $maxlnum = $this->dec2roman($bbit,true);
19609 $blt_width = $this->GetStringWidth($maxlnum.$this->list_number_suffix);
19610 break;
19611 case 'lower-roman':
19612 case 'i':
19613 if ($maxnum>87) { $bbit = 87; }
19614 else if ($maxnum>86) { $bbit = 86; }
19615 else if ($maxnum>37) { $bbit = 38; }
19616 else if ($maxnum>36) { $bbit = 37; }
19617 else if ($maxnum>27) { $bbit = 28; }
19618 else if ($maxnum>26) { $bbit = 27; }
19619 else if ($maxnum>17) { $bbit = 18; }
19620 else if ($maxnum>16) { $bbit = 17; }
19621 else if ($maxnum>7) { $bbit = 8; }
19622 else if ($maxnum>6) { $bbit = 7; }
19623 else if ($maxnum>3) { $bbit = 4; }
19624 else { $bbit = $maxnum; }
19625 $maxlnum = $this->dec2roman($bbit,false);
19626 $blt_width = $this->GetStringWidth($maxlnum.$this->list_number_suffix);
19627 break;
19628
19629 case 'disc':
19630 case 'circle':
19631 case 'square':
19632 $size = $this->ConvertSize($this->list_symbol_size,$this->FontSize);
19633 $offset = $this->ConvertSize($this->list_marker_offset,$this->FontSize);
19634 $blt_width = $size + $offset;
19635 break;
19636
19637 case 'arabic-indic':
19638 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, 0x0660),strlen($maxnum)).$this->list_number_suffix);
19639 break;
19640 case 'persian':
19641 case 'urdu':
19642 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, 0x06F0),strlen($maxnum)).$this->list_number_suffix);
19643 break;
19644 case 'bengali':
19645 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, 0x09E6),strlen($maxnum)).$this->list_number_suffix);
19646 break;
19647 case 'devanagari':
19648 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, 0x0966),strlen($maxnum)).$this->list_number_suffix);
19649 break;
19650 case 'gujarati':
19651 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, 0x0AE6),strlen($maxnum)).$this->list_number_suffix);
19652 break;
19653 case 'gurmukhi':
19654 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, 0x0A66),strlen($maxnum)).$this->list_number_suffix);
19655 break;
19656 case 'kannada':
19657 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, 0x0CE6),strlen($maxnum)).$this->list_number_suffix);
19658 break;
19659 case 'malayalam':
19660 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(6, 0x0D66),strlen($maxnum)).$this->list_number_suffix);
19661 break;
19662 case 'oriya':
19663 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, 0x0B66),strlen($maxnum)).$this->list_number_suffix);
19664 break;
19665 case 'telugu':
19666 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, 0x0C66),strlen($maxnum)).$this->list_number_suffix);
19667 break;
19668 case 'tamil':
19669 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(9, 0x0BE6),strlen($maxnum)).$this->list_number_suffix);
19670 break;
19671 case 'thai':
19672 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(5, 0x0E50),strlen($maxnum)).$this->list_number_suffix);
19673 break;
19674 default:
19675 $blt_width = $this->GetStringWidth(str_repeat('5',strlen($maxnum)).$this->list_number_suffix);
19676 break;
19677 }
19678
19679
19680
19681 return ($blt_width + $markeroffset);
19682 }
19683
19684
19685
19686 function CloseTag($tag,&$ahtml,&$ihtml) { // mPDF 6
19687
19688 //Closing tag
19689 if($tag=='OPTION') { $this->selectoption['ACTIVE'] = false; $this->lastoptionaltag = ''; }
19690
19691 if($tag=='TTS' or $tag=='TTA' or $tag=='TTZ') {
19692 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
19693 unset($this->InlineProperties[$tag]);
19694 $ltag = strtolower($tag);
19695 $this->$ltag = false;
19696 }
19697
19698
19699 if($tag=='FONT' || $tag=='SPAN' || $tag=='CODE' || $tag=='KBD' || $tag=='SAMP' || $tag=='TT' || $tag=='VAR'
19700 || $tag=='INS' || $tag=='STRONG' || $tag=='CITE' || $tag=='SUB' || $tag=='SUP' || $tag=='S' || $tag=='STRIKE' || $tag=='DEL'
19701 || $tag=='Q' || $tag=='EM' || $tag=='B' || $tag=='I' || $tag=='U' | $tag=='SMALL' || $tag=='BIG' || $tag=='ACRONYM'
19702 || $tag=='MARK' || $tag=='TIME' || $tag=='PROGRESS' || $tag=='METER' || $tag== 'BDO' || $tag== 'BDI'
19703 ) {
19704
19705 $annot = false; // mPDF 6
19706 $bdf = false; // mPDF 6
19707
19708 // mPDF 5.7.3 Inline tags
19709 if ($tag=='PROGRESS' || $tag=='METER') {
19710 if (isset($this->InlineProperties[$tag]) && $this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
19711 unset($this->InlineProperties[$tag]);
19712 if (isset($this->InlineAnnots[$tag]) && $this->InlineAnnots[$tag]) { $annot = $this->InlineAnnots[$tag]; } // *ANNOTATIONS*
19713 unset($this->InlineAnnots[$tag]); // *ANNOTATIONS*
19714 }
19715 else {
19716 if (isset($this->InlineProperties[$tag]) && count($this->InlineProperties[$tag])) {
19717 $tmpProps = array_pop($this->InlineProperties[$tag]); // mPDF 5.7.4
19718 $this->restoreInlineProperties($tmpProps);
19719 }
19720 if (isset($this->InlineAnnots[$tag]) && count($this->InlineAnnots[$tag])) { // *ANNOTATIONS*
19721 $annot = array_pop($this->InlineAnnots[$tag]); // *ANNOTATIONS*
19722 } // *ANNOTATIONS*
19723 if (isset($this->InlineBDF[$tag]) && count($this->InlineBDF[$tag])) { // mPDF 6
19724 $bdfarr = array_pop($this->InlineBDF[$tag]);
19725 $bdf = $bdfarr[0];
19726 }
19727 }
19728
19729 /*-- ANNOTATIONS --*/
19730 if ($annot) { // mPDF 6
19731 if($this->tableLevel) { // *TABLES*
19732 $this->cell[$this->row][$this->col]['textbuffer'][] = array($annot); // *TABLES*
19733 } // *TABLES*
19734 else { // *TABLES*
19735 $this->textbuffer[] = array($annot);
19736 } // *TABLES*
19737 }
19738 /*-- END ANNOTATIONS --*/
19739
19740 // mPDF 6 bidi
19741 // mPDF 6 Bidirectional formatting for inline elements
19742 if ($bdf) {
19743 $popf = $this->_setBidiCodes('end', $bdf);
19744 $this->OTLdata = array();
19745 if($this->tableLevel) { $this->_saveCellTextBuffer($popf); }
19746 else { $this->_saveTextBuffer($popf); }
19747 }
19748
19749 } // End of (most) Inline elements eg SPAN
19750
19751
19752 if($tag=='METER' || $tag=='PROGRESS') {
19753 $this->ignorefollowingspaces = false;
19754 $this->inMeter = false;
19755 }
19756
19757
19758 if($tag=='A') {
19759 $this->HREF='';
19760 if (isset($this->InlineProperties['A'])) { $this->restoreInlineProperties($this->InlineProperties['A']); }
19761 unset($this->InlineProperties['A']);
19762 }
19763
19764 if($tag=='LEGEND') {
19765 if (count($this->textbuffer) && !$this->tableLevel) {
19766 $leg = $this->textbuffer[(count($this->textbuffer)-1)];
19767 unset($this->textbuffer[(count($this->textbuffer)-1)]);
19768 $this->textbuffer = array_values($this->textbuffer);
19769 $this->blk[$this->blklvl]['border_legend'] = $leg;
19770 $this->blk[$this->blklvl]['margin_top'] += ($leg[11]/2)/_MPDFK;
19771 $this->blk[$this->blklvl]['padding_top'] += ($leg[11]/2)/_MPDFK;
19772 }
19773 if (isset($this->InlineProperties['LEGEND'])) { $this->restoreInlineProperties($this->InlineProperties['LEGEND']); }
19774 unset($this->InlineProperties['LEGEND']);
19775 $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
19776 }
19777
19778
19779
19780 /*-- FORMS --*/
19781 // *********** FORM ELEMENTS ********************
19782
19783 if($tag=='TEXTAREA') {
19784 $this->ignorefollowingspaces = false;
19785 $this->specialcontent = '';
19786 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
19787 unset($this->InlineProperties[$tag]);
19788 }
19789
19790
19791 if($tag=='SELECT') {
19792 $this->ignorefollowingspaces = false;
19793 $this->lastoptionaltag = '';
19794 $texto = '';
19795 $OTLdata = false;
19796 if (isset($this->selectoption['SELECTED'])) { $texto = $this->selectoption['SELECTED']; }
19797 if (isset($this->selectoption['SELECTED-OTLDATA'])) { $OTLdata = $this->selectoption['SELECTED-OTLDATA']; }
19798
19799 if ($this->useActiveForms) { $w = $this->selectoption['MAXWIDTH']; }
19800 else { $w = $this->GetStringWidth($texto, true, $OTLdata); }
19801 if ($w == 0) { $w = 5; }
19802 $objattr['type'] = 'select';
19803 $objattr['text'] = $texto;
19804 $objattr['OTLdata'] = $OTLdata;
19805 if (isset($this->selectoption['NAME'])) { $objattr['fieldname'] = $this->selectoption['NAME']; }
19806 if (isset($this->selectoption['READONLY'])) { $objattr['readonly'] = true; }
19807 if (isset($this->selectoption['REQUIRED'])) { $objattr['required'] = true; }
19808 if (isset($this->selectoption['SPELLCHECK'])) { $objattr['spellcheck'] = true; }
19809 if (isset($this->selectoption['EDITABLE'])) { $objattr['editable'] = true; }
19810 if (isset($this->selectoption['ONCHANGE'])) { $objattr['onChange'] = $this->selectoption['ONCHANGE']; }
19811 if (isset($this->selectoption['ITEMS'])) { $objattr['items'] = $this->selectoption['ITEMS']; }
19812 if (isset($this->selectoption['MULTIPLE'])) { $objattr['multiple'] = $this->selectoption['MULTIPLE']; }
19813 if (isset($this->selectoption['DISABLED'])) { $objattr['disabled'] = $this->selectoption['DISABLED']; }
19814 if (isset($this->selectoption['TITLE'])) { $objattr['title'] = $this->selectoption['TITLE']; }
19815 if (isset($this->selectoption['COLOR'])) { $objattr['color'] = $this->selectoption['COLOR']; }
19816 if (isset($this->selectoption['SIZE'])) { $objattr['size'] = $this->selectoption['SIZE']; }
19817 if (isset($objattr['size']) && $objattr['size']>1) { $rows=$objattr['size']; } else { $rows = 1; }
19818
19819 $objattr['fontfamily'] = $this->FontFamily;
19820 $objattr['fontsize'] = $this->FontSizePt;
19821
19822 $objattr['width'] = $w + ($this->mpdfform->form_element_spacing['select']['outer']['h']*2)+($this->mpdfform->form_element_spacing['select']['inner']['h']*2) + ($this->FontSize*1.4);
19823 $objattr['height'] = ($this->FontSize*$rows) + ($this->mpdfform->form_element_spacing['select']['outer']['v']*2)+($this->mpdfform->form_element_spacing['select']['inner']['v']*2);
19824 $e = "\xbb\xa4\xactype=select,objattr=".serialize($objattr)."\xbb\xa4\xac";
19825
19826 // Clear properties - tidy up
19827 $properties = array();
19828
19829 // Output it to buffers
19830 if ($this->tableLevel) { // *TABLES*
19831 $this->_saveCellTextBuffer($e, $this->HREF);
19832 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ; // *TABLES*
19833 } // *TABLES*
19834 else { // *TABLES*
19835 $this->_saveTextBuffer($e, $this->HREF);
19836 } // *TABLES*
19837
19838 $this->selectoption = array();
19839 $this->specialcontent = '';
19840
19841 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
19842 unset($this->InlineProperties[$tag]);
19843
19844 }
19845 /*-- END FORMS --*/
19846
19847
19848 // *********** BLOCKS ********************
19849 // mPDF 6 Lists
19850 if($tag=='P' || $tag=='DIV' || $tag=='H1' || $tag=='H2' || $tag=='H3' || $tag=='H4' || $tag=='H5' || $tag=='H6' || $tag=='PRE'
19851 || $tag=='FORM' || $tag=='ADDRESS' || $tag=='BLOCKQUOTE' || $tag=='CENTER' || $tag=='DT' || $tag=='DD' || $tag=='DL'
19852 || $tag=='CAPTION' || $tag=='FIELDSET' || $tag=='UL' || $tag=='OL' || $tag=='LI'
19853 || $tag=='ARTICLE' || $tag=='ASIDE' || $tag=='FIGURE' || $tag=='FIGCAPTION' || $tag=='FOOTER' || $tag=='HEADER' || $tag=='HGROUP'
19854 || $tag=='MAIN' || $tag=='NAV' || $tag=='SECTION' || $tag=='DETAILS' || $tag=='SUMMARY'
19855 ) {
19856
19857 // mPDF 6 bidi
19858 // Block
19859 // If unicode-bidi set, any embedding levels, isolates, or overrides started by this box are closed
19860 if (isset($this->blk[$this->blklvl]['bidicode'])) {
19861 $blockpost = $this->_setBidiCodes('end', $this->blk[$this->blklvl]['bidicode']);
19862 if ($blockpost) {
19863 $this->OTLdata = array();
19864 if($this->tableLevel) { $this->_saveCellTextBuffer($blockpost); }
19865 else { $this->_saveTextBuffer($blockpost); }
19866 }
19867 }
19868
19869 $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
19870 $this->blockjustfinished=true;
19871
19872 $this->lastblockbottommargin = $this->blk[$this->blklvl]['margin_bottom'];
19873 // mPDF 6 Lists
19874 if ($tag == 'UL' || $tag == 'OL') {
19875 if ($this->listlvl>0 && $this->tableLevel) {
19876 if (isset($this->listtype[$this->listlvl])) unset($this->listtype[$this->listlvl]);
19877 }
19878 $this->listlvl--;
19879 $this->listitem = array();
19880 }
19881 if ($tag == 'LI') {
19882 $this->listitem = array();
19883 }
19884
19885 if (preg_match('/^H\d/',$tag) && !$this->tableLevel && !$this->writingToC) {
19886 if (isset($this->h2toc[$tag]) || isset($this->h2bookmarks[$tag])) {
19887 $content = '';
19888 if (count($this->textbuffer)==1) { $content = $this->textbuffer[0][0]; }
19889 else {
19890 for ($i=0;$i<count($this->textbuffer);$i++) {
19891 if (substr($this->textbuffer[$i][0],0,3) != "\xbb\xa4\xac") { //inline object
19892 $content .= $this->textbuffer[$i][0];
19893 }
19894 }
19895 }
19896 /*-- TOC --*/
19897 if (isset($this->h2toc[$tag])) {
19898 $objattr = array();
19899 $objattr['type'] = 'toc';
19900 $objattr['toclevel'] = $this->h2toc[$tag];
19901 $objattr['CONTENT'] = htmlspecialchars($content);
19902 $e = "\xbb\xa4\xactype=toc,objattr=".serialize($objattr)."\xbb\xa4\xac";
19903 array_unshift($this->textbuffer,array($e));
19904 }
19905 /*-- END TOC --*/
19906 /*-- BOOKMARKS --*/
19907 if (isset($this->h2bookmarks[$tag])) {
19908 $objattr = array();
19909 $objattr['type'] = 'bookmark';
19910 $objattr['bklevel'] = $this->h2bookmarks[$tag];
19911 $objattr['CONTENT'] = $content;
19912 $e = "\xbb\xa4\xactype=toc,objattr=".serialize($objattr)."\xbb\xa4\xac";
19913 array_unshift($this->textbuffer,array($e));
19914 }
19915 /*-- END BOOKMARKS --*/
19916 }
19917 }
19918
19919 /*-- TABLES --*/
19920 if($this->tableLevel) {
19921 if ($this->linebreakjustfinished) { $this->blockjustfinished=false; }
19922 if (isset($this->InlineProperties['BLOCKINTABLE'])) {
19923 if ($this->InlineProperties['BLOCKINTABLE']) { $this->restoreInlineProperties($this->InlineProperties['BLOCKINTABLE']); }
19924 unset($this->InlineProperties['BLOCKINTABLE']);
19925 }
19926 if($tag=='PRE') { $this->ispre=false; }
19927 return;
19928 }
19929 /*-- END TABLES --*/
19930 $this->lastoptionaltag = '';
19931 $this->divbegin=false;
19932
19933 $this->linebreakjustfinished=false;
19934
19935 $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
19936
19937 /*-- CSS-FLOAT --*/
19938 // If float contained in a float, need to extend bottom to allow for it
19939 $currpos = $this->page*1000 + $this->y;
19940 if (isset($this->blk[$this->blklvl]['float_endpos']) && $this->blk[$this->blklvl]['float_endpos'] > $currpos) {
19941 $old_page = $this->page;
19942 $new_page = intval($this->blk[$this->blklvl]['float_endpos'] /1000);
19943 if ($old_page != $new_page) {
19944 $s = $this->PrintPageBackgrounds();
19945 // Writes after the marker so not overwritten later by page background etc.
19946 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.$this->uniqstr.')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
19947 $this->pageBackgrounds = array();
19948 $this->page = $new_page;
19949 $this->ResetMargins();
19950 $this->Reset();
19951 $this->pageoutput[$this->page] = array();
19952 }
19953 $this->y = (($this->blk[$this->blklvl]['float_endpos'] *1000) % 1000000)/1000; // mod changes operands to integers before processing
19954 }
19955 /*-- END CSS-FLOAT --*/
19956
19957
19958 //Print content
19959 if ($this->lastblocklevelchange == 1) { $blockstate = 3; } // Top & bottom margins/padding
19960 else if ($this->lastblocklevelchange == -1) { $blockstate = 2; } // Bottom margins/padding only
19961 else { $blockstate = 0; }
19962 // called from after e.g. </table> </div> </div> ... Outputs block margin/border and padding
19963 if (count($this->textbuffer) && $this->textbuffer[count($this->textbuffer)-1]) {
19964 if (substr($this->textbuffer[count($this->textbuffer)-1][0],0,3) != "\xbb\xa4\xac") { // not special content
19965 // Right trim last content and adjust OTLdata
19966 if (preg_match('/[ ]+$/',$this->textbuffer[count($this->textbuffer)-1][0], $m)) {
19967 $strip = strlen($m[0]);
19968 $this->textbuffer[count($this->textbuffer)-1][0] = substr($this->textbuffer[count($this->textbuffer)-1][0],0,(strlen($this->textbuffer[count($this->textbuffer)-1][0])-$strip));
19969 /*-- OTL --*/
19970 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
19971 $this->otl->trimOTLdata($this->textbuffer[count($this->textbuffer)-1][18], false, true); // mPDF 6 ZZZ99K
19972 }
19973 /*-- END OTL --*/
19974 }
19975 }
19976 }
19977
19978 if (count($this->textbuffer) == 0 && $this->lastblocklevelchange != 0) {
19979 //$this->newFlowingBlock( $this->blk[$this->blklvl]['width'],$this->lineheight,'',false,2,true, (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : 'ltr'));
19980 $this->newFlowingBlock( $this->blk[$this->blklvl]['width'],$this->lineheight,'',false,$blockstate,true, (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : 'ltr'));
19981 $this->finishFlowingBlock(true); // true = END of flowing block
19982 $this->PaintDivBB('',$blockstate);
19983 }
19984 else {
19985 $this->printbuffer($this->textbuffer,$blockstate);
19986 }
19987
19988
19989 $this->textbuffer=array();
19990
19991 if ($this->kwt) {
19992 $this->kwt_height = $this->y - $this->kwt_y0;
19993 }
19994
19995 /*-- CSS-IMAGE-FLOAT --*/
19996 $this->printfloatbuffer();
19997 /*-- END CSS-IMAGE-FLOAT --*/
19998
19999 if($tag=='PRE') { $this->ispre=false; }
20000
20001 /*-- CSS-FLOAT --*/
20002 if ($this->blk[$this->blklvl]['float'] == 'R') {
20003 // If width not set, here would need to adjust and output buffer
20004 $s = $this->PrintPageBackgrounds();
20005 // Writes after the marker so not overwritten later by page background etc.
20006 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.$this->uniqstr.')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
20007 $this->pageBackgrounds = array();
20008 $this->Reset();
20009 $this->pageoutput[$this->page] = array();
20010
20011 for($i=($this->blklvl-1); $i >= 0; $i--) {
20012 if (isset($this->blk[$i]['float_endpos'])) { $this->blk[$i]['float_endpos'] = max($this->blk[$i]['float_endpos'], ($this->page*1000 + $this->y)); }
20013 else { $this->blk[$i]['float_endpos'] = $this->page*1000 + $this->y; }
20014 }
20015
20016 $this->floatDivs[] = array(
20017 'side'=>'R',
20018 'startpage'=>$this->blk[$this->blklvl]['startpage'] ,
20019 'y0'=>$this->blk[$this->blklvl]['float_start_y'] ,
20020 'startpos'=> ($this->blk[$this->blklvl]['startpage']*1000 + $this->blk[$this->blklvl]['float_start_y']),
20021 'endpage'=>$this->page ,
20022 'y1'=>$this->y ,
20023 'endpos'=> ($this->page*1000 + $this->y),
20024 'w'=> $this->blk[$this->blklvl]['float_width'],
20025 'blklvl'=>$this->blklvl,
20026 'blockContext' => $this->blk[$this->blklvl-1]['blockContext']
20027 );
20028
20029 $this->y = $this->blk[$this->blklvl]['float_start_y'] ;
20030 $this->page = $this->blk[$this->blklvl]['startpage'] ;
20031 $this->ResetMargins();
20032 $this->pageoutput[$this->page] = array();
20033 }
20034 if ($this->blk[$this->blklvl]['float'] == 'L') {
20035 // If width not set, here would need to adjust and output buffer
20036 $s = $this->PrintPageBackgrounds();
20037 // Writes after the marker so not overwritten later by page background etc.
20038 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.$this->uniqstr.')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
20039 $this->pageBackgrounds = array();
20040 $this->Reset();
20041 $this->pageoutput[$this->page] = array();
20042
20043 for($i=($this->blklvl-1); $i >= 0; $i--) {
20044 if (isset($this->blk[$i]['float_endpos'])) { $this->blk[$i]['float_endpos'] = max($this->blk[$i]['float_endpos'], ($this->page*1000 + $this->y)); }
20045 else { $this->blk[$i]['float_endpos'] = $this->page*1000 + $this->y; }
20046 }
20047
20048 $this->floatDivs[] = array(
20049 'side'=>'L',
20050 'startpage'=>$this->blk[$this->blklvl]['startpage'] ,
20051 'y0'=>$this->blk[$this->blklvl]['float_start_y'] ,
20052 'startpos'=> ($this->blk[$this->blklvl]['startpage']*1000 + $this->blk[$this->blklvl]['float_start_y']),
20053 'endpage'=>$this->page ,
20054 'y1'=>$this->y ,
20055 'endpos'=> ($this->page*1000 + $this->y),
20056 'w'=> $this->blk[$this->blklvl]['float_width'],
20057 'blklvl'=>$this->blklvl,
20058 'blockContext' => $this->blk[$this->blklvl-1]['blockContext']
20059 );
20060
20061 $this->y = $this->blk[$this->blklvl]['float_start_y'] ;
20062 $this->page = $this->blk[$this->blklvl]['startpage'] ;
20063 $this->ResetMargins();
20064 $this->pageoutput[$this->page] = array();
20065 }
20066 /*-- END CSS-FLOAT --*/
20067
20068 if (isset($this->blk[$this->blklvl]['visibility']) && $this->blk[$this->blklvl]['visibility']!='visible') {
20069 $this->SetVisibility('visible');
20070 }
20071
20072 if (isset($this->blk[$this->blklvl]['page_break_after'])) { $page_break_after = $this->blk[$this->blklvl]['page_break_after']; }
20073 else { $page_break_after = ''; }
20074
20075 //Reset values
20076 $this->Reset();
20077
20078 if (isset($this->blk[$this->blklvl]['z-index']) && $this->blk[$this->blklvl]['z-index'] > 0) {
20079 $this->EndLayer();
20080 }
20081
20082 // mPDF 6 page-break-inside:avoid
20083 if ($this->blk[$this->blklvl]['keep_block_together']) {
20084 $movepage=false;
20085 // If page-break-inside:avoid section has broken to new page but fits on one side - then move:
20086 if (($this->page - $this->kt_p00) == 1 && $this->y < $this->kt_y00) {
20087 $movepage=true;
20088 }
20089 if (($this->page - $this->kt_p00) > 0) {
20090 for ($i=$this->page;$i>$this->kt_p00;$i--) {
20091 unset($this->pages[$i]);
20092 if (isset($this->blk[$this->blklvl]['bb_painted'][$i])) { unset($this->blk[$this->blklvl]['bb_painted'][$i]); }
20093 if (isset($this->blk[$this->blklvl]['marginCorrected'][$i])) { unset($this->blk[$this->blklvl]['marginCorrected'][$i]); }
20094 if (isset($this->pageoutput[$i])) { unset($this->pageoutput[$i]); }
20095 }
20096 $this->page = $this->kt_p00;
20097 }
20098 $this->keep_block_together = 0;
20099 $this->pageoutput[$this->page] = array();
20100
20101 $this->y = $this->kt_y00;
20102 $ihtml = $this->blk[$this->blklvl]['array_i']-1;
20103
20104 $ahtml[$ihtml+1] .= ' pagebreakavoidchecked="true";'; // avoid re-iterating; read in OpenTag()
20105
20106 unset($this->blk[$this->blklvl]);
20107 $this->blklvl--;
20108
20109 for ($blklvl=1;$blklvl<=$this->blklvl;$blklvl++) {
20110 $this->blk[$blklvl]['y0'] = $this->blk[$blklvl]['initial_y0'] ;
20111 $this->blk[$blklvl]['x0'] = $this->blk[$blklvl]['initial_x0'] ;
20112 $this->blk[$blklvl]['startpage'] = $this->blk[$blklvl]['initial_startpage'] ;
20113 }
20114
20115 if (isset($this->blk[$this->blklvl]['x0'])) { $this->x = $this->blk[$this->blklvl]['x0']; }
20116 else { $this->x=$this->lMargin; }
20117
20118 $this->lastblocklevelchange = 0;
20119 $this->ResetMargins();
20120 if ($movepage) { $this->AddPage(); }
20121 return;
20122 }
20123
20124 if ($this->blklvl > 0) { // ==0 SHOULDN'T HAPPEN - NOT XHTML
20125 if ($this->blk[$this->blklvl]['tag'] == $tag) {
20126 unset($this->blk[$this->blklvl]);
20127 $this->blklvl--;
20128 }
20129 //else { echo $tag; exit; } // debug - forces error if incorrectly nested html tags
20130 }
20131
20132 $this->lastblocklevelchange = -1 ;
20133 // Reset Inline-type properties
20134 if (isset($this->blk[$this->blklvl]['InlineProperties'])) { $this->restoreInlineProperties($this->blk[$this->blklvl]['InlineProperties']); }
20135
20136 $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
20137
20138 if (!$this->tableLevel && $page_break_after) {
20139 $save_blklvl = $this->blklvl;
20140 $save_blk = $this->blk;
20141 $save_silp = $this->saveInlineProperties();
20142 $save_ilp = $this->InlineProperties;
20143 $save_bflp = $this->InlineBDF;
20144 $save_bflpc = $this->InlineBDFctr; // mPDF 6
20145
20146 // mPDF 6 pagebreaktype
20147 $startpage = $this->page;
20148 $pagebreaktype = $this->defaultPagebreakType;
20149 if ($this->ColActive) { $pagebreaktype = 'cloneall'; }
20150
20151 // mPDF 6 pagebreaktype
20152 $this->_preForcedPagebreak($pagebreaktype);
20153
20154 if ($page_break_after == 'RIGHT') { $this->AddPage($this->CurOrientation,'NEXT-ODD','','','','','', '','', '','','','','','',0,0,0,0); }
20155 else if ($page_break_after == 'LEFT') { $this->AddPage($this->CurOrientation,'NEXT-EVEN','','','','','', '','', '','','','','','',0,0,0,0); }
20156 else { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0); }
20157
20158 // mPDF 6 pagebreaktype
20159 $this->_postForcedPagebreak($pagebreaktype, $startpage, $save_blk, $save_blklvl);
20160
20161 $this->InlineProperties = $save_ilp;
20162 $this->InlineBDF = $save_bflp;
20163 $this->InlineBDFctr = $save_bflpc; // mPDF 6
20164 $this->restoreInlineProperties($save_silp);
20165 }
20166 // mPDF 6 bidi
20167 // Block
20168 // If unicode-bidi set, any embedding levels, isolates, or overrides reopened in the continuing block
20169 if (isset($this->blk[$this->blklvl]['bidicode'])) {
20170 $blockpre = $this->_setBidiCodes('start', $this->blk[$this->blklvl]['bidicode']);
20171 if ($blockpre) {
20172 $this->OTLdata = array();
20173 if($this->tableLevel) { $this->_saveCellTextBuffer($blockpre); }
20174 else { $this->_saveTextBuffer($blockpre); }
20175 }
20176 }
20177
20178 }
20179
20180
20181 /*-- TABLES --*/
20182
20183 if($tag=='TH') $this->SetStyle('B',false);
20184
20185 if(($tag=='TH' or $tag=='TD') && $this->tableLevel) {
20186 $this->lastoptionaltag = 'TR';
20187 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
20188 $this->cssmgr->tbCSSlvl--;
20189 if (!$this->tdbegin) { return; }
20190 $this->tdbegin = false;
20191 // Added for correct calculation of cell column width - otherwise misses the last line if not end </p> etc.
20192 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
20193 if (!is_array($this->cell[$this->row][$this->col])) { $this->Error("You may have an error in your HTML code e.g. &lt;/td&gt;&lt;/td&gt;"); }
20194 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
20195 }
20196 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
20197 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
20198 }
20199
20200 // Remove last <br> if at end of cell
20201 if (isset($this->cell[$this->row][$this->col]['textbuffer'])) { $ntb = count($this->cell[$this->row][$this->col]['textbuffer']); }
20202 else { $ntb = 0; }
20203 if ($ntb>1 && $this->cell[$this->row][$this->col]['textbuffer'][$ntb-1][0] == "\n") {
20204 unset($this->cell[$this->row][$this->col]['textbuffer'][$ntb-1]);
20205 }
20206
20207 if ($this->tablethead) {
20208 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_thead'][$this->row] = true;
20209 if ($this->tableLevel==1) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['headernrows'] = max($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['headernrows'] , ($this->row+1)); }
20210 }
20211 if ($this->tabletfoot) {
20212 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'][$this->row] = true;
20213 if ($this->tableLevel==1) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['footernrows'] = max($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['footernrows'] , ($this->row+1 - $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['headernrows'] )); }
20214 }
20215 $this->Reset();
20216 }
20217
20218 if($tag=='TR' && $this->tableLevel) {
20219 // If Border set on TR - Update right border
20220 if (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-left'][$this->row])) {
20221 $c =& $this->cell[$this->row][$this->col];
20222 if ($c) {
20223 if ($this->packTableData) {
20224 $cell = $this->_unpackCellBorder($c['borderbin'] );
20225 }
20226 else { $cell = $c; }
20227 $cell['border_details']['R'] = $this->border_details($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-right'][$this->row]);
20228 $this->setBorder($cell['border'], _BORDER_RIGHT, $cell['border_details']['R']['s']);
20229 if ($this->packTableData) {
20230 $c['borderbin'] = $this->_packCellBorder($cell);
20231 unset($c['border']);
20232 unset($c['border_details']);
20233 }
20234 else { $c = $cell; }
20235 }
20236 }
20237 $this->lastoptionaltag = '';
20238 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
20239 $this->cssmgr->tbCSSlvl--;
20240 $this->trow_text_rotate = '';
20241 $this->tabletheadjustfinished = false;
20242 }
20243
20244 if($tag=='TBODY') {
20245 $this->lastoptionaltag = '';
20246 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
20247 $this->cssmgr->tbCSSlvl--;
20248 }
20249
20250 if($tag=='THEAD') {
20251 $this->lastoptionaltag = '';
20252 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
20253 $this->cssmgr->tbCSSlvl--;
20254 $this->tablethead = 0;
20255 $this->tabletheadjustfinished = true;
20256 $this->ResetStyles();
20257 $this->thead_font_weight = '';
20258 $this->thead_font_style = '';
20259 $this->thead_font_smCaps = '';
20260
20261 $this->thead_valign_default = '';
20262 $this->thead_textalign_default = '';
20263 }
20264
20265 if($tag=='TFOOT') {
20266 $this->lastoptionaltag = '';
20267 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
20268 $this->cssmgr->tbCSSlvl--;
20269 $this->tabletfoot = 0;
20270 $this->ResetStyles();
20271 $this->tfoot_font_weight = '';
20272 $this->tfoot_font_style = '';
20273 $this->tfoot_font_smCaps = '';
20274
20275 $this->tfoot_valign_default = '';
20276 $this->tfoot_textalign_default = '';
20277 }
20278
20279 if($tag=='TABLE') { // TABLE-END (
20280 if ($this->progressBar) { $this->UpdateProgressBar(1,'','TABLE'); } // *PROGRESS-BAR*
20281 if ($this->progressBar) { $this->UpdateProgressBar(7,0,''); } // *PROGRESS-BAR*
20282 $this->lastoptionaltag = '';
20283 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
20284 $this->cssmgr->tbCSSlvl--;
20285 $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
20286 // mPDF 5.7.3
20287 // In case a colspan (on a row after first row) exceeded number of columns in table
20288 for ($k=0; $k < $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr']; $k++) {
20289 for($l=0; $l < $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc']; $l++) {
20290 if (!isset($this->cell[$k][$l])) {
20291 for ($n=$l-1; $n>=0; $n--) {
20292 if (isset($this->cell[$k][$n]) && $this->cell[$k][$n]!=0) { break; }
20293 }
20294 $this->cell[$k][$l] = array(
20295 'a' => 'C',
20296 'va' => 'M',
20297 'R' => false,
20298 'nowrap' => false,
20299 'bgcolor' => false,
20300 'padding' => array('L' => false, 'R' => false, 'T' => false, 'B' => false),
20301 'gradient' => false,
20302 's' => 0,
20303 'maxs' => 0,
20304 'textbuffer' => array(),
20305 'dfs' => $this->FontSize,
20306 );
20307
20308 if (!$this->simpleTables){
20309 $this->cell[$k][$l]['border'] = 0;
20310 $this->cell[$k][$l]['border_details']['R'] = array('s' => 0, 'w' => 0, 'c' => false, 'style' => 'none', 'dom' => 0);
20311 $this->cell[$k][$l]['border_details']['L'] = array('s' => 0, 'w' => 0, 'c' => false, 'style' => 'none', 'dom' => 0);
20312 $this->cell[$k][$l]['border_details']['T'] = array('s' => 0, 'w' => 0, 'c' => false, 'style' => 'none', 'dom' => 0);
20313 $this->cell[$k][$l]['border_details']['B'] = array('s' => 0, 'w' => 0, 'c' => false, 'style' => 'none', 'dom' => 0);
20314 $this->cell[$k][$l]['border_details']['mbw'] = array('BL' =>0,'BR' =>0,'RT' =>0,'RB' =>0,'TL' =>0,'TR' =>0,'LT' =>0,'LB' =>0);
20315 if ($this->packTableData) {
20316 $this->cell[$k][$l]['borderbin'] = $this->_packCellBorder($this->cell[$k][$l]);
20317 unset($this->cell[$k][$l]['border']);
20318 unset($this->cell[$k][$l]['border_details']);
20319 }
20320 }
20321 }
20322 }
20323 }
20324 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] = $this->cell;
20325 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['wc'] = array_pad(array(),$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'],array('miw'=>0,'maw'=>0));
20326 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['hr'] = array_pad(array(),$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr'],0);
20327
20328 // Move table footer <tfoot> row to end of table
20329 if (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot']) && count($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'])) {
20330 $tfrows = array();
20331 foreach($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'] AS $r=>$val) {
20332 if ($val) { $tfrows[] = $r; }
20333 }
20334 $temp = array();
20335 $temptf = array();
20336 foreach($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] AS $k=>$row) {
20337 if (in_array($k,$tfrows)) {
20338 $temptf[] = $row;
20339 }
20340 else {
20341 $temp[] = $row;
20342 }
20343 }
20344 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'] = array();
20345 for($i=count($temp) ; $i<(count($temp)+count($temptf)); $i++) {
20346 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'][$i] = true;
20347 }
20348 // Update nestedpos row references
20349 if (isset($this->table[($this->tableLevel+1)]) && count($this->table[($this->tableLevel+1)])) {
20350 foreach($this->table[($this->tableLevel+1)] AS $nid=>$nested) {
20351 $this->table[($this->tableLevel+1)][$nid]['nestedpos'][0] -= count($temptf);
20352 }
20353 }
20354 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] = array_merge($temp, $temptf);
20355
20356 // Update other arays set on row number
20357 // [trbackground-images] [trgradients]
20358 $temptrbgi = array();
20359 $temptrbgg = array();
20360 $temptrbgc = array();
20361 if (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][-1])) {
20362 $temptrbgc[-1] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][-1];
20363 }
20364 for($k=0; $k<$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr']; $k++) {
20365 if (!in_array($k,$tfrows)) {
20366 $temptrbgi[] = (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'][$k]) ? $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'][$k] : null);
20367 $temptrbgg[] = (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'][$k]) ? $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'][$k] : null);
20368 $temptrbgc[] = (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$k]) ? $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$k] : null);
20369 }
20370 }
20371 for($k=0; $k<$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr']; $k++) {
20372 if (in_array($k,$tfrows)) {
20373 $temptrbgi[] = (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'][$k]) ? $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'][$k] : null);
20374 $temptrbgg[] = (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'][$k]) ? $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'][$k] : null);
20375 $temptrbgc[] = (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$k]) ? $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$k] : null);
20376 }
20377 }
20378 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'] = $temptrbgi;
20379 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'] = $temptrbgg;
20380 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'] = $temptrbgc ;
20381 // Should Update all other arays set on row number, but cell properties have been set so not needed
20382 // [bgcolor] [trborder-left] [trborder-right] [trborder-top] [trborder-bottom]
20383 }
20384
20385 if ($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['direction']=='rtl') {
20386 $this->_reverseTableDir($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]);
20387 }
20388
20389 // Fix Borders *********************************************
20390 $this->_fixTableBorders($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]);
20391
20392 if ($this->progressBar) { $this->UpdateProgressBar(7,10,' '); } // *PROGRESS-BAR*
20393
20394 if ($this->ColActive) { $this->table_rotate = 0; } // *COLUMNS*
20395 if ($this->table_rotate <> 0) {
20396 $this->tablebuffer = '';
20397 // Max width for rotated table
20398 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 1);
20399 $this->tbrot_maxh = $this->blk[$this->blklvl]['inner_width'] ; // Max width for rotated table
20400 $this->tbrot_align = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['a'] ;
20401 }
20402 $this->shrin_k = 1;
20403
20404 if ($this->shrink_tables_to_fit < 1) { $this->shrink_tables_to_fit = 1; }
20405 if (!$this->shrink_this_table_to_fit) { $this->shrink_this_table_to_fit = $this->shrink_tables_to_fit; }
20406
20407 if ($this->tableLevel>1) {
20408 // deal with nested table
20409
20410 $this->_tableColumnWidth($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]],true);
20411
20412 $tmiw = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['miw'];
20413 $tmaw = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['maw'];
20414 $tl = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['tl'];
20415
20416 // Go down to lower table level
20417 $this->tableLevel--;
20418
20419 // Reset lower level table
20420 $this->base_table_properties = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['baseProperties'];
20421 // mPDF 5.7.3
20422 $this->default_font = $this->base_table_properties['FONT-FAMILY'];
20423 $this->SetFont($this->default_font,'',0,false);
20424 $this->default_font_size = $this->ConvertSize($this->base_table_properties['FONT-SIZE'])*(_MPDFK);
20425 $this->SetFontSize($this->default_font_size,false);
20426
20427 $this->cell = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'];
20428 if (isset($this->cell['PARENTCELL'])) {
20429 if ($this->cell['PARENTCELL']) { $this->restoreInlineProperties($this->cell['PARENTCELL']); }
20430 unset($this->cell['PARENTCELL']);
20431 }
20432 $this->row = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currrow'];
20433 $this->col = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currcol'];
20434 $objattr = array();
20435 $objattr['type'] = 'nestedtable';
20436 $objattr['nestedcontent'] = $this->tbctr[($this->tableLevel+1)];
20437 $objattr['table'] = $this->tbctr[$this->tableLevel];
20438 $objattr['row'] = $this->row;
20439 $objattr['col'] = $this->col;
20440 $objattr['level'] = $this->tableLevel;
20441 $e = "\xbb\xa4\xactype=nestedtable,objattr=".serialize($objattr)."\xbb\xa4\xac";
20442 $this->_saveCellTextBuffer($e);
20443 $this->cell[$this->row][$this->col]['s'] += $tl ;
20444 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
20445 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
20446 }
20447 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
20448 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
20449 }
20450 $this->cell[$this->row][$this->col]['s'] = 0;// reset
20451 if ((isset($this->cell[$this->row][$this->col]['nestedmaw']) && $this->cell[$this->row][$this->col]['nestedmaw'] < $tmaw) || !isset($this->cell[$this->row][$this->col]['nestedmaw'])) { $this->cell[$this->row][$this->col]['nestedmaw'] = $tmaw ; }
20452 if ((isset($this->cell[$this->row][$this->col]['nestedmiw']) && $this->cell[$this->row][$this->col]['nestedmiw'] < $tmiw) || !isset($this->cell[$this->row][$this->col]['nestedmiw'])) { $this->cell[$this->row][$this->col]['nestedmiw'] = $tmiw ; }
20453 $this->tdbegin = true;
20454 $this->nestedtablejustfinished = true;
20455 $this->ignorefollowingspaces = true;
20456 return;
20457 }
20458 $this->cMarginL = 0;
20459 $this->cMarginR = 0;
20460 $this->cMarginT = 0;
20461 $this->cMarginB = 0;
20462 $this->cellPaddingL = 0;
20463 $this->cellPaddingR = 0;
20464 $this->cellPaddingT = 0;
20465 $this->cellPaddingB = 0;
20466
20467 if (isset($this->table[1][1]['overflow']) && $this->table[1][1]['overflow']=='visible') {
20468 if ($this->kwt || $this->table_rotate || $this->table_keep_together || $this->ColActive) {
20469 $this->kwt = false;
20470 $this->table_rotate = 0;
20471 $this->table_keep_together = false;
20472 //die("mPDF Warning: You cannot use CSS overflow:visible together with any of these functions: 'Keep-with-table', rotated tables, page-break-inside:avoid, or columns");
20473 }
20474 $this->_tableColumnWidth($this->table[1][1],true);
20475 $this->_tableWidth($this->table[1][1]);
20476 }
20477 else {
20478 if (!$this->kwt_saved) { $this->kwt_height = 0; }
20479
20480 list($check,$tablemiw) = $this->_tableColumnWidth($this->table[1][1],true);
20481 $save_table = $this->table;
20482 $reset_to_minimum_width = false;
20483 $added_page = false;
20484
20485 if ($check > 1) {
20486 if ($check > $this->shrink_this_table_to_fit && $this->table_rotate) {
20487 if ($this->y != $this->tMargin) {
20488 $this->AddPage($this->CurOrientation);
20489 $this->kwt_moved = true;
20490 }
20491 $added_page = true;
20492 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
20493 //$check = $tablemiw/$this->tbrot_maxw; // undo any shrink
20494 $check = 1; // undo any shrink
20495 }
20496 $reset_to_minimum_width = true;
20497 }
20498
20499 if ($reset_to_minimum_width) {
20500 $this->shrin_k = $check;
20501
20502 $this->default_font_size /= $this->shrin_k;
20503 $this->SetFontSize($this->default_font_size, false );
20504
20505 $this->shrinkTable($this->table[1][1],$this->shrin_k);
20506
20507 $this->_tableColumnWidth($this->table[1][1],false); // repeat
20508
20509 // Starting at $this->innermostTableLevel
20510 // Shrink table values - and redo columnWidth
20511 for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
20512 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
20513 $this->shrinkTable($this->table[$lvl][$nid],$this->shrin_k);
20514 $this->_tableColumnWidth($this->table[$lvl][$nid],false);
20515 }
20516 }
20517 }
20518
20519 // Set table cell widths for top level table
20520 // Use $shrin_k to resize but don't change again
20521 $this->SetLineHeight('',$this->table[1][1]['cellLineHeight']);
20522
20523 // Top level table
20524 $this->_tableWidth($this->table[1][1]);
20525
20526 }
20527
20528 // Now work through any nested tables setting child table[w'] = parent cell['w']
20529 // Now do nested tables _tableWidth
20530 for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
20531 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
20532 // HERE set child table width = cell width
20533
20534 list($parentrow, $parentcol, $parentnid) = $this->table[$lvl][$nid]['nestedpos'];
20535
20536 $c =& $this->table[($lvl-1)][$parentnid]['cells'][$parentrow][$parentcol];
20537
20538 if (isset($c['colspan']) && $c['colspan']> 1) {
20539 $parentwidth = 0;
20540 for($cs=0;$cs<$c['colspan'] ; $cs++) {
20541 $parentwidth += $this->table[($lvl-1)][$parentnid]['wc'][$parentcol+$cs];
20542 }
20543 }
20544 else { $parentwidth = $this->table[($lvl-1)][$parentnid]['wc'][$parentcol]; }
20545
20546
20547 //$parentwidth -= ALLOW FOR PADDING ETC.in parent cell
20548 if (!$this->simpleTables){
20549 if ($this->packTableData) {
20550 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
20551 }
20552 else {
20553 $br = $c['border_details']['R']['w'];
20554 $bl = $c['border_details']['L']['w'];
20555 }
20556 if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
20557 $parentwidth -= $br + $bl
20558 + $c['padding']['L']
20559 + $c['padding']['R']
20560 + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
20561 }
20562 else {
20563 $parentwidth -= $br/2 + $bl/2
20564 + $c['padding']['L']
20565 + $c['padding']['R'];
20566 }
20567 }
20568 else if ($this->simpleTables){
20569 if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
20570 $parentwidth -= $this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']
20571 + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']
20572 + $c['padding']['L']
20573 + $c['padding']['R']
20574 + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
20575 }
20576 else {
20577 $parentwidth -= $this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']/2
20578 + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']/2
20579 + $c['padding']['L']
20580 + $c['padding']['R'];
20581 }
20582 }
20583 if (isset($this->table[$lvl][$nid]['wpercent']) && $this->table[$lvl][$nid]['wpercent'] && $lvl>1) {
20584 $this->table[$lvl][$nid]['w'] = $parentwidth;
20585 }
20586 else if ($parentwidth > $this->table[$lvl][$nid]['maw']) {
20587 $this->table[$lvl][$nid]['w'] = $this->table[$lvl][$nid]['maw'];
20588 }
20589 else {
20590 $this->table[$lvl][$nid]['w'] = $parentwidth;
20591 }
20592 unset($c);
20593 $this->_tableWidth($this->table[$lvl][$nid]);
20594 }
20595 }
20596
20597 // Starting at $this->innermostTableLevel
20598 // Cascade back up nested tables: setting heights back up the tree
20599 for($lvl=$this->innermostTableLevel;$lvl>0;$lvl--) {
20600 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
20601 list($tableheight,$maxrowheight,$fullpage,$remainingpage, $maxfirstrowheight) = $this->_tableHeight($this->table[$lvl][$nid]); }
20602 }
20603 if ($this->progressBar) { $this->UpdateProgressBar(7,20,' '); } // *PROGRESS-BAR*
20604 if ($this->table[1][1]['overflow']=='visible') {
20605 if ($maxrowheight > $fullpage) { die("mPDF Warning: A Table row is greater than available height. You cannot use CSS overflow:visible"); }
20606 if ($maxfirstrowheight > $remainingpage) { $this->AddPage($this->CurOrientation); }
20607 $r = 0; $c = 0; $p = 0; $y = 0;
20608 $finished = false;
20609 while (!$finished) {
20610 list($finished,$r,$c,$p,$y,$y0) = $this->_tableWrite($this->table[1][1],true,$r,$c,$p,$y);
20611 if (!$finished) {
20612 $this->AddPage($this->CurOrientation);
20613 // If printed something on first spread, set same y
20614 if ($r==0 && $y0 > -1) { $this->y = $y0; }
20615 }
20616 }
20617 }
20618 else {
20619 $recalculate = 1;
20620 $forcerecalc = false;
20621 // RESIZING ALGORITHM
20622 if ($maxrowheight > $fullpage) {
20623 $recalculate = $this->tbsqrt($maxrowheight / $fullpage, 1);
20624 $forcerecalc = true;
20625 }
20626 else if ($this->table_rotate) { // NB $remainingpage == $fullpage == the width of the page
20627 if ($tableheight > $remainingpage) {
20628 // If can fit on remainder of page whilst respecting autsize value..
20629 if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, 1)) <= $this->shrink_this_table_to_fit) {
20630 $recalculate = $this->tbsqrt($tableheight / $remainingpage, 1);
20631 }
20632 else if (!$added_page) {
20633 if ($this->y != $this->tMargin) {
20634 $this->AddPage($this->CurOrientation);
20635 $this->kwt_moved = true;
20636 }
20637 $added_page = true;
20638 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
20639 // 0.001 to force it to recalculate
20640 $recalculate = (1 / $this->shrin_k) + 0.001; // undo any shrink
20641 }
20642 }
20643 else { $recalculate = 1; }
20644 }
20645 else if ($this->table_keep_together || ($this->table[1][1]['nr']==1 && !$this->writingHTMLfooter)) {
20646 if ($tableheight > $fullpage) {
20647 if (($this->shrin_k * $this->tbsqrt($tableheight / $fullpage, 1)) <= $this->shrink_this_table_to_fit) {
20648 $recalculate = $this->tbsqrt($tableheight / $fullpage, 1);
20649 }
20650 else if ($this->tableMinSizePriority) {
20651 $this->table_keep_together = false;
20652 $recalculate = 1.001;
20653 }
20654 else {
20655 if ($this->y != $this->tMargin) {
20656 $this->AddPage($this->CurOrientation);
20657 $this->kwt_moved = true;
20658 }
20659 $added_page = true;
20660 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
20661 $recalculate = $this->tbsqrt($tableheight / $fullpage, 1);
20662 }
20663 }
20664 else if ($tableheight > $remainingpage) {
20665 // If can fit on remainder of page whilst respecting autsize value..
20666 if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, 1)) <= $this->shrink_this_table_to_fit) {
20667 $recalculate = $this->tbsqrt($tableheight / $remainingpage, 1);
20668 }
20669 else {
20670 if ($this->y != $this->tMargin) {
20671 // mPDF 6
20672 if ($this->AcceptPageBreak()) { $this->AddPage($this->CurOrientation); }
20673 else if ($this->ColActive && $tableheight > (($this->h-$this->bMargin)-$this->y0)) {
20674 $this->AddPage($this->CurOrientation);
20675 }
20676 $this->kwt_moved = true;
20677 }
20678 $added_page = true;
20679 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
20680 $recalculate = 1.001;
20681 }
20682 }
20683 else { $recalculate = 1; }
20684 }
20685 else { $recalculate = 1; }
20686
20687 if ($recalculate > $this->shrink_this_table_to_fit && !$forcerecalc) { $recalculate = $this->shrink_this_table_to_fit; }
20688
20689 $iteration = 1;
20690
20691 // RECALCULATE
20692 while($recalculate <> 1) {
20693 $this->shrin_k1 = $recalculate ;
20694 $this->shrin_k *= $recalculate ;
20695 $this->default_font_size /= ($this->shrin_k1) ;
20696 $this->SetFontSize($this->default_font_size, false );
20697 $this->SetLineHeight('',$this->table[1][1]['cellLineHeight']);
20698 $this->table = $save_table;
20699 if ($this->shrin_k <> 1) { $this->shrinkTable($this->table[1][1],$this->shrin_k); }
20700 $this->_tableColumnWidth($this->table[1][1],false); // repeat
20701
20702 // Starting at $this->innermostTableLevel
20703 // Shrink table values - and redo columnWidth
20704 for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
20705 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
20706 if ($this->shrin_k <> 1) { $this->shrinkTable($this->table[$lvl][$nid],$this->shrin_k); }
20707 $this->_tableColumnWidth($this->table[$lvl][$nid],false);
20708 }
20709 }
20710 // Set table cell widths for top level table
20711
20712 // Top level table
20713 $this->_tableWidth($this->table[1][1]);
20714
20715 // Now work through any nested tables setting child table[w'] = parent cell['w']
20716 // Now do nested tables _tableWidth
20717 for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
20718 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
20719 // HERE set child table width = cell width
20720
20721 list($parentrow, $parentcol, $parentnid) = $this->table[$lvl][$nid]['nestedpos'];
20722 $c =& $this->table[($lvl-1)][$parentnid]['cells'][$parentrow][$parentcol];
20723
20724 if (isset($c['colspan']) && $c['colspan']> 1) {
20725 $parentwidth = 0;
20726 for($cs=0;$cs<$c['colspan'] ; $cs++) {
20727 $parentwidth += $this->table[($lvl-1)][$parentnid]['wc'][$parentcol+$cs];
20728 }
20729 }
20730 else { $parentwidth = $this->table[($lvl-1)][$parentnid]['wc'][$parentcol]; }
20731
20732 //$parentwidth -= ALLOW FOR PADDING ETC.in parent cell
20733 if (!$this->simpleTables){
20734 if ($this->packTableData) {
20735 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
20736 }
20737 else {
20738 $br = $c['border_details']['R']['w'];
20739 $bl = $c['border_details']['L']['w'];
20740 }
20741 if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
20742 $parentwidth -= $br + $bl
20743 + $c['padding']['L']
20744 + $c['padding']['R']
20745 + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
20746 }
20747 else {
20748 $parentwidth -= $br/2 + $bl/2
20749 + $c['padding']['L']
20750 + $c['padding']['R'];
20751 }
20752 }
20753 else if ($this->simpleTables){
20754 if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
20755 $parentwidth -= $this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']
20756 + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']
20757 + $c['padding']['L']
20758 + $c['padding']['R']
20759 + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
20760 }
20761 else {
20762 $parentwidth -= ($this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']
20763 + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']) /2
20764 + $c['padding']['L']
20765 + $c['padding']['R'];
20766 }
20767 }
20768 if (isset($this->table[$lvl][$nid]['wpercent']) && $this->table[$lvl][$nid]['wpercent'] && $lvl>1) {
20769 $this->table[$lvl][$nid]['w'] = $parentwidth;
20770 }
20771 else if ($parentwidth > $this->table[$lvl][$nid]['maw']) {
20772 $this->table[$lvl][$nid]['w'] = $this->table[$lvl][$nid]['maw'] ;
20773 }
20774 else {
20775 $this->table[$lvl][$nid]['w'] = $parentwidth;
20776 }
20777 unset($c);
20778 $this->_tableWidth($this->table[$lvl][$nid]);
20779 }
20780 }
20781
20782 // Starting at $this->innermostTableLevel
20783 // Cascade back up nested tables: setting heights back up the tree
20784 for($lvl=$this->innermostTableLevel;$lvl>0;$lvl--) {
20785 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
20786 list($tableheight,$maxrowheight,$fullpage,$remainingpage, $maxfirstrowheight) = $this->_tableHeight($this->table[$lvl][$nid]); }
20787 }
20788
20789 // RESIZING ALGORITHM
20790
20791 if ($maxrowheight > $fullpage) { $recalculate = $this->tbsqrt($maxrowheight / $fullpage, $iteration); $iteration++; }
20792 else if ($this->table_rotate && $tableheight > $remainingpage && !$added_page) {
20793 // If can fit on remainder of page whilst respecting autosize value..
20794 if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->shrink_this_table_to_fit) {
20795 $recalculate = $this->tbsqrt($tableheight / $remainingpage, $iteration); $iteration++;
20796 }
20797 else {
20798 if (!$added_page) {
20799 $this->AddPage($this->CurOrientation);
20800 $added_page = true;
20801 $this->kwt_moved = true;
20802 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
20803 }
20804 // 0.001 to force it to recalculate
20805 $recalculate = (1 / $this->shrin_k) + 0.001; // undo any shrink
20806 }
20807 }
20808 else if ($this->table_keep_together || ($this->table[1][1]['nr']==1 && !$this->writingHTMLfooter)) {
20809 if ($tableheight > $fullpage) {
20810 if (($this->shrin_k * $this->tbsqrt($tableheight / $fullpage, $iteration)) <= $this->shrink_this_table_to_fit) {
20811 $recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); $iteration++;
20812 }
20813 else if ($this->tableMinSizePriority) {
20814 $this->table_keep_together = false;
20815 $recalculate = (1 / $this->shrin_k) + 0.001;
20816 }
20817 else {
20818 if (!$added_page && $this->y != $this->tMargin) {
20819 $this->AddPage($this->CurOrientation);
20820 $added_page = true;
20821 $this->kwt_moved = true;
20822 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
20823 }
20824 $recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); $iteration++;
20825 }
20826 }
20827 else if ($tableheight > $remainingpage) {
20828 // If can fit on remainder of page whilst respecting autosize value..
20829 if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->shrink_this_table_to_fit) {
20830 $recalculate = $this->tbsqrt($tableheight / $remainingpage, $iteration); $iteration++;
20831 }
20832 else {
20833 if (!$added_page) {
20834 // mPDF 6
20835 if ($this->AcceptPageBreak()) { $this->AddPage($this->CurOrientation); }
20836 else if ($this->ColActive && $tableheight > (($this->h-$this->bMargin)-$this->y0)) {
20837 $this->AddPage($this->CurOrientation);
20838 }
20839 $added_page = true;
20840 $this->kwt_moved = true;
20841 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
20842 }
20843
20844 //$recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); $iteration++;
20845 $recalculate = (1 / $this->shrin_k) + 0.001; // undo any shrink
20846 }
20847 }
20848 else { $recalculate = 1; }
20849 }
20850 else { $recalculate = 1; }
20851 }
20852
20853
20854 if ($maxfirstrowheight > $remainingpage && !$added_page && !$this->table_rotate && !$this->ColActive && !$this->table_keep_together && !$this->writingHTMLheader && !$this->writingHTMLfooter) {
20855 $this->AddPage($this->CurOrientation);
20856 $this->kwt_moved = true;
20857 }
20858
20859 // keep-with-table: if page has advanced, print out buffer now, else done in fn. _Tablewrite()
20860 if ($this->kwt_saved && $this->kwt_moved) {
20861 $this->printkwtbuffer();
20862 $this->kwt_moved = false;
20863 $this->kwt_saved = false;
20864 }
20865
20866 if ($this->progressBar) { $this->UpdateProgressBar(7,30,' '); } // *PROGRESS-BAR*
20867 // Recursively writes all tables starting at top level
20868 $this->_tableWrite($this->table[1][1]);
20869
20870 if ($this->table_rotate && $this->tablebuffer) {
20871 $this->PageBreakTrigger=$this->h-$this->bMargin;
20872 $save_tr = $this->table_rotate;
20873 $save_y = $this->y;
20874 $this->table_rotate = 0;
20875 $this->y = $this->tbrot_y0;
20876 $h = $this->tbrot_w;
20877 $this->DivLn($h,$this->blklvl,true);
20878
20879 $this->table_rotate = $save_tr;
20880 $this->y = $save_y;
20881
20882 $this->printtablebuffer();
20883 }
20884 $this->table_rotate = 0;
20885 }
20886
20887
20888 $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
20889
20890 $this->maxPosR = max($this->maxPosR , ($this->x + $this->table[1][1]['w']));
20891
20892 $this->blockjustfinished=true;
20893 $this->lastblockbottommargin = $this->table[1][1]['margin']['B'];
20894 //Reset values
20895
20896 if (isset($this->table[1][1]['page_break_after'])) { $page_break_after = $this->table[1][1]['page_break_after']; }
20897 else { $page_break_after = ''; }
20898
20899 // Keep-with-table
20900 $this->kwt = false;
20901 $this->kwt_y0 = 0;
20902 $this->kwt_x0 = 0;
20903 $this->kwt_height = 0;
20904 $this->kwt_buffer = array();
20905 $this->kwt_Links = array();
20906 $this->kwt_Annots = array();
20907 $this->kwt_moved = false;
20908 $this->kwt_saved = false;
20909
20910 $this->kwt_Reference = array();
20911 $this->kwt_BMoutlines = array();
20912 $this->kwt_toc = array();
20913
20914 $this->shrin_k = 1;
20915 $this->shrink_this_table_to_fit = 0;
20916
20917 unset($this->table);
20918 $this->table=array(); //array
20919 $this->tableLevel=0;
20920 $this->tbctr=array();
20921 $this->innermostTableLevel=0;
20922 $this->cssmgr->tbCSSlvl = 0;
20923 $this->cssmgr->tablecascadeCSS = array();
20924
20925 unset($this->cell);
20926 $this->cell=array(); //array
20927
20928 $this->col=-1; //int
20929 $this->row=-1; //int
20930 $this->Reset();
20931
20932 $this->cellPaddingL = 0;
20933 $this->cellPaddingT = 0;
20934 $this->cellPaddingR = 0;
20935 $this->cellPaddingB = 0;
20936 $this->cMarginL = 0;
20937 $this->cMarginT = 0;
20938 $this->cMarginR = 0;
20939 $this->cMarginB = 0;
20940 $this->default_font_size = $this->original_default_font_size;
20941 $this->default_font = $this->original_default_font;
20942 $this->SetFontSize($this->default_font_size, false);
20943 $this->SetFont($this->default_font,'',0,false);
20944 $this->SetLineHeight();
20945 if (isset($this->blk[$this->blklvl]['InlineProperties'])) { $this->restoreInlineProperties($this->blk[$this->blklvl]['InlineProperties']);}
20946 if ($this->progressBar) { $this->UpdateProgressBar(7,100,' '); } // *PROGRESS-BAR*
20947
20948 if ($page_break_after) {
20949 $save_blklvl = $this->blklvl;
20950 $save_blk = $this->blk;
20951 $save_silp = $this->saveInlineProperties();
20952 $save_ilp = $this->InlineProperties;
20953 $save_bflp = $this->InlineBDF;
20954 $save_bflpc = $this->InlineBDFctr; // mPDF 6
20955
20956 // mPDF 6 pagebreaktype
20957 $startpage = $this->page;
20958 $pagebreaktype = $this->defaultPagebreakType;
20959 if ($this->ColActive) { $pagebreaktype = 'cloneall'; }
20960
20961 // mPDF 6 pagebreaktype
20962 $this->_preForcedPagebreak($pagebreaktype);
20963
20964 if ($page_break_after == 'RIGHT') { $this->AddPage($this->CurOrientation,'NEXT-ODD','','','','','', '','', '','','','','','',0,0,0,0); }
20965 else if ($page_break_after == 'LEFT') { $this->AddPage($this->CurOrientation,'NEXT-EVEN','','','','','', '','', '','','','','','',0,0,0,0); }
20966 else { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0); }
20967
20968 // mPDF 6 pagebreaktype
20969 $this->_postForcedPagebreak($pagebreaktype, $startpage, $save_blk, $save_blklvl);
20970
20971 $this->InlineProperties = $save_ilp;
20972 $this->InlineBDF = $save_bflp;
20973 $this->InlineBDFctr = $save_bflpc; // mPDF 6
20974 $this->restoreInlineProperties($save_silp);
20975
20976 }
20977 }
20978 /*-- END TABLES --*/
20979
20980 }
20981
20982
20983 /*-- TABLES --*/
20984 // This function determines the shrink factor when resizing tables
20985 // val is the table_height / page_height_available
20986 // returns a scaling factor used as $shrin_k to resize the table
20987 // Overcompensating will be quicker but may unnecessarily shrink table too much
20988 // Undercompensating means it will reiterate more times (taking more processing time)
20989 function tbsqrt($val, $iteration=3) {
20990 $k = 4; // Alters number of iterations until it returns $val itself - Must be > 2
20991 // Probably best guess and most accurate
20992 if ($iteration==1) return sqrt($val);
20993 // Faster than using sqrt (because it won't undercompensate), and gives reasonable results
20994 //return 1+(($val-1)/2);
20995 $x = 2-(($iteration-2)/($k-2));
20996 if ($x == 0) { $ret = $val+0.00001; }
20997 else if ($x < 0) { $ret = 1 + ( pow(2, ($iteration-2-$k))/1000 ); }
20998 else { $ret = 1+(($val-1)/$x); }
20999 return $ret;
21000 }
21001 /*-- END TABLES --*/
21002
21003
21004
21005 function _saveTextBuffer($t, $link = '', $intlink = '', $return=false) { // mPDF 6 Lists
21006 $arr = array();
21007 $arr[0] = $t;
21008 if (isset($link) && $link) $arr[1] = $link;
21009 $arr[2] = $this->currentfontstyle;
21010 if (isset($this->colorarray) && $this->colorarray) $arr[3] = $this->colorarray;
21011 $arr[4] = $this->currentfontfamily;
21012 $arr[5] = $this->currentLang; // mPDF 6
21013 if (isset($intlink) && $intlink) $arr[7] = $intlink;
21014 // mPDF 6
21015 // If Kerning set for OTL, and useOTL has positive value, but has not set for this particular script,
21016 // set for kerning via kern table
21017 // e.g. Latin script when useOTL set as 0x80
21018 if (isset($this->OTLtags['Plus']) && strpos($this->OTLtags['Plus'],'kern')!==false && empty($this->OTLdata['GPOSinfo'])) {
21019 $this->textvar = ($this->textvar | FC_KERNING);
21020 }
21021 $arr[8] = $this->textvar; // mPDF 5.7.1
21022 if (isset($this->textparam) && $this->textparam) $arr[9] = $this->textparam;
21023 if (isset($this->spanbgcolorarray) && $this->spanbgcolorarray) $arr[10] = $this->spanbgcolorarray;
21024 $arr[11] = $this->currentfontsize;
21025 if (isset($this->ReqFontStyle) && $this->ReqFontStyle) $arr[12] = $this->ReqFontStyle;
21026 if (isset($this->lSpacingCSS) && $this->lSpacingCSS) $arr[14] = $this->lSpacingCSS;
21027 if (isset($this->wSpacingCSS) && $this->wSpacingCSS) $arr[15] = $this->wSpacingCSS;
21028 if (isset($this->spanborddet) && $this->spanborddet) $arr[16] = $this->spanborddet;
21029 if (isset($this->textshadow) && $this->textshadow) $arr[17] = $this->textshadow;
21030 if (isset($this->OTLdata) && $this->OTLdata) { $arr[18] = $this->OTLdata; $this->OTLdata = array(); } // mPDF 5.7.1
21031 else { $arr[18] = NULL; }
21032 // mPDF 6 Lists
21033 if ($return) { return ($arr); }
21034 if ($this->listitem) {
21035 $this->textbuffer[] = $this->listitem;
21036 $this->listitem = array();
21037 }
21038 $this->textbuffer[] = $arr;
21039 }
21040
21041 function _saveCellTextBuffer($t, $link = '', $intlink = '') {
21042 $arr = array();
21043 $arr[0] = $t;
21044 if (isset($link) && $link) $arr[1] = $link;
21045 $arr[2] = $this->currentfontstyle;
21046 if (isset($this->colorarray) && $this->colorarray) $arr[3] = $this->colorarray;
21047 $arr[4] = $this->currentfontfamily;
21048 if (isset($intlink) && $intlink) $arr[7] = $intlink;
21049 // mPDF 6
21050 // If Kerning set for OTL, and useOTL has positive value, but has not set for this particular script,
21051 // set for kerning via kern table
21052 // e.g. Latin script when useOTL set as 0x80
21053 if (isset($this->OTLtags['Plus']) && strpos($this->OTLtags['Plus'],'kern')!==false && empty($this->OTLdata['GPOSinfo'])) {
21054 $this->textvar = ($this->textvar | FC_KERNING);
21055 }
21056 $arr[8] = $this->textvar; // mPDF 5.7.1
21057 if (isset($this->textparam) && $this->textparam) $arr[9] = $this->textparam;
21058 if (isset($this->spanbgcolorarray) && $this->spanbgcolorarray) $arr[10] = $this->spanbgcolorarray;
21059 $arr[11] = $this->currentfontsize;
21060 if (isset($this->ReqFontStyle) && $this->ReqFontStyle) $arr[12] = $this->ReqFontStyle;
21061 if (isset($this->lSpacingCSS) && $this->lSpacingCSS) $arr[14] = $this->lSpacingCSS;
21062 if (isset($this->wSpacingCSS) && $this->wSpacingCSS) $arr[15] = $this->wSpacingCSS;
21063 if (isset($this->spanborddet) && $this->spanborddet) $arr[16] = $this->spanborddet;
21064 if (isset($this->textshadow) && $this->textshadow) $arr[17] = $this->textshadow;
21065 if (isset($this->OTLdata) && $this->OTLdata) { $arr[18] = $this->OTLdata; $this->OTLdata = array(); } // mPDF 5.7.1
21066 else { $arr[18] = NULL; }
21067 $this->cell[$this->row][$this->col]['textbuffer'][] = $arr;
21068 }
21069
21070
21071
21072 function printbuffer($arrayaux,$blockstate=0,$is_table=false,$table_draft=false,$cell_dir='') {
21073 // $blockstate = 0; // NO margins/padding
21074 // $blockstate = 1; // Top margins/padding only
21075 // $blockstate = 2; // Bottom margins/padding only
21076 // $blockstate = 3; // Top & bottom margins/padding
21077 $this->spanbgcolorarray = '';
21078 $this->spanbgcolor = false;
21079 $this->spanborder = false;
21080 $this->spanborddet = array();
21081 $paint_ht_corr = 0;
21082 /*-- CSS-FLOAT --*/
21083 if (count($this->floatDivs)) {
21084 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
21085 if (($this->blk[$this->blklvl]['inner_width']-$l_width-$r_width) < (2*$this->GetCharWidth('W',false))) {
21086 // Too narrow to fit - try to move down past L or R float
21087 if ($l_max < $r_max && ($this->blk[$this->blklvl]['inner_width']-$r_width) > (2*$this->GetCharWidth('W',false))) {
21088 $this->ClearFloats('LEFT', $this->blklvl);
21089 }
21090 else if ($r_max < $l_max && ($this->blk[$this->blklvl]['inner_width']-$l_width) > (2*$this->GetCharWidth('W',false))) {
21091 $this->ClearFloats('RIGHT', $this->blklvl);
21092 }
21093 else { $this->ClearFloats('BOTH', $this->blklvl); }
21094 }
21095 }
21096 /*-- END CSS-FLOAT --*/
21097 $bak_y = $this->y;
21098 $bak_x = $this->x;
21099 $align = '';
21100 if (!$is_table) {
21101 if (isset($this->blk[$this->blklvl]['align']) && $this->blk[$this->blklvl]['align']) { $align = $this->blk[$this->blklvl]['align']; }
21102 // Block-align is set by e.g. <.. align="center"> Takes priority for this block but not inherited
21103 if (isset($this->blk[$this->blklvl]['block-align']) && $this->blk[$this->blklvl]['block-align']) { $align = $this->blk[$this->blklvl]['block-align']; }
21104 if (isset($this->blk[$this->blklvl]['direction'])) $blockdir = $this->blk[$this->blklvl]['direction'];
21105 else $blockdir = "";
21106 $this->divwidth = $this->blk[$this->blklvl]['width'];
21107 }
21108 else {
21109 $align = $this->cellTextAlign;
21110 $blockdir = $cell_dir;
21111 }
21112 $oldpage = $this->page;
21113
21114 // ADDED for Out of Block now done as Flowing Block
21115 if ($this->divwidth == 0) {
21116 $this->divwidth = $this->pgwidth;
21117 }
21118
21119 if (!$is_table) { $this->SetLineHeight($this->FontSizePt,$this->blk[$this->blklvl]['line_height']); }
21120 $this->divheight = $this->lineheight;
21121 $old_height = $this->divheight;
21122
21123 // As a failsafe - if font has been set but not output to page
21124 if (!$table_draft) $this->SetFont($this->default_font,'',$this->default_font_size,true,true); // force output to page
21125
21126 $this->newFlowingBlock( $this->divwidth,$this->divheight,$align,$is_table,$blockstate,true,$blockdir,$table_draft);
21127
21128 $array_size = count($arrayaux);
21129
21130 // Added - Otherwise <div><div><p> did not output top margins/padding for 1st/2nd div
21131 if ($array_size == 0) { $this->finishFlowingBlock(true); } // true = END of flowing block
21132
21133 // mPDF 6
21134 // ALL the chunks of textbuffer need to have at least basic OTLdata set
21135 // First make sure each element/chunk has the OTLdata for Bidi set.
21136 for($i=0;$i < $array_size; $i++) {
21137 if (empty($arrayaux[$i][18])) {
21138 if (substr($arrayaux[$i][0],0,3) == "\xbb\xa4\xac") { // object identifier has been identified!
21139 $unicode = array(0xFFFC); // Object replacement character
21140 }
21141 else { $unicode = $this->UTF8StringToArray($arrayaux[$i][0], false); }
21142 $is_strong = false;
21143 $this->getBasicOTLdata($arrayaux[$i][18], $unicode, $is_strong);
21144 }
21145 // Gets messed up if try and use core fonts inside a paragraph of text which needs to be BiDi re-ordered or OTLdata set
21146 if (($blockdir == 'rtl' || $this->biDirectional) && isset($arrayaux[$i][4]) && in_array($arrayaux[$i][4],array('ccourier','ctimes','chelvetica','csymbol','czapfdingbats'))) {
21147 $this->Error("You cannot use core fonts in a document which contains RTL text.");
21148 }
21149 }
21150 // mPDF 6
21151 // Process bidirectional text ready for bidi-re-ordering (which is done after line-breaks are established in WriteFlowingBlock etc.)
21152 if (($blockdir == 'rtl' || $this->biDirectional) && !$table_draft) {
21153 if (!class_exists('otl', false)) { include(_MPDF_PATH.'classes/otl.php'); }
21154 if (empty($this->otl)) { $this->otl = new otl($this); }
21155 $this->otl->_bidiPrepare($arrayaux, $blockdir);
21156 $array_size = count($arrayaux);
21157 }
21158
21159
21160 // Remove empty items // mPDF 6
21161 for($i=$array_size-1; $i > 0; $i--) {
21162 if (empty($arrayaux[$i][0]) && $arrayaux[$i][16]!=='0' && empty($arrayaux[$i][7])) {
21163 unset($arrayaux[$i]);
21164 }
21165 }
21166
21167 // Correct adjoining borders for inline elements
21168 if (isset($arrayaux[0][16])) { $lastspanborder = $arrayaux[0][16]; }
21169 else { $lastspanborder = false; }
21170 for($i=1;$i < $array_size; $i++) {
21171 if (isset($arrayaux[$i][16]) && $arrayaux[$i][16]==$lastspanborder &&
21172 ((!isset($arrayaux[$i][9]['bord-decoration']) && !isset($arrayaux[$i-1][9]['bord-decoration'])) ||
21173 (isset($arrayaux[$i][9]['bord-decoration']) && isset($arrayaux[$i-1][9]['bord-decoration']) && $arrayaux[$i][9]['bord-decoration'] == $arrayaux[$i-1][9]['bord-decoration'])
21174 )
21175 ) {
21176 if (isset($arrayaux[$i][16]['R'])) { $lastspanborder = $arrayaux[$i][16]; }
21177 else { $lastspanborder = false; }
21178 $arrayaux[$i][16]['L']['s'] = 0;
21179 $arrayaux[$i][16]['L']['w'] = 0;
21180 $arrayaux[$i-1][16]['R']['s'] = 0;
21181 $arrayaux[$i-1][16]['R']['w'] = 0;
21182 }
21183 else {
21184 if (isset($arrayaux[$i][16]['R'])) { $lastspanborder = $arrayaux[$i][16]; }
21185 else { $lastspanborder = false; }
21186 }
21187 }
21188
21189 for($i=0;$i < $array_size; $i++)
21190 {
21191 // COLS
21192 $oldcolumn = $this->CurrCol;
21193 $vetor = $arrayaux[$i];
21194 if ($i == 0 and $vetor[0] != "\n" and !$this->ispre) {
21195 $vetor[0] = ltrim($vetor[0]);
21196 if (!empty($vetor[18])) { $this->otl->trimOTLdata($vetor[18], true, false); } // *OTL*
21197 }
21198
21199 // FIXED TO ALLOW IT TO SHOW '0'
21200 if (empty($vetor[0]) && !($vetor[0]==='0') && empty($vetor[7])) { //Ignore empty text and not carrying an internal link
21201 //Check if it is the last element. If so then finish printing the block
21202 if ($i == ($array_size-1)) { $this->finishFlowingBlock(true); } // true = END of flowing block
21203 continue;
21204 }
21205
21206
21207 //Activating buffer properties
21208 if(isset($vetor[11]) and $vetor[11] != '') { // Font Size
21209 if ($is_table && $this->shrin_k) {
21210 $this->SetFontSize($vetor[11]/$this->shrin_k,false);
21211 }
21212 else {
21213 $this->SetFontSize($vetor[11],false);
21214 }
21215 }
21216
21217 if(isset($vetor[17]) && !empty($vetor[17])) { //TextShadow
21218 $this->textshadow = $vetor[17];
21219 }
21220 if(isset($vetor[16]) && !empty($vetor[16])) { //Border
21221 $this->spanborddet = $vetor[16];
21222 $this->spanborder = true;
21223 }
21224
21225 if(isset($vetor[15])) { // Word spacing
21226 $this->wSpacingCSS = $vetor[15];
21227 if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') {
21228 $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize)/$this->shrin_k; // mPDF 5.7.3
21229 }
21230 }
21231 if(isset($vetor[14])) { // Letter spacing
21232 $this->lSpacingCSS = $vetor[14];
21233 if (($this->lSpacingCSS || $this->lSpacingCSS==='0') && strtoupper($this->lSpacingCSS) != 'NORMAL') {
21234 $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize)/$this->shrin_k; // mPDF 5.7.3
21235 }
21236 }
21237
21238
21239 if(isset($vetor[10]) and !empty($vetor[10])) //Background color
21240 {
21241 $this->spanbgcolorarray = $vetor[10];
21242 $this->spanbgcolor = true;
21243 }
21244 if(isset($vetor[9]) and !empty($vetor[9])) // Text parameters - Outline + hyphens
21245 {
21246 $this->textparam = $vetor[9] ;
21247 $this->SetTextOutline($this->textparam);
21248 // mPDF 5.7.3 inline text-decoration parameters
21249 if ($is_table && $this->shrin_k) {
21250 if (isset($this->textparam['text-baseline'])) { $this->textparam['text-baseline'] /= $this->shrin_k; }
21251 if (isset($this->textparam['decoration-baseline'])) { $this->textparam['decoration-baseline'] /= $this->shrin_k; }
21252 if (isset($this->textparam['decoration-fontsize'])) { $this->textparam['decoration-fontsize'] /= $this->shrin_k; }
21253 }
21254
21255 }
21256 if(isset($vetor[8])) // mPDF 5.7.1
21257 {
21258 $this->textvar = $vetor[8];
21259 }
21260 if(isset($vetor[7]) and $vetor[7] != '') // internal target: <a name="anyvalue">
21261 {
21262 $ily = $this->y;
21263 if ($this->table_rotate) { $this->internallink[$vetor[7]] = array("Y"=>$ily,"PAGE"=>$this->page, "tbrot"=>true ); }
21264 else if ($this->kwt) { $this->internallink[$vetor[7]] = array("Y"=>$ily,"PAGE"=>$this->page, "kwt"=>true ); }
21265 else if ($this->ColActive) { $this->internallink[$vetor[7]] = array("Y"=>$ily,"PAGE"=>$this->page, "col"=>$this->CurrCol ); }
21266 else if (!$this->keep_block_together) { $this->internallink[$vetor[7]] = array("Y"=>$ily,"PAGE"=>$this->page ); }
21267 if (empty($vetor[0])) { //Ignore empty text
21268 //Check if it is the last element. If so then finish printing the block
21269 if ($i == ($array_size-1)) { $this->finishFlowingBlock(true); } // true = END of flowing block
21270 continue;
21271 }
21272 }
21273 if(isset($vetor[5]) and $vetor[5] != '') { // Language // mPDF 6
21274 $this->currentLang = $vetor[5];
21275 }
21276 if(isset($vetor[4]) and $vetor[4] != '') { // Font Family
21277 $font = $this->SetFont($vetor[4],$this->FontStyle,0,false);
21278 }
21279 if (!empty($vetor[3])) //Font Color
21280 {
21281 $cor = $vetor[3];
21282 $this->SetTColor($cor);
21283 }
21284 if(isset($vetor[2]) and $vetor[2] != '') //Bold,Italic styles
21285 {
21286 $this->SetStyles($vetor[2]);
21287 }
21288
21289 if(isset($vetor[12]) and $vetor[12] != '') { //Requested Bold,Italic
21290 $this->ReqFontStyle = $vetor[12];
21291 }
21292 if(isset($vetor[1]) and $vetor[1] != '') //LINK
21293 {
21294 if (strpos($vetor[1],".") === false && strpos($vetor[1],"@") !== 0) //assuming every external link has a dot indicating extension (e.g: .html .txt .zip www.somewhere.com etc.)
21295 {
21296 //Repeated reference to same anchor?
21297 while(array_key_exists($vetor[1],$this->internallink)) $vetor[1]="#".$vetor[1];
21298 $this->internallink[$vetor[1]] = $this->AddLink();
21299 $vetor[1] = $this->internallink[$vetor[1]];
21300 }
21301 $this->HREF = $vetor[1]; // HREF link style set here ******
21302 }
21303
21304 // SPECIAL CONTENT - IMAGES & FORM OBJECTS
21305 //Print-out special content
21306
21307 if (substr($vetor[0],0,3) == "\xbb\xa4\xac") { //identifier has been identified!
21308
21309 $objattr = $this->_getObjAttr($vetor[0]);
21310
21311 /*-- TABLES --*/
21312 if ($objattr['type'] == 'nestedtable') {
21313 if ($objattr['nestedcontent']) {
21314 $level = $objattr['level'];
21315 $table = &$this->table[$level][$objattr['table']];
21316
21317 if ($table_draft) {
21318 $this->y += $this->table[($level+1)][$objattr['nestedcontent']]['h']; // nested table height
21319 $this->finishFlowingBlock(false,'nestedtable');
21320 }
21321 else {
21322
21323 $cell = &$table['cells'][$objattr['row']][$objattr['col']];
21324 $this->finishFlowingBlock(false,'nestedtable');
21325 $save_dw = $this->divwidth ;
21326 $save_buffer = $this->cellBorderBuffer;
21327 $this->cellBorderBuffer = array();
21328 $ncx = $this->x;
21329 list($dummyx,$w) = $this->_tableGetWidth($table, $objattr['row'], $objattr['col']);
21330 $ntw = $this->table[($level+1)][$objattr['nestedcontent']]['w']; // nested table width
21331 if (!$this->simpleTables){
21332 if ($this->packTableData) {
21333 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($cell['borderbin']);
21334 }
21335 else {
21336 $br = $cell['border_details']['R']['w'];
21337 $bl = $cell['border_details']['L']['w'];
21338 }
21339 if ($table['borders_separate']) {
21340 $innerw = $w - $bl - $br - $cell['padding']['L'] - $cell['padding']['R'] - $table['border_spacing_H'];
21341 }
21342 else {
21343 $innerw = $w - $bl/2 - $br/2 - $cell['padding']['L'] - $cell['padding']['R'];
21344 }
21345 }
21346 else if ($this->simpleTables){
21347 if ($table['borders_separate']) {
21348 $innerw = $w - $table['simple']['border_details']['L']['w'] - $table['simple']['border_details']['R']['w'] - $cell['padding']['L'] - $cell['padding']['R'] - $table['border_spacing_H'];
21349 }
21350 else {
21351 $innerw = $w - $table['simple']['border_details']['L']['w']/2 - $table['simple']['border_details']['R']['w']/2 - $cell['padding']['L'] - $cell['padding']['R'];
21352 }
21353 }
21354 if ($cell['a']=='C' || $this->table[($level+1)][$objattr['nestedcontent']]['a']=='C') {
21355 $ncx += ($innerw-$ntw)/2;
21356 }
21357 elseif ($cell['a']=='R' || $this->table[($level+1)][$objattr['nestedcontent']]['a']=='R') {
21358 $ncx += $innerw- $ntw;
21359 }
21360 $this->x = $ncx ;
21361
21362 $this->_tableWrite($this->table[($level+1)][$objattr['nestedcontent']]);
21363 $this->cellBorderBuffer = $save_buffer;
21364 $this->x = $bak_x ;
21365 $this->divwidth = $save_dw;
21366
21367 }
21368
21369 $this->newFlowingBlock( $this->divwidth,$this->divheight,$align,$is_table,$blockstate,false,$blockdir,$table_draft);
21370 }
21371 }
21372 else {
21373 /*-- END TABLES --*/
21374 if ($is_table) { // *TABLES*
21375 $maxWidth = $this->divwidth; // *TABLES*
21376 } // *TABLES*
21377 else { // *TABLES*
21378 $maxWidth = $this->divwidth - ($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']);
21379 } // *TABLES*
21380
21381 /*-- CSS-IMAGE-FLOAT --*/
21382 // If float (already) exists at this level
21383 if (isset($this->floatmargins['R']) && $this->y <= $this->floatmargins['R']['y1'] && $this->y >= $this->floatmargins['R']['y0']) { $maxWidth -= $this->floatmargins['R']['w']; }
21384 if (isset($this->floatmargins['L']) && $this->y <= $this->floatmargins['L']['y1'] && $this->y >= $this->floatmargins['L']['y0']) { $maxWidth -= $this->floatmargins['L']['w']; }
21385 /*-- END CSS-IMAGE-FLOAT --*/
21386
21387 list($skipln) = $this->inlineObject($objattr['type'], '', $this->y, $objattr,$this->lMargin, ($this->flowingBlockAttr['contentWidth']/_MPDFK), $maxWidth, $this->flowingBlockAttr['height'], false, $is_table);
21388 // 1 -> New line needed because of width
21389 // -1 -> Will fit width on line but NEW PAGE REQUIRED because of height
21390 // -2 -> Will not fit on line therefore needs new line but thus NEW PAGE REQUIRED
21391 $iby = $this->y;
21392 $oldpage = $this->page;
21393 $oldcol = $this->CurrCol;
21394 if (($skipln == 1 || $skipln == -2) && !isset($objattr['float'])) {
21395 $this->finishFlowingBlock(false,$objattr['type']);
21396 $this->newFlowingBlock( $this->divwidth,$this->divheight,$align,$is_table,$blockstate,false,$blockdir,$table_draft);
21397 }
21398
21399 if (!$table_draft) {
21400 $thispage = $this->page;
21401 if ($this->CurrCol!=$oldcol) { $changedcol = true; }
21402 else { $changedcol=false; }
21403
21404 // the previous lines can already have triggered page break or column change
21405 if (!$changedcol && $skipln <0 && $this->AcceptPageBreak() && $thispage==$oldpage) {
21406
21407 $this->AddPage($this->CurOrientation);
21408
21409 // Added to correct Images already set on line before page advanced
21410 // i.e. if second inline image on line is higher than first and forces new page
21411 if (count($this->objectbuffer)) {
21412 $yadj = $iby - $this->y;
21413 foreach($this->objectbuffer AS $ib=>$val) {
21414 if ($this->objectbuffer[$ib]['OUTER-Y'] ) $this->objectbuffer[$ib]['OUTER-Y'] -= $yadj;
21415 if ($this->objectbuffer[$ib]['BORDER-Y']) $this->objectbuffer[$ib]['BORDER-Y'] -= $yadj;
21416 if ($this->objectbuffer[$ib]['INNER-Y']) $this->objectbuffer[$ib]['INNER-Y'] -= $yadj;
21417 }
21418 }
21419 }
21420
21421 // Added to correct for OddEven Margins
21422 if ($this->page != $oldpage) {
21423 if (($this->page-$oldpage) % 2 == 1) {
21424 $bak_x += $this->MarginCorrection;
21425 }
21426 $oldpage = $this->page;
21427 $y = $this->tMargin - $paint_ht_corr ;
21428 $this->oldy = $this->tMargin - $paint_ht_corr ;
21429 $old_height = 0;
21430 }
21431 $this->x = $bak_x;
21432 /*-- COLUMNS --*/
21433 // COLS
21434 // OR COLUMN CHANGE
21435 if ($this->CurrCol != $oldcolumn) {
21436 if ($this->directionality == 'rtl') { // *OTL*
21437 $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap); // *OTL*
21438 } // *OTL*
21439 else { // *OTL*
21440 $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap);
21441 } // *OTL*
21442 $this->x = $bak_x;
21443 $oldcolumn = $this->CurrCol;
21444 $y = $this->y0 - $paint_ht_corr ;
21445 $this->oldy = $this->y0 - $paint_ht_corr ;
21446 $old_height = 0;
21447 }
21448 /*-- END COLUMNS --*/
21449
21450 }
21451
21452 /*-- CSS-IMAGE-FLOAT --*/
21453 if ($objattr['type'] == 'image' && isset($objattr['float'])) {
21454 $fy = $this->y;
21455
21456 // DIV TOP MARGIN/BORDER/PADDING
21457 if ($this->flowingBlockAttr['newblock'] && ($this->flowingBlockAttr['blockstate']==1 || $this->flowingBlockAttr['blockstate']==3) && $this->flowingBlockAttr['lineCount']== 0) {
21458 $fy += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
21459 }
21460
21461 if ($objattr['float']=='R') {
21462 $fx = $this->w - $this->rMargin - $objattr['width'] - ($this->blk[$this->blklvl]['outer_right_margin'] + $this->blk[$this->blklvl]['border_right']['w'] + $this->blk[$this->blklvl]['padding_right']);
21463
21464
21465 }
21466 else if ($objattr['float']=='L') {
21467 $fx = $this->lMargin + ($this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_left']);
21468 }
21469 $w = $objattr['width'];
21470 $h = abs($objattr['height']);
21471
21472 $widthLeft = $maxWidth - ($this->flowingBlockAttr['contentWidth']/_MPDFK);
21473 $maxHeight = $this->h - ($this->tMargin + $this->margin_header + $this->bMargin + 10) ;
21474 // For Images
21475 $extraWidth = ($objattr['border_left']['w'] + $objattr['border_right']['w'] + $objattr['margin_left']+ $objattr['margin_right']);
21476 $extraHeight = ($objattr['border_top']['w'] + $objattr['border_bottom']['w'] + $objattr['margin_top']+ $objattr['margin_bottom']);
21477
21478 if ($objattr['itype'] == 'wmf' || $objattr['itype'] == 'svg') {
21479 $file = $objattr['file'];
21480 $info=$this->formobjects[$file];
21481 }
21482 else {
21483 $file = $objattr['file'];
21484 $info=$this->images[$file];
21485 }
21486 $img_w = $w - $extraWidth ;
21487 $img_h = $h - $extraHeight ;
21488 if ($objattr['border_left']['w']) {
21489 $objattr['BORDER-WIDTH'] = $img_w + (($objattr['border_left']['w'] + $objattr['border_right']['w'])/2) ;
21490 $objattr['BORDER-HEIGHT'] = $img_h + (($objattr['border_top']['w'] + $objattr['border_bottom']['w'])/2) ;
21491 $objattr['BORDER-X'] = $fx + $objattr['margin_left'] + (($objattr['border_left']['w'])/2) ;
21492 $objattr['BORDER-Y'] = $fy + $objattr['margin_top'] + (($objattr['border_top']['w'])/2) ;
21493 }
21494 $objattr['INNER-WIDTH'] = $img_w;
21495 $objattr['INNER-HEIGHT'] = $img_h;
21496 $objattr['INNER-X'] = $fx + $objattr['margin_left'] + ($objattr['border_left']['w']);
21497 $objattr['INNER-Y'] = $fy + $objattr['margin_top'] + ($objattr['border_top']['w']) ;
21498 $objattr['ID'] = $info['i'];
21499 $objattr['OUTER-WIDTH'] = $w;
21500 $objattr['OUTER-HEIGHT'] = $h;
21501 $objattr['OUTER-X'] = $fx;
21502 $objattr['OUTER-Y'] = $fy;
21503 if ($objattr['float']=='R') {
21504 // If R float already exists at this level
21505 $this->floatmargins['R']['skipline'] = false;
21506 if (isset($this->floatmargins['R']['y1']) && $this->floatmargins['R']['y1'] > 0 && $fy < $this->floatmargins['R']['y1']) {
21507 $this->WriteFlowingBlock($vetor[0],$vetor[18]); // mPDF 5.7.1
21508 }
21509 // If L float already exists at this level
21510 else if (isset($this->floatmargins['L']['y1']) && $this->floatmargins['L']['y1'] > 0 && $fy < $this->floatmargins['L']['y1']) {
21511 // Final check distance between floats is not now too narrow to fit text
21512 $mw = 2*$this->GetCharWidth('W',false);
21513 if (($this->blk[$this->blklvl]['inner_width'] - $w - $this->floatmargins['L']['w']) < $mw) {
21514 $this->WriteFlowingBlock($vetor[0],$vetor[18]); // mPDF 5.7.1
21515 }
21516 else {
21517 $this->floatmargins['R']['x'] = $fx;
21518 $this->floatmargins['R']['w'] = $w;
21519 $this->floatmargins['R']['y0'] = $fy;
21520 $this->floatmargins['R']['y1'] = $fy + $h;
21521 if ($skipln == 1) {
21522 $this->floatmargins['R']['skipline'] = true;
21523 $this->floatmargins['R']['id'] = count($this->floatbuffer)+0;
21524 $objattr['skipline'] = true;
21525 }
21526 $this->floatbuffer[] = $objattr;
21527 }
21528 }
21529 else {
21530 $this->floatmargins['R']['x'] = $fx;
21531 $this->floatmargins['R']['w'] = $w;
21532 $this->floatmargins['R']['y0'] = $fy;
21533 $this->floatmargins['R']['y1'] = $fy + $h;
21534 if ($skipln == 1) {
21535 $this->floatmargins['R']['skipline'] = true;
21536 $this->floatmargins['R']['id'] = count($this->floatbuffer)+0;
21537 $objattr['skipline'] = true;
21538 }
21539 $this->floatbuffer[] = $objattr;
21540 }
21541 }
21542 else if ($objattr['float']=='L') {
21543 // If L float already exists at this level
21544 $this->floatmargins['L']['skipline'] = false;
21545 if (isset($this->floatmargins['L']['y1']) && $this->floatmargins['L']['y1'] > 0 && $fy < $this->floatmargins['L']['y1']) {
21546 $this->floatmargins['L']['skipline'] = false;
21547 $this->WriteFlowingBlock($vetor[0],$vetor[18]); // mPDF 5.7.1
21548 }
21549 // If R float already exists at this level
21550 else if (isset($this->floatmargins['R']['y1']) && $this->floatmargins['R']['y1'] > 0 && $fy < $this->floatmargins['R']['y1']) {
21551 // Final check distance between floats is not now too narrow to fit text
21552 $mw = 2*$this->GetCharWidth('W',false);
21553 if (($this->blk[$this->blklvl]['inner_width'] - $w - $this->floatmargins['R']['w']) < $mw) {
21554 $this->WriteFlowingBlock($vetor[0],$vetor[18]); // mPDF 5.7.1
21555 }
21556 else {
21557 $this->floatmargins['L']['x'] = $fx + $w;
21558 $this->floatmargins['L']['w'] = $w;
21559 $this->floatmargins['L']['y0'] = $fy;
21560 $this->floatmargins['L']['y1'] = $fy + $h;
21561 if ($skipln == 1) {
21562 $this->floatmargins['L']['skipline'] = true;
21563 $this->floatmargins['L']['id'] = count($this->floatbuffer)+0;
21564 $objattr['skipline'] = true;
21565 }
21566 $this->floatbuffer[] = $objattr;
21567 }
21568 }
21569 else {
21570 $this->floatmargins['L']['x'] = $fx + $w;
21571 $this->floatmargins['L']['w'] = $w;
21572 $this->floatmargins['L']['y0'] = $fy;
21573 $this->floatmargins['L']['y1'] = $fy + $h;
21574 if ($skipln == 1) {
21575 $this->floatmargins['L']['skipline'] = true;
21576 $this->floatmargins['L']['id'] = count($this->floatbuffer)+0;
21577 $objattr['skipline'] = true;
21578 }
21579 $this->floatbuffer[] = $objattr;
21580 }
21581 }
21582 }
21583 else {
21584 /*-- END CSS-IMAGE-FLOAT --*/
21585 $this->WriteFlowingBlock($vetor[0],(isset($vetor[18]) ? $vetor[18] : NULL)); // mPDF 5.7.1
21586 /*-- CSS-IMAGE-FLOAT --*/
21587 }
21588 /*-- END CSS-IMAGE-FLOAT --*/
21589 } // *TABLES*
21590
21591 } // END If special content
21592 else { //THE text
21593 if ($this->tableLevel) { $paint_ht_corr = 0; } // To move the y up when new column/page started if div border needed
21594 else { $paint_ht_corr = $this->blk[$this->blklvl]['border_top']['w']; }
21595
21596 if ($vetor[0] == "\n") { //We are reading a <BR> now turned into newline ("\n")
21597 if ($this->flowingBlockAttr['content']) {
21598 $this->finishFlowingBlock(false,'br');
21599 }
21600 else if ($is_table) {
21601 $this->y+= $this->_computeLineheight($this->cellLineHeight);
21602 }
21603 else if (!$is_table) {
21604 $this->DivLn($this->lineheight);
21605 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
21606 }
21607 // Added to correct for OddEven Margins
21608 if ($this->page != $oldpage) {
21609 if (($this->page-$oldpage) % 2 == 1) {
21610 $bak_x += $this->MarginCorrection;
21611 }
21612 $oldpage = $this->page;
21613 $y = $this->tMargin - $paint_ht_corr ;
21614 $this->oldy = $this->tMargin - $paint_ht_corr ;
21615 $old_height = 0;
21616 }
21617 $this->x = $bak_x;
21618 /*-- COLUMNS --*/
21619 // COLS
21620 // OR COLUMN CHANGE
21621 if ($this->CurrCol != $oldcolumn) {
21622 if ($this->directionality == 'rtl') { // *OTL*
21623 $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap); // *OTL*
21624 } // *OTL*
21625 else { // *OTL*
21626 $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap);
21627 } // *OTL*
21628 $this->x = $bak_x;
21629 $oldcolumn = $this->CurrCol;
21630 $y = $this->y0 - $paint_ht_corr ;
21631 $this->oldy = $this->y0 - $paint_ht_corr ;
21632 $old_height = 0;
21633 }
21634 /*-- END COLUMNS --*/
21635 $this->newFlowingBlock( $this->divwidth,$this->divheight,$align,$is_table,$blockstate,false,$blockdir,$table_draft);
21636 }
21637 else {
21638 $this->WriteFlowingBlock($vetor[0],$vetor[18]); // mPDF 5.7.1
21639
21640 // Added to correct for OddEven Margins
21641 if ($this->page != $oldpage) {
21642 if (($this->page-$oldpage) % 2 == 1) {
21643 $bak_x += $this->MarginCorrection;
21644 $this->x = $bak_x;
21645 }
21646 $oldpage = $this->page;
21647 $y = $this->tMargin - $paint_ht_corr ;
21648 $this->oldy = $this->tMargin - $paint_ht_corr ;
21649 $old_height = 0;
21650 }
21651 /*-- COLUMNS --*/
21652 // COLS
21653 // OR COLUMN CHANGE
21654 if ($this->CurrCol != $oldcolumn) {
21655 if ($this->directionality == 'rtl') { // *OTL*
21656 $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap); // *OTL*
21657 } // *OTL*
21658 else { // *OTL*
21659 $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap);
21660 } // *OTL*
21661 $this->x = $bak_x;
21662 $oldcolumn = $this->CurrCol;
21663 $y = $this->y0 - $paint_ht_corr ;
21664 $this->oldy = $this->y0 - $paint_ht_corr ;
21665 $old_height = 0;
21666 }
21667 /*-- END COLUMNS --*/
21668 }
21669
21670
21671 }
21672
21673 //Check if it is the last element. If so then finish printing the block
21674 if ($i == ($array_size-1)) {
21675 $this->finishFlowingBlock(true); // true = END of flowing block
21676 // Added to correct for OddEven Margins
21677 if ($this->page != $oldpage) {
21678 if (($this->page-$oldpage) % 2 == 1) {
21679 $bak_x += $this->MarginCorrection;
21680 $this->x = $bak_x;
21681 }
21682 $oldpage = $this->page;
21683 $y = $this->tMargin - $paint_ht_corr ;
21684 $this->oldy = $this->tMargin - $paint_ht_corr ;
21685 $old_height = 0;
21686 }
21687
21688 /*-- COLUMNS --*/
21689 // COLS
21690 // OR COLUMN CHANGE
21691 if ($this->CurrCol != $oldcolumn) {
21692 if ($this->directionality == 'rtl') { // *OTL*
21693 $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap); // *OTL*
21694 } // *OTL*
21695 else { // *OTL*
21696 $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap);
21697 } // *OTL*
21698 $this->x = $bak_x;
21699 $oldcolumn = $this->CurrCol;
21700 $y = $this->y0 - $paint_ht_corr ;
21701 $this->oldy = $this->y0 - $paint_ht_corr ;
21702 $old_height = 0;
21703 }
21704 /*-- END COLUMNS --*/
21705
21706 }
21707
21708 // RESETTING VALUES
21709 $this->SetTColor($this->ConvertColor(0));
21710 $this->SetDColor($this->ConvertColor(0));
21711 $this->SetFColor($this->ConvertColor(255));
21712 $this->colorarray = '';
21713 $this->spanbgcolorarray = '';
21714 $this->spanbgcolor = false;
21715 $this->spanborder = false;
21716 $this->spanborddet = array();
21717 $this->HREF = '';
21718 $this->textparam = array();
21719 $this->SetTextOutline();
21720
21721 $this->textvar = 0x00; // mPDF 5.7.1
21722 $this->OTLtags = array();
21723 $this->textshadow = '';
21724
21725 $this->currentfontfamily = '';
21726 $this->currentfontsize = '';
21727 $this->currentfontstyle = '';
21728 $this->currentLang = $this->default_lang; // mPDF 6
21729 $this->RestrictUnicodeFonts($this->default_available_fonts ); // mPDF 6
21730 /*-- TABLES --*/
21731 if ($this->tableLevel) {
21732 $this->SetLineHeight('',$this->table[1][1]['cellLineHeight']); // *TABLES*
21733 }
21734 else
21735 /*-- END TABLES --*/
21736 if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) {
21737 $this->SetLineHeight('',$this->blk[$this->blklvl]['line_height']); // sets default line height
21738 }
21739 $this->ResetStyles();
21740 $this->lSpacingCSS = '';
21741 $this->wSpacingCSS = '';
21742 $this->fixedlSpacing = false;
21743 $this->minwSpacing = 0;
21744 $this->SetDash();
21745 $this->dash_on = false;
21746 $this->dotted_on = false;
21747
21748 }//end of for(i=0;i<arraysize;i++)
21749
21750 $this->Reset(); // mPDF 6
21751
21752 // PAINT DIV BORDER // DISABLED IN COLUMNS AS DOESN'T WORK WHEN BROKEN ACROSS COLS??
21753 if ((isset($this->blk[$this->blklvl]['border']) || isset($this->blk[$this->blklvl]['bgcolor']) || isset($this->blk[$this->blklvl]['box_shadow'])) && $blockstate && ($this->y != $this->oldy)) {
21754 $bottom_y = $this->y; // Does not include Bottom Margin
21755 if (isset($this->blk[$this->blklvl]['startpage']) && $this->blk[$this->blklvl]['startpage'] != $this->page && $blockstate != 1) {
21756 $this->PaintDivBB('pagetop',$blockstate);
21757 }
21758
21759 else if ($blockstate != 1) {
21760 $this->PaintDivBB('',$blockstate);
21761 }
21762 $this->y = $bottom_y;
21763 $this->x = $bak_x;
21764 }
21765
21766 // Reset Font
21767 $this->SetFontSize($this->default_font_size,false);
21768 if ($table_draft) {
21769 $ch = $this->y - $bak_y;
21770 $this->y = $bak_y;
21771 $this->x = $bak_x;
21772 return $ch;
21773 }
21774
21775 }
21776
21777 function _setDashBorder($style, $div, $cp, $side) {
21778 if ($style == 'dashed' && (($side=='L' || $side=='R') || ($side=='T' && $div != 'pagetop' && !$cp) || ($side=='B' && $div!='pagebottom') )) {
21779 $dashsize = 2; // final dash will be this + 1*linewidth
21780 $dashsizek = 1.5; // ratio of Dash/Blank
21781 $this->SetDash($dashsize,($dashsize/$dashsizek)+($this->LineWidth*2));
21782 }
21783 else if ($style == 'dotted' || ($side=='T' && ($div == 'pagetop' || $cp)) || ($side=='B' && $div == 'pagebottom')) {
21784 //Round join and cap
21785 $this->SetLineJoin(1);
21786 $this->SetLineCap(1);
21787 $this->SetDash(0.001,($this->LineWidth*3));
21788 }
21789 }
21790
21791 function _setBorderLine($b, $k=1) {
21792 $this->SetLineWidth($b['w']/$k);
21793 $this->SetDColor($b['c']);
21794 if ($b['c'][0]==5) { // RGBa
21795 $this->SetAlpha(ord($b['c'][4])/100, 'Normal', false, 'S')."\n"; // mPDF 5.7.2
21796 }
21797 else if ($b['c'][0]==6) { // CMYKa
21798 $this->SetAlpha(ord($b['c'][5])/100, 'Normal', false, 'S')."\n"; // mPDF 5.7.2
21799 }
21800 }
21801
21802 function PaintDivBB($divider='',$blockstate=0,$blvl=0) {
21803 // Borders & backgrounds are done elsewhere for columns - messes up the repositioning in printcolumnbuffer
21804 if ($this->ColActive) { return ; } // *COLUMNS*
21805 if ($this->keep_block_together ) { return ; } // mPDF 6
21806 $save_y = $this->y;
21807 if (!$blvl) { $blvl = $this->blklvl; }
21808 $x0 = $x1 = $y0 = $y1 = 0;
21809
21810 // Added mPDF 3.0 Float DIV
21811 if (isset($this->blk[$blvl]['bb_painted'][$this->page]) && $this->blk[$blvl]['bb_painted'][$this->page]) { return; } // *CSS-FLOAT*
21812
21813 if (isset($this->blk[$blvl]['x0'])) { $x0 = $this->blk[$blvl]['x0']; } // left
21814 if (isset($this->blk[$blvl]['y1'])) { $y1 = $this->blk[$blvl]['y1']; } // bottom
21815
21816 // Added mPDF 3.0 Float DIV - ensures backgrounds/borders are drawn to bottom of page
21817 if ($y1==0) {
21818 if ($divider=='pagebottom') { $y1 = $this->h-$this->bMargin; }
21819 else { $y1 = $this->y; }
21820 }
21821
21822 if (isset($this->blk[$blvl]['startpage']) && $this->blk[$blvl]['startpage'] != $this->page) { $continuingpage = true; } else { $continuingpage = false; }
21823
21824 if (isset($this->blk[$blvl]['y0'])) { $y0 = $this->blk[$blvl]['y0']; }
21825 $h = $y1 - $y0;
21826 $w = $this->blk[$blvl]['width'];
21827 $x1 = $x0 + $w;
21828
21829 // Set border-widths as used here
21830 $border_top = $this->blk[$blvl]['border_top']['w'];
21831 $border_bottom = $this->blk[$blvl]['border_bottom']['w'];
21832 $border_left = $this->blk[$blvl]['border_left']['w'];
21833 $border_right = $this->blk[$blvl]['border_right']['w'];
21834 if (!$this->blk[$blvl]['border_top'] || $divider == 'pagetop' || $continuingpage) {
21835 $border_top = 0;
21836 }
21837 if (!$this->blk[$blvl]['border_bottom'] || $blockstate == 1 || $divider == 'pagebottom') {
21838 $border_bottom = 0;
21839 }
21840
21841 $brTL_H = 0;
21842 $brTL_V = 0;
21843 $brTR_H = 0;
21844 $brTR_V = 0;
21845 $brBL_H = 0;
21846 $brBL_V = 0;
21847 $brBR_H = 0;
21848 $brBR_V = 0;
21849
21850 $brset = false;
21851 /*-- BORDER-RADIUS --*/
21852 if (isset($this->blk[$blvl]['border_radius_TL_H'])) { $brTL_H = $this->blk[$blvl]['border_radius_TL_H']; $brset = true; }
21853 if (isset($this->blk[$blvl]['border_radius_TL_V'])) { $brTL_V = $this->blk[$blvl]['border_radius_TL_V']; $brset = true; }
21854 if (isset($this->blk[$blvl]['border_radius_TR_H'])) { $brTR_H = $this->blk[$blvl]['border_radius_TR_H']; $brset = true; }
21855 if (isset($this->blk[$blvl]['border_radius_TR_V'])) { $brTR_V = $this->blk[$blvl]['border_radius_TR_V']; $brset = true; }
21856 if (isset($this->blk[$blvl]['border_radius_BR_H'])) { $brBR_H = $this->blk[$blvl]['border_radius_BR_H']; $brset = true; }
21857 if (isset($this->blk[$blvl]['border_radius_BR_V'])) { $brBR_V = $this->blk[$blvl]['border_radius_BR_V']; $brset = true; }
21858 if (isset($this->blk[$blvl]['border_radius_BL_H'])) { $brBL_H = $this->blk[$blvl]['border_radius_BL_H']; $brset = true; }
21859 if (isset($this->blk[$blvl]['border_radius_BL_V'])) { $brBL_V = $this->blk[$blvl]['border_radius_BL_V']; $brset = true; }
21860
21861 if (!$this->blk[$blvl]['border_top'] || $divider == 'pagetop' || $continuingpage) {
21862 $brTL_H = 0;
21863 $brTL_V = 0;
21864 $brTR_H = 0;
21865 $brTR_V = 0;
21866 }
21867 if (!$this->blk[$blvl]['border_bottom'] || $blockstate == 1 || $divider == 'pagebottom') {
21868 $brBL_H = 0;
21869 $brBL_V = 0;
21870 $brBR_H = 0;
21871 $brBR_V = 0;
21872 }
21873
21874 // Disallow border-radius if it is smaller than the border width.
21875 if ($brTL_H < min($border_left, $border_top)) { $brTL_H = $brTL_V = 0; }
21876 if ($brTL_V < min($border_left, $border_top)) { $brTL_V = $brTL_H = 0; }
21877 if ($brTR_H < min($border_right, $border_top)) { $brTR_H = $brTR_V = 0; }
21878 if ($brTR_V < min($border_right, $border_top)) { $brTR_V = $brTR_H = 0; }
21879 if ($brBL_H < min($border_left, $border_bottom)) { $brBL_H = $brBL_V = 0; }
21880 if ($brBL_V < min($border_left, $border_bottom)) { $brBL_V = $brBL_H = 0; }
21881 if ($brBR_H < min($border_right, $border_bottom)) { $brBR_H = $brBR_V = 0; }
21882 if ($brBR_V < min($border_right, $border_bottom)) { $brBR_V = $brBR_H = 0; }
21883
21884 // CHECK FOR radii that sum to > width or height of div ********
21885 $f = min($h/($brTL_V + $brBL_V + 0.001), $h/($brTR_V + $brBR_V + 0.001), $w/($brTL_H + $brTR_H + 0.001), $w/($brBL_H + $brBR_H + 0.001));
21886 if ($f < 1) {
21887 $brTL_H *= $f;
21888 $brTL_V *= $f;
21889 $brTR_H *= $f;
21890 $brTR_V *= $f;
21891 $brBL_H *= $f;
21892 $brBL_V *= $f;
21893 $brBR_H *= $f;
21894 $brBR_V *= $f;
21895 }
21896 /*-- END BORDER-RADIUS --*/
21897
21898 $tbcol = $this->ConvertColor(255);
21899 for($l=0; $l <= $blvl; $l++) {
21900 if ($this->blk[$l]['bgcolor']) {
21901 $tbcol = $this->blk[$l]['bgcolorarray'];
21902 }
21903 }
21904
21905 // BORDERS
21906 if (isset($this->blk[$blvl]['y0']) && $this->blk[$blvl]['y0']) { $y0 = $this->blk[$blvl]['y0']; }
21907 $h = $y1 - $y0;
21908 $w = $this->blk[$blvl]['width'];
21909
21910 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
21911 $tbd = $this->blk[$blvl]['border_top'];
21912
21913 $legend = '';
21914 $legbreakL = 0;
21915 $legbreakR = 0;
21916 // BORDER LEGEND
21917 if (isset($this->blk[$blvl]['border_legend']) && $this->blk[$blvl]['border_legend']) {
21918 $legend = $this->blk[$blvl]['border_legend']; // Same structure array as textbuffer
21919 $txt = $legend[0] = ltrim($legend[0]);
21920 if (!empty($legend[18])) { $this->otl->trimOTLdata($legend[18], true, false); } // *OTL*
21921
21922 //Set font, size, style, color
21923 $this->SetFont($legend[4],$legend[2],$legend[11]);
21924 if (isset($legend[3]) && $legend[3]) {
21925 $cor = $legend[3];
21926 $this->SetTColor($cor);
21927
21928 }
21929 $stringWidth = $this->GetStringWidth($txt, true, $legend[18], $legend[8]);
21930 $save_x = $this->x;
21931 $save_y = $this->y;
21932 $save_currentfontfamily = $this->FontFamily;
21933 $save_currentfontsize = $this->FontSizePt;
21934 $save_currentfontstyle = $this->FontStyle;
21935 $this->y = $y0 - $this->FontSize/2 + $this->blk[$blvl]['border_top']['w']/2;
21936 $this->x = $x0 + $this->blk[$blvl]['padding_left'] + $this->blk[$blvl]['border_left']['w'];
21937
21938 // Set the distance from the border line to the text ? make configurable variable
21939 $gap = 0.2 * $this->FontSize;
21940 $legbreakL = $this->x - $gap;
21941 $legbreakR = $this->x + $stringWidth + $gap;
21942 $this->magic_reverse_dir($txt, $this->blk[$blvl]['direction'], $legend[18]);
21943 $fill = '';
21944 $this->Cell( $stringWidth, $this->FontSize, $txt , '', 0, 'C', $fill, '', 0, 0,0,'M', $fill, false, $legend[18], $legend[8]);
21945 // Reset
21946 $this->x = $save_x;
21947 $this->y = $save_y;
21948 $this->SetFont($save_currentfontfamily,$save_currentfontstyle,$save_currentfontsize);
21949 $this->SetTColor($this->ConvertColor(0));
21950 }
21951
21952 if (isset($tbd['s']) && $tbd['s']) {
21953 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') {
21954 $this->_out('q');
21955 $this->SetLineWidth(0);
21956 $this->_out(sprintf('%.3F %.3F m ',($x0)*_MPDFK, ($this->h-($y0))*_MPDFK));
21957 $this->_out(sprintf('%.3F %.3F l ',($x0 + $border_left)*_MPDFK, ($this->h-($y0 + $border_top))*_MPDFK));
21958 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w - $border_right)*_MPDFK, ($this->h-($y0 + $border_top))*_MPDFK));
21959 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w)*_MPDFK, ($this->h-($y0))*_MPDFK));
21960 $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
21961 }
21962
21963 $this->_setBorderLine($tbd);
21964 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') {
21965 $legbreakL -= $border_top/2; // because line cap different
21966 $legbreakR += $border_top/2;
21967 $this->_setDashBorder($tbd['style'],$divider,$continuingpage,'T');
21968 }
21969 /*-- BORDER-RADIUS --*/
21970 else if (($brTL_V && $brTL_H) || ($brTR_V && $brTR_H) || $tbd['style']=='solid' || $tbd['style']=='double' ) {
21971 $this->SetLineJoin(0);
21972 $this->SetLineCap(0);
21973 }
21974 $s = '';
21975 if ($brTR_H && $brTR_V) {
21976 $s .= ($this->_EllipseArc($x0 + $w - $brTR_H, $y0 + $brTR_V, $brTR_H - $border_top/2 , $brTR_V - $border_top/2 , 1, 2, true))."\n";
21977 }
21978 else
21979 /*-- END BORDER-RADIUS --*/
21980 if ($tbd['style']=='solid' || $tbd['style']=='double') {
21981 $s .= (sprintf('%.3F %.3F m ',($x0 + $w)*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
21982 }
21983 else {
21984 $s .= (sprintf('%.3F %.3F m ',($x0 + $w - ($border_top/2))*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
21985 }
21986 /*-- BORDER-RADIUS --*/
21987 if ($brTL_H && $brTL_V ) {
21988 if ($legend) {
21989 if ($legbreakR < ($x0 + $w - $brTR_H)) {
21990 $s .= (sprintf('%.3F %.3F l ', $legbreakR*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
21991 }
21992 if ($legbreakL > ($x0 + $brTL_H )) {
21993 $s .= (sprintf('%.3F %.3F m ',$legbreakL*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
21994 $s .= (sprintf('%.3F %.3F l ',($x0 + $brTL_H )*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK)."\n");
21995 }
21996 else {
21997 $s .= (sprintf('%.3F %.3F m ',($x0 + $brTL_H )*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
21998 }
21999 }
22000 else {
22001 $s .= (sprintf('%.3F %.3F l ',($x0 + $brTL_H )*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
22002 }
22003 $s .= ($this->_EllipseArc($x0 + $brTL_H, $y0 + $brTL_V, $brTL_H - $border_top/2 , $brTL_V - $border_top/2 , 2, 1))."\n";
22004 }
22005 else {
22006 /*-- END BORDER-RADIUS --*/
22007 if ($legend) {
22008 if ($legbreakR < ($x0 + $w)) {
22009 $s .= (sprintf('%.3F %.3F l ',$legbreakR*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
22010 }
22011 if ($legbreakL > ($x0)) {
22012 $s .= (sprintf('%.3F %.3F m ',$legbreakL*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
22013 if ($tbd['style']=='solid' || $tbd['style']=='double') {
22014 $s .= (sprintf('%.3F %.3F l ',($x0)*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
22015 }
22016 else {
22017 $s .= (sprintf('%.3F %.3F l ',($x0 + ($border_top/2))*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
22018 }
22019 }
22020 else if ($tbd['style']=='solid' || $tbd['style']=='double') {
22021 $s .= (sprintf('%.3F %.3F m ', ($x0)*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
22022 }
22023 else {
22024 $s .= (sprintf('%.3F %.3F m ', ($x0 + $border_top/2)*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
22025 }
22026 }
22027 else if ($tbd['style']=='solid' || $tbd['style']=='double') {
22028 $s .= (sprintf('%.3F %.3F l ',($x0)*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
22029 }
22030 else {
22031 $s .= (sprintf('%.3F %.3F l ',($x0 + ($border_top/2))*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
22032 }
22033 /*-- BORDER-RADIUS --*/
22034 }
22035 /*-- END BORDER-RADIUS --*/
22036 $s .= 'S'."\n";
22037 $this->_out($s);
22038
22039 if ($tbd['style']=='double') {
22040 $this->SetLineWidth($tbd['w']/3);
22041 $this->SetDColor($tbcol);
22042 $this->_out($s);
22043 }
22044 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') { $this->_out('Q'); }
22045
22046 // Reset Corners and Dash off
22047 $this->SetLineWidth(0.1);
22048 $this->SetDColor($this->ConvertColor(0));
22049 $this->SetLineJoin(2);
22050 $this->SetLineCap(2);
22051 $this->SetDash();
22052 }
22053 }
22054 // Reinstate line above for dotted line divider when block border crosses a page
22055 //else if ($divider == 'pagetop' || $continuingpage) {
22056
22057 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
22058 $tbd = $this->blk[$blvl]['border_bottom'];
22059 if (isset($tbd['s']) && $tbd['s']) {
22060 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') {
22061 $this->_out('q');
22062 $this->SetLineWidth(0);
22063 $this->_out(sprintf('%.3F %.3F m ',($x0)*_MPDFK, ($this->h-($y0 + $h))*_MPDFK));
22064 $this->_out(sprintf('%.3F %.3F l ',($x0 + $border_left)*_MPDFK, ($this->h-($y0 + $h - $border_bottom))*_MPDFK));
22065 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w - $border_right)*_MPDFK, ($this->h-($y0 + $h - $border_bottom))*_MPDFK));
22066 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w)*_MPDFK, ($this->h-($y0 + $h))*_MPDFK));
22067 $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
22068 }
22069
22070 $this->_setBorderLine($tbd);
22071 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],$divider,$continuingpage,'B'); }
22072 /*-- BORDER-RADIUS --*/
22073 else if (($brBL_V && $brBL_H) || ($brBR_V && $brBR_H) || $tbd['style']=='solid' || $tbd['style']=='double' ) {
22074 $this->SetLineJoin(0);
22075 $this->SetLineCap(0);
22076 }
22077 $s = '';
22078 if ($brBL_H && $brBL_V) {
22079 $s .= ($this->_EllipseArc($x0 + $brBL_H, $y0 + $h - $brBL_V, $brBL_H - $border_bottom/2 , $brBL_V - $border_bottom/2 , 3, 2, true))."\n";
22080 }
22081 else
22082 /*-- END BORDER-RADIUS --*/
22083 if ($tbd['style']=='solid' || $tbd['style']=='double') {
22084 $s .= (sprintf('%.3F %.3F m ',($x0)*_MPDFK, ($this->h-($y0 + $h - ($border_bottom/2)))*_MPDFK))."\n";
22085 }
22086 else {
22087 $s .= (sprintf('%.3F %.3F m ',($x0 + ($border_bottom/2))*_MPDFK, ($this->h-($y0 + $h - ($border_bottom/2)))*_MPDFK))."\n";
22088 }
22089 /*-- BORDER-RADIUS --*/
22090 if ($brBR_H && $brBR_V ) {
22091 $s .= (sprintf('%.3F %.3F l ',($x0 + $w - ($border_bottom/2) - $brBR_H )*_MPDFK, ($this->h-($y0 + $h - ($border_bottom/2)))*_MPDFK))."\n";
22092 $s .= ($this->_EllipseArc($x0 + $w - $brBR_H, $y0 + $h - $brBR_V, $brBR_H - $border_bottom/2 , $brBR_V - $border_bottom/2 , 4, 1))."\n";
22093 }
22094 else
22095 /*-- END BORDER-RADIUS --*/
22096 if ($tbd['style']=='solid' || $tbd['style']=='double') {
22097 $s .= (sprintf('%.3F %.3F l ',($x0 + $w)*_MPDFK, ($this->h-($y0 + $h - ($border_bottom/2)))*_MPDFK))."\n";
22098 }
22099 else {
22100 $s .= (sprintf('%.3F %.3F l ',($x0 + $w - ($border_bottom/2))*_MPDFK, ($this->h-($y0 + $h - ($border_bottom/2)))*_MPDFK))."\n";
22101 }
22102 $s .= 'S'."\n";
22103 $this->_out($s);
22104
22105 if ($tbd['style']=='double') {
22106 $this->SetLineWidth($tbd['w']/3);
22107 $this->SetDColor($tbcol);
22108 $this->_out($s);
22109 }
22110 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') { $this->_out('Q'); }
22111
22112
22113 // Reset Corners and Dash off
22114 $this->SetLineWidth(0.1);
22115 $this->SetDColor($this->ConvertColor(0));
22116 $this->SetLineJoin(2);
22117 $this->SetLineCap(2);
22118 $this->SetDash();
22119 }
22120 }
22121 // Reinstate line below for dotted line divider when block border crosses a page
22122 //else if ($blockstate == 1 || $divider == 'pagebottom') {
22123
22124 if ($this->blk[$blvl]['border_left']) {
22125 $tbd = $this->blk[$blvl]['border_left'];
22126 if (isset($tbd['s']) && $tbd['s']) {
22127 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') {
22128 $this->_out('q');
22129 $this->SetLineWidth(0);
22130 $this->_out(sprintf('%.3F %.3F m ',($x0)*_MPDFK, ($this->h-($y0))*_MPDFK));
22131 $this->_out(sprintf('%.3F %.3F l ',($x0 + $border_left)*_MPDFK, ($this->h-($y0+$border_top))*_MPDFK));
22132 $this->_out(sprintf('%.3F %.3F l ',($x0 + $border_left)*_MPDFK, ($this->h-($y0 + $h - $border_bottom))*_MPDFK));
22133 $this->_out(sprintf('%.3F %.3F l ',($x0)*_MPDFK, ($this->h-($y0 + $h))*_MPDFK));
22134 $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
22135 }
22136
22137 $this->_setBorderLine($tbd);
22138 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],$divider,$continuingpage,'L'); }
22139 /*-- BORDER-RADIUS --*/
22140 else if (($brTL_V && $brTL_H) || ($brBL_V && $brBL_H) || $tbd['style']=='solid' || $tbd['style']=='double' ) {
22141 $this->SetLineJoin(0);
22142 $this->SetLineCap(0);
22143 }
22144 $s = '';
22145 if ($brTL_V && $brTL_H) {
22146 $s .= ($this->_EllipseArc($x0 + $brTL_H, $y0 + $brTL_V, $brTL_H - $border_left/2 , $brTL_V - $border_left/2, 2, 2, true))."\n";
22147 }
22148 else
22149 /*-- END BORDER-RADIUS --*/
22150 if ($tbd['style']=='solid' || $tbd['style']=='double') {
22151 $s .= (sprintf('%.3F %.3F m ',($x0 + ($border_left/2))*_MPDFK, ($this->h-($y0))*_MPDFK))."\n";
22152 }
22153 else {
22154 $s .= (sprintf('%.3F %.3F m ',($x0 + ($border_left/2))*_MPDFK, ($this->h-($y0 + ($border_left/2)))*_MPDFK))."\n";
22155 }
22156 /*-- BORDER-RADIUS --*/
22157 if ($brBL_V && $brBL_H ) {
22158 $s .= (sprintf('%.3F %.3F l ',($x0 + ($border_left/2))*_MPDFK, ($this->h-($y0 + $h - ($border_left/2)- $brBL_V) )*_MPDFK))."\n";
22159 $s .= ($this->_EllipseArc($x0 + $brBL_H, $y0 + $h - $brBL_V, $brBL_H - $border_left/2 , $brBL_V - $border_left/2, 3, 1))."\n";
22160 }
22161 else
22162 /*-- END BORDER-RADIUS --*/
22163 if ($tbd['style']=='solid' || $tbd['style']=='double') {
22164 $s .= (sprintf('%.3F %.3F l ',($x0 + ($border_left/2))*_MPDFK, ($this->h-($y0 + $h) )*_MPDFK))."\n";
22165 }
22166 else {
22167 $s .= (sprintf('%.3F %.3F l ',($x0 + ($border_left/2))*_MPDFK, ($this->h-($y0 + $h - ($border_left/2)) )*_MPDFK))."\n";
22168 }
22169 $s .= 'S'."\n";
22170 $this->_out($s);
22171
22172 if ($tbd['style']=='double') {
22173 $this->SetLineWidth($tbd['w']/3);
22174 $this->SetDColor($tbcol);
22175 $this->_out($s);
22176 }
22177 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') { $this->_out('Q'); }
22178
22179 // Reset Corners and Dash off
22180 $this->SetLineWidth(0.1);
22181 $this->SetDColor($this->ConvertColor(0));
22182 $this->SetLineJoin(2);
22183 $this->SetLineCap(2);
22184 $this->SetDash();
22185 }
22186 }
22187 if ($this->blk[$blvl]['border_right']) {
22188 $tbd = $this->blk[$blvl]['border_right'];
22189 if (isset($tbd['s']) && $tbd['s']) {
22190 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') {
22191 $this->_out('q');
22192 $this->SetLineWidth(0);
22193 $this->_out(sprintf('%.3F %.3F m ',($x0 + $w)*_MPDFK, ($this->h-($y0))*_MPDFK));
22194 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w - $border_right)*_MPDFK, ($this->h-($y0+$border_top))*_MPDFK));
22195 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w - $border_right)*_MPDFK, ($this->h-($y0 + $h - $border_bottom))*_MPDFK));
22196 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w)*_MPDFK, ($this->h-($y0 + $h))*_MPDFK));
22197 $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
22198 }
22199
22200 $this->_setBorderLine($tbd);
22201 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],$divider,$continuingpage,'R'); }
22202 /*-- BORDER-RADIUS --*/
22203 else if (($brTR_V && $brTR_H) || ($brBR_V && $brBR_H) || $tbd['style']=='solid' || $tbd['style']=='double' ) {
22204 $this->SetLineJoin(0);
22205 $this->SetLineCap(0);
22206 }
22207 $s = '';
22208 if ($brBR_V && $brBR_H) {
22209 $s .= ($this->_EllipseArc($x0 + $w - $brBR_H, $y0 + $h - $brBR_V, $brBR_H - $border_right/2 , $brBR_V - $border_right/2, 4, 2, true))."\n";
22210 }
22211 else
22212 /*-- END BORDER-RADIUS --*/
22213 if ($tbd['style']=='solid' || $tbd['style']=='double') {
22214 $s .= (sprintf('%.3F %.3F m ',($x0 + $w - ($border_right/2))*_MPDFK, ($this->h-($y0 + $h))*_MPDFK))."\n";
22215 }
22216 else {
22217 $s .= (sprintf('%.3F %.3F m ',($x0 + $w - ($border_right/2))*_MPDFK, ($this->h-($y0 + $h - ($border_right/2)))*_MPDFK))."\n";
22218 }
22219 /*-- BORDER-RADIUS --*/
22220 if ($brTR_V && $brTR_H ) {
22221 $s .= (sprintf('%.3F %.3F l ',($x0 + $w - ($border_right/2))*_MPDFK, ($this->h-($y0 + ($border_right/2) + $brTR_V) )*_MPDFK))."\n";
22222 $s .= ($this->_EllipseArc($x0 + $w - $brTR_H, $y0 + $brTR_V, $brTR_H - $border_right/2 , $brTR_V - $border_right/2, 1, 1))."\n";
22223 }
22224 else
22225 /*-- END BORDER-RADIUS --*/
22226 if ($tbd['style']=='solid' || $tbd['style']=='double') {
22227 $s .= (sprintf('%.3F %.3F l ',($x0 + $w - ($border_right/2))*_MPDFK, ($this->h-($y0) )*_MPDFK))."\n";
22228 }
22229 else {
22230 $s .= (sprintf('%.3F %.3F l ',($x0 + $w - ($border_right/2))*_MPDFK, ($this->h-($y0 + ($border_right/2)) )*_MPDFK))."\n";
22231 }
22232 $s .= 'S'."\n";
22233 $this->_out($s);
22234
22235 if ($tbd['style']=='double') {
22236 $this->SetLineWidth($tbd['w']/3);
22237 $this->SetDColor($tbcol);
22238 $this->_out($s);
22239 }
22240 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') { $this->_out('Q'); }
22241
22242 // Reset Corners and Dash off
22243 $this->SetLineWidth(0.1);
22244 $this->SetDColor($this->ConvertColor(0));
22245 $this->SetLineJoin(2);
22246 $this->SetLineCap(2);
22247 $this->SetDash();
22248 }
22249 }
22250
22251
22252 $this->SetDash();
22253 $this->y = $save_y;
22254
22255
22256 // BACKGROUNDS are disabled in columns/kbt/headers - messes up the repositioning in printcolumnbuffer
22257 if ($this->ColActive || $this->kwt || $this->keep_block_together) { return ; }
22258
22259
22260 $bgx0 = $x0;
22261 $bgx1 = $x1;
22262 $bgy0 = $y0;
22263 $bgy1 = $y1;
22264
22265 // Defined br values represent the radius of the outer curve - need to take border-width/2 from each radius for drawing the borders
22266 if (isset($this->blk[$blvl]['background_clip']) && $this->blk[$blvl]['background_clip'] == 'padding-box') {
22267 $brbgTL_H = max(0, $brTL_H - $this->blk[$blvl]['border_left']['w']);
22268 $brbgTL_V = max(0, $brTL_V - $this->blk[$blvl]['border_top']['w']);
22269 $brbgTR_H = max(0, $brTR_H - $this->blk[$blvl]['border_right']['w']);
22270 $brbgTR_V = max(0, $brTR_V - $this->blk[$blvl]['border_top']['w']);
22271 $brbgBL_H = max(0, $brBL_H - $this->blk[$blvl]['border_left']['w']);
22272 $brbgBL_V = max(0, $brBL_V - $this->blk[$blvl]['border_bottom']['w']);
22273 $brbgBR_H = max(0, $brBR_H - $this->blk[$blvl]['border_right']['w']);
22274 $brbgBR_V = max(0, $brBR_V - $this->blk[$blvl]['border_bottom']['w']);
22275 $bgx0 += $this->blk[$blvl]['border_left']['w'];
22276 $bgx1 -= $this->blk[$blvl]['border_right']['w'];
22277 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
22278 $bgy0 += $this->blk[$blvl]['border_top']['w'];
22279 }
22280 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
22281 $bgy1 -= $this->blk[$blvl]['border_bottom']['w'];
22282 }
22283 }
22284 else if (isset($this->blk[$blvl]['background_clip']) && $this->blk[$blvl]['background_clip'] == 'content-box') {
22285 $brbgTL_H = max(0, $brTL_H - $this->blk[$blvl]['border_left']['w'] - $this->blk[$blvl]['padding_left']);
22286 $brbgTL_V = max(0, $brTL_V - $this->blk[$blvl]['border_top']['w'] - $this->blk[$blvl]['padding_top']);
22287 $brbgTR_H = max(0, $brTR_H - $this->blk[$blvl]['border_right']['w'] - $this->blk[$blvl]['padding_right']);
22288 $brbgTR_V = max(0, $brTR_V - $this->blk[$blvl]['border_top']['w'] - $this->blk[$blvl]['padding_top']);
22289 $brbgBL_H = max(0, $brBL_H - $this->blk[$blvl]['border_left']['w'] - $this->blk[$blvl]['padding_left']);
22290 $brbgBL_V = max(0, $brBL_V - $this->blk[$blvl]['border_bottom']['w'] - $this->blk[$blvl]['padding_bottom']);
22291 $brbgBR_H = max(0, $brBR_H - $this->blk[$blvl]['border_right']['w'] - $this->blk[$blvl]['padding_right']);
22292 $brbgBR_V = max(0, $brBR_V - $this->blk[$blvl]['border_bottom']['w'] - $this->blk[$blvl]['padding_bottom']);
22293 $bgx0 += $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'];
22294 $bgx1 -= $this->blk[$blvl]['border_right']['w'] + $this->blk[$blvl]['padding_right'];
22295 if (($this->blk[$blvl]['border_top']['w'] || $this->blk[$blvl]['padding_top']) && $divider != 'pagetop' && !$continuingpage) {
22296 $bgy0 += $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top'];
22297 }
22298 if (($this->blk[$blvl]['border_bottom']['w'] || $this->blk[$blvl]['padding_bottom']) && $blockstate != 1 && $divider != 'pagebottom') {
22299 $bgy1 -= $this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom'];
22300 }
22301 }
22302 else {
22303 $brbgTL_H = $brTL_H;
22304 $brbgTL_V = $brTL_V;
22305 $brbgTR_H = $brTR_H;
22306 $brbgTR_V = $brTR_V;
22307 $brbgBL_H = $brBL_H;
22308 $brbgBL_V = $brBL_V;
22309 $brbgBR_H = $brBR_H;
22310 $brbgBR_V = $brBR_V;
22311 }
22312
22313 // Set clipping path
22314 $s = ' q 0 w '; // Line width=0
22315 $s .= sprintf('%.3F %.3F m ', ($bgx0+$brbgTL_H )*_MPDFK, ($this->h-$bgy0)*_MPDFK); // start point TL before the arc
22316 /*-- BORDER-RADIUS --*/
22317 if ($brbgTL_H || $brbgTL_V) {
22318 $s .= $this->_EllipseArc($bgx0+$brbgTL_H, $bgy0+$brbgTL_V, $brbgTL_H , $brbgTL_V , 2); // segment 2 TL
22319 }
22320 /*-- END BORDER-RADIUS --*/
22321 $s .= sprintf('%.3F %.3F l ', ($bgx0)*_MPDFK, ($this->h-($bgy1-$brbgBL_V ))*_MPDFK); // line to BL
22322 /*-- BORDER-RADIUS --*/
22323 if ($brbgBL_H || $brbgBL_V) {
22324 $s .= $this->_EllipseArc($bgx0+$brbgBL_H, $bgy1-$brbgBL_V, $brbgBL_H , $brbgBL_V , 3); // segment 3 BL
22325 }
22326 /*-- END BORDER-RADIUS --*/
22327 $s .= sprintf('%.3F %.3F l ', ($bgx1-$brbgBR_H )*_MPDFK, ($this->h-($bgy1))*_MPDFK); // line to BR
22328 /*-- BORDER-RADIUS --*/
22329 if ($brbgBR_H || $brbgBR_V) {
22330 $s .= $this->_EllipseArc($bgx1-$brbgBR_H, $bgy1-$brbgBR_V, $brbgBR_H , $brbgBR_V , 4); // segment 4 BR
22331 }
22332 /*-- END BORDER-RADIUS --*/
22333 $s .= sprintf('%.3F %.3F l ', ($bgx1)*_MPDFK, ($this->h-($bgy0+$brbgTR_V))*_MPDFK); // line to TR
22334 /*-- BORDER-RADIUS --*/
22335 if ($brbgTR_H || $brbgTR_V) {
22336 $s .= $this->_EllipseArc($bgx1-$brbgTR_H, $bgy0+$brbgTR_V, $brbgTR_H , $brbgTR_V , 1); // segment 1 TR
22337 }
22338 /*-- END BORDER-RADIUS --*/
22339 $s .= sprintf('%.3F %.3F l ', ($bgx0+$brbgTL_H )*_MPDFK, ($this->h-$bgy0)*_MPDFK); // line to TL
22340
22341
22342 // Box Shadow
22343 $shadow = '';
22344 if (isset($this->blk[$blvl]['box_shadow']) && $this->blk[$blvl]['box_shadow'] && $h > 0) {
22345 foreach($this->blk[$blvl]['box_shadow'] AS $sh) {
22346 // Colors
22347 if ($sh['col']{0}==1) {
22348 $colspace = 'Gray';
22349 if ($sh['col']{2}==1) { $col1 = '1'.$sh['col'][1].'1'.$sh['col'][3]; }
22350 else { $col1 = '1'.$sh['col'][1].'1'.chr(100); }
22351 $col2 = '1'.$sh['col'][1].'1'.chr(0);
22352 }
22353 else if ($sh['col']{0}==4) { // CMYK
22354 $colspace = 'CMYK';
22355 $col1 = '6'.$sh['col'][1].$sh['col'][2].$sh['col'][3].$sh['col'][4].chr(100);
22356 $col2 = '6'.$sh['col'][1].$sh['col'][2].$sh['col'][3].$sh['col'][4].chr(0);
22357 }
22358 else if ($sh['col']{0}==5) { // RGBa
22359 $colspace = 'RGB';
22360 $col1 = '5'.$sh['col'][1].$sh['col'][2].$sh['col'][3].$sh['col'][4];
22361 $col2 = '5'.$sh['col'][1].$sh['col'][2].$sh['col'][3].chr(0);
22362 }
22363 else if ($sh['col']{0}==6) { // CMYKa
22364 $colspace = 'CMYK';
22365 $col1 = '6'.$sh['col'][1].$sh['col'][2].$sh['col'][3].$sh['col'][4].$sh['col'][5];
22366 $col2 = '6'.$sh['col'][1].$sh['col'][2].$sh['col'][3].$sh['col'][4].chr(0);
22367 }
22368 else {
22369 $colspace = 'RGB';
22370 $col1 = '5'.$sh['col'][1].$sh['col'][2].$sh['col'][3].chr(100);
22371 $col2 = '5'.$sh['col'][1].$sh['col'][2].$sh['col'][3].chr(0);
22372 }
22373
22374 // Use clipping path as set above (and rectangle around page) to clip area outside box
22375 $shadow .= $s; // Use the clipping path with W*
22376 $shadow .= sprintf('0 %.3F m %.3F %.3F l ', $this->h*_MPDFK, $this->w*_MPDFK, $this->h*_MPDFK);
22377 $shadow .= sprintf('%.3F 0 l 0 0 l 0 %.3F l ', $this->w*_MPDFK, $this->h*_MPDFK);
22378 $shadow .= 'W n'."\n";
22379
22380 $sh['blur'] = abs($sh['blur']); // cannot have negative blur value
22381 // Ensure spread/blur do not make effective shadow width/height < 0
22382 // Could do more complex things but this just adjusts spread value
22383 if (-$sh['spread'] + $sh['blur']/2 > min($w/2, $h/2)) {
22384 $sh['spread'] = $sh['blur']/2 - min($w/2, $h/2) + 0.01;
22385 }
22386 // Shadow Offset
22387 if ($sh['x'] || $sh['y']) $shadow .= sprintf(' q 1 0 0 1 %.4F %.4F cm', $sh['x']*_MPDFK, -$sh['y']*_MPDFK)."\n";
22388
22389 // Set path for INNER shadow
22390 $shadow .= ' q 0 w ';
22391 $shadow .= $this->SetFColor($col1, true)."\n";
22392 if ($col1{0}==5 && ord($col1{4})<100) { // RGBa
22393 $shadow .= $this->SetAlpha(ord($col1{4})/100, 'Normal', true, 'F')."\n";
22394 }
22395 else if ($col1{0}==6 && ord($col1{5})<100) { // CMYKa
22396 $shadow .= $this->SetAlpha(ord($col1{5})/100, 'Normal', true, 'F')."\n";
22397 }
22398 else if ($col1{0}==1 && $col1{2}==1 && ord($col1{3})<100) { // Gray
22399 $shadow .= $this->SetAlpha(ord($col1{3})/100, 'Normal', true, 'F')."\n";
22400 }
22401
22402 // Blur edges
22403 $mag = 0.551784; // Bezier Control magic number for 4-part spline for circle/ellipse
22404 $mag2 = 0.551784; // Bezier Control magic number to fill in edge of blurred rectangle
22405 $d1 = $sh['spread']+$sh['blur']/2;
22406 $d2 = $sh['spread']-$sh['blur']/2;
22407 $bl = $sh['blur'];
22408 $x00 = $x0 - $d1;
22409 $y00 = $y0 - $d1;
22410 $w00 = $w + $d1*2;
22411 $h00 = $h + $d1*2;
22412
22413 // If any border-radius is greater width-negative spread(inner edge), ignore radii for shadow or screws up
22414 $flatten = false;
22415 if (max($brbgTR_H, $brbgTL_H, $brbgBR_H, $brbgBL_H) >= $w+$d2) { $flatten = true; }
22416 if (max($brbgTR_V, $brbgTL_V, $brbgBR_V, $brbgBL_V) >= $h+$d2) { $flatten = true; }
22417
22418
22419 // TOP RIGHT corner
22420 $p1x = $x00+$w00-$d1-$brbgTR_H; $p1c2x = $p1x +($d2+$brbgTR_H)*$mag;
22421 $p1y = $y00+$bl;
22422 $p2x = $x00+$w00-$d1-$brbgTR_H; $p2c2x = $p2x + ($d1+$brbgTR_H)*$mag;
22423 $p2y = $y00; $p2c1y = $p2y + $bl/2;
22424 $p3x = $x00+$w00; $p3c2x = $p3x - $bl/2;
22425 $p3y = $y00+$d1+$brbgTR_V; $p3c1y = $p3y - ($d1+$brbgTR_V)*$mag;
22426 $p4x = $x00+$w00-$bl;
22427 $p4y = $y00+$d1+$brbgTR_V; $p4c2y = $p4y - ($d2+$brbgTR_V)*$mag;
22428 if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) {
22429 $p1x = $x00+$w00-$bl; $p1c2x = $p1x;
22430 $p2x = $x00+$w00-$bl; $p2c2x = $p2x + $bl*$mag2;
22431 $p3y = $y00+$bl; $p3c1y = $p3y - $bl*$mag2;
22432 $p4y = $y00+$bl; $p4c2y = $p4y ;
22433 }
22434
22435 $shadow .= sprintf('%.3F %.3F m ', ($p1x )*_MPDFK, ($this->h-($p1y ))*_MPDFK);
22436 $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1c2x)*_MPDFK, ($this->h-($p1y))*_MPDFK, ($p4x)*_MPDFK, ($this->h-($p4c2y))*_MPDFK, ($p4x)*_MPDFK, ($this->h-($p4y))*_MPDFK);
22437 $patch_array[0]['f']=0;
22438 $patch_array[0]['points']=array($p1x,$p1y, $p1x,$p1y,
22439 $p2x,$p2c1y, $p2x,$p2y, $p2c2x,$p2y,
22440 $p3x,$p3c1y, $p3x,$p3y, $p3c2x,$p3y,
22441 $p4x,$p4y, $p4x,$p4y, $p4x,$p4c2y,
22442 $p1c2x,$p1y);
22443 $patch_array[0]['colors'] = array($col1,$col2,$col2,$col1);
22444
22445
22446 // RIGHT
22447 $p1x = $x00+$w00; // control point only matches p3 preceding
22448 $p1y = $y00+$d1+$brbgTR_V;
22449 $p2x = $x00+$w00-$bl; // control point only matches p4 preceding
22450 $p2y = $y00+$d1+$brbgTR_V;
22451 $p3x = $x00+$w00-$bl;
22452 $p3y = $y00+$h00-$d1-$brbgBR_V;
22453 $p4x = $x00+$w00; $p4c1x = $p4x-$bl/2;
22454 $p4y = $y00+$h00-$d1-$brbgBR_V;
22455 if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) {
22456 $p1y = $y00+$bl;
22457 $p2y = $y00+$bl;
22458 }
22459 if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) {
22460 $p3y = $y00+$h00-$bl;
22461 $p4y = $y00+$h00-$bl;
22462 }
22463
22464 $shadow .= sprintf('%.3F %.3F l ', ($p3x )*_MPDFK, ($this->h-($p3y ))*_MPDFK);
22465 $patch_array[1]['f']=2;
22466 $patch_array[1]['points']=array($p2x,$p2y,
22467 $p3x,$p3y, $p3x,$p3y, $p3x,$p3y,
22468 $p4c1x,$p4y, $p4x,$p4y, $p4x,$p4y,
22469 $p1x,$p1y);
22470 $patch_array[1]['colors'] = array($col1,$col2);
22471
22472
22473 // BOTTOM RIGHT corner
22474 $p1x = $x00+$w00-$bl; // control points only matches p3 preceding
22475 $p1y = $y00+$h00-$d1-$brbgBR_V; $p1c2y = $p1y + ($d2+$brbgBR_V)*$mag;
22476 $p2x = $x00+$w00; // control point only matches p4 preceding
22477 $p2y = $y00+$h00-$d1-$brbgBR_V; $p2c2y = $p2y + ($d1+$brbgBR_V)*$mag;
22478 $p3x = $x00+$w00-$d1-$brbgBR_H; $p3c1x = $p3x + ($d1+$brbgBR_H)*$mag;
22479 $p3y = $y00+$h00; $p3c2y = $p3y - $bl/2;
22480 $p4x = $x00+$w00-$d1-$brbgBR_H; $p4c2x = $p4x + ($d2+$brbgBR_H)*$mag;
22481 $p4y = $y00+$h00-$bl;
22482
22483 if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) {
22484 $p1y = $y00+$h00-$bl; $p1c2y = $p1y;
22485 $p2y = $y00+$h00-$bl; $p2c2y = $p2y + $bl*$mag2;
22486 $p3x = $x00+$w00-$bl; $p3c1x = $p3x + $bl*$mag2;
22487 $p4x = $x00+$w00-$bl; $p4c2x = $p4x;
22488 }
22489
22490 $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1x)*_MPDFK, ($this->h-($p1c2y))*_MPDFK, ($p4c2x)*_MPDFK, ($this->h-($p4y))*_MPDFK, ($p4x)*_MPDFK, ($this->h-($p4y))*_MPDFK);
22491 $patch_array[2]['f']=2;
22492 $patch_array[2]['points']=array($p2x,$p2c2y,
22493 $p3c1x,$p3y, $p3x,$p3y, $p3x,$p3c2y,
22494 $p4x,$p4y, $p4x,$p4y, $p4c2x,$p4y,
22495 $p1x,$p1c2y);
22496 $patch_array[2]['colors'] = array($col2,$col1);
22497
22498
22499
22500 // BOTTOM
22501 $p1x = $x00+$w00-$d1-$brbgBR_H; // control point only matches p3 preceding
22502 $p1y = $y00+$h00;
22503 $p2x = $x00+$w00-$d1-$brbgBR_H; // control point only matches p4 preceding
22504 $p2y = $y00+$h00-$bl;
22505 $p3x = $x00+$d1+$brbgBL_H;
22506 $p3y = $y00+$h00-$bl;
22507 $p4x = $x00+$d1+$brbgBL_H;
22508 $p4y = $y00+$h00; $p4c1y = $p4y - $bl/2;
22509
22510 if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) {
22511 $p1x = $x00+$w00-$bl;
22512 $p2x = $x00+$w00-$bl;
22513 }
22514 if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) {
22515 $p3x = $x00+$bl;
22516 $p4x = $x00+$bl;
22517 }
22518
22519 $shadow .= sprintf('%.3F %.3F l ', ($p3x )*_MPDFK, ($this->h-($p3y ))*_MPDFK);
22520 $patch_array[3]['f']=2;
22521 $patch_array[3]['points']=array($p2x,$p2y,
22522 $p3x,$p3y, $p3x,$p3y, $p3x,$p3y,
22523 $p4x,$p4c1y, $p4x,$p4y, $p4x,$p4y,
22524 $p1x,$p1y);
22525 $patch_array[3]['colors'] = array($col1,$col2);
22526
22527 // BOTTOM LEFT corner
22528 $p1x = $x00+$d1+$brbgBL_H; $p1c2x = $p1x - ($d2+$brbgBL_H)*$mag; // control points only matches p3 preceding
22529 $p1y = $y00+$h00-$bl;
22530 $p2x = $x00+$d1+$brbgBL_H; $p2c2x = $p2x - ($d1+$brbgBL_H)*$mag; // control point only matches p4 preceding
22531 $p2y = $y00+$h00;
22532 $p3x = $x00; $p3c2x = $p3x + $bl/2;
22533 $p3y = $y00+$h00-$d1-$brbgBL_V; $p3c1y = $p3y + ($d1+$brbgBL_V)*$mag;
22534 $p4x = $x00+$bl;
22535 $p4y = $y00+$h00-$d1-$brbgBL_V; $p4c2y = $p4y + ($d2+$brbgBL_V)*$mag;
22536 if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) {
22537 $p1x = $x00+$bl; $p1c2x = $p1x;
22538 $p2x = $x00+$bl; $p2c2x = $p2x - $bl*$mag2;
22539 $p3y = $y00+$h00-$bl; $p3c1y = $p3y + $bl*$mag2;
22540 $p4y = $y00+$h00-$bl; $p4c2y = $p4y;
22541 }
22542
22543 $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1c2x)*_MPDFK, ($this->h-($p1y))*_MPDFK, ($p4x)*_MPDFK, ($this->h-($p4c2y))*_MPDFK, ($p4x)*_MPDFK, ($this->h-($p4y))*_MPDFK);
22544 $patch_array[4]['f']=2;
22545 $patch_array[4]['points']=array($p2c2x,$p2y,
22546 $p3x,$p3c1y, $p3x,$p3y, $p3c2x,$p3y,
22547 $p4x,$p4y, $p4x,$p4y, $p4x,$p4c2y,
22548 $p1c2x,$p1y);
22549 $patch_array[4]['colors'] = array($col2,$col1);
22550
22551
22552 // LEFT - joins on the right (C3-C4 of previous): f = 2
22553 $p1x = $x00; // control point only matches p3 preceding
22554 $p1y = $y00+$h00-$d1-$brbgBL_V;
22555 $p2x = $x00+$bl; // control point only matches p4 preceding
22556 $p2y = $y00+$h00-$d1-$brbgBL_V;
22557 $p3x = $x00+$bl;
22558 $p3y = $y00+$d1+$brbgTL_V;
22559 $p4x = $x00; $p4c1x = $p4x + $bl/2;
22560 $p4y = $y00+$d1+$brbgTL_V;
22561 if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) {
22562 $p1y = $y00+$h00-$bl;
22563 $p2y = $y00+$h00-$bl;
22564 }
22565 if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) {
22566 $p3y = $y00+$bl;
22567 $p4y = $y00+$bl;
22568 }
22569
22570 $shadow .= sprintf('%.3F %.3F l ', ($p3x )*_MPDFK, ($this->h-($p3y ))*_MPDFK);
22571 $patch_array[5]['f']=2;
22572 $patch_array[5]['points']=array($p2x,$p2y,
22573 $p3x,$p3y, $p3x,$p3y, $p3x,$p3y,
22574 $p4c1x,$p4y, $p4x,$p4y, $p4x,$p4y,
22575 $p1x,$p1y);
22576 $patch_array[5]['colors'] = array($col1,$col2);
22577
22578 // TOP LEFT corner
22579 $p1x = $x00+$bl; // control points only matches p3 preceding
22580 $p1y = $y00+$d1+$brbgTL_V; $p1c2y = $p1y - ($d2+$brbgTL_V)*$mag;
22581 $p2x = $x00; // control point only matches p4 preceding
22582 $p2y = $y00+$d1+$brbgTL_V; $p2c2y = $p2y - ($d1+$brbgTL_V)*$mag;
22583 $p3x = $x00+$d1+$brbgTL_H; $p3c1x = $p3x - ($d1+$brbgTL_H)*$mag;
22584 $p3y = $y00; $p3c2y = $p3y + $bl/2;
22585 $p4x = $x00+$d1+$brbgTL_H; $p4c2x = $p4x - ($d2+$brbgTL_H)*$mag;
22586 $p4y = $y00+$bl;
22587
22588 if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) {
22589 $p1y = $y00+$bl; $p1c2y = $p1y;
22590 $p2y = $y00+$bl; $p2c2y = $p2y - $bl*$mag2;
22591 $p3x = $x00+$bl; $p3c1x = $p3x - $bl*$mag2;
22592 $p4x = $x00+$bl; $p4c2x = $p4x ;
22593 }
22594
22595 $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1x)*_MPDFK, ($this->h-($p1c2y))*_MPDFK, ($p4c2x)*_MPDFK, ($this->h-($p4y))*_MPDFK, ($p4x)*_MPDFK, ($this->h-($p4y))*_MPDFK);
22596 $patch_array[6]['f']=2;
22597 $patch_array[6]['points']=array($p2x,$p2c2y,
22598 $p3c1x,$p3y, $p3x,$p3y, $p3x,$p3c2y,
22599 $p4x,$p4y, $p4x,$p4y, $p4c2x,$p4y,
22600 $p1x,$p1c2y);
22601 $patch_array[6]['colors'] = array($col2,$col1);
22602
22603
22604 // TOP - joins on the right (C3-C4 of previous): f = 2
22605 $p1x = $x00+$d1+$brbgTL_H; // control point only matches p3 preceding
22606 $p1y = $y00;
22607 $p2x = $x00+$d1+$brbgTL_H; // control point only matches p4 preceding
22608 $p2y = $y00+$bl;
22609 $p3x = $x00+$w00-$d1-$brbgTR_H;
22610 $p3y = $y00+$bl;
22611 $p4x = $x00+$w00-$d1-$brbgTR_H;
22612 $p4y = $y00; $p4c1y = $p4y + $bl/2;
22613 if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) {
22614 $p1x = $x00+$bl;
22615 $p2x = $x00+$bl;
22616 }
22617 if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) {
22618 $p3x = $x00+$w00-$bl;
22619 $p4x = $x00+$w00-$bl;
22620 }
22621
22622 $shadow .= sprintf('%.3F %.3F l ', ($p3x )*_MPDFK, ($this->h-($p3y ))*_MPDFK);
22623 $patch_array[7]['f']=2;
22624 $patch_array[7]['points']=array($p2x,$p2y,
22625 $p3x,$p3y, $p3x,$p3y, $p3x,$p3y,
22626 $p4x,$p4c1y, $p4x,$p4y, $p4x,$p4y,
22627 $p1x,$p1y);
22628 $patch_array[7]['colors'] = array($col1,$col2);
22629
22630 $shadow .= ' h f Q '."\n"; // Close path and Fill the inner solid shadow
22631
22632 if ($bl) $shadow .= $this->grad->CoonsPatchMesh($x00,$y00,$w00,$h00,$patch_array,$x00,$x00+$w00,$y00,$y00+$h00, $colspace, true);
22633
22634 if ($sh['x'] || $sh['y']) $shadow .= ' Q'."\n"; // Shadow Offset
22635 $shadow .= ' Q'."\n"; // Ends path no-op & Sets the clipping path
22636
22637 }
22638 }
22639
22640 $s .= ' W n '; // Ends path no-op & Sets the clipping path
22641
22642 if ($this->blk[$blvl]['bgcolor']) {
22643 $this->pageBackgrounds[$blvl][] = array('x'=>$x0, 'y'=>$y0, 'w'=>$w, 'h'=>$h, 'col'=>$this->blk[$blvl]['bgcolorarray'], 'clippath'=>$s, 'visibility'=>$this->visibility, 'shadow'=>$shadow, 'z-index'=>$this->current_layer);
22644 }
22645 else if ($shadow) {
22646 $this->pageBackgrounds[$blvl][] = array('shadowonly'=>true, 'col'=>'', 'clippath'=>'', 'visibility'=>$this->visibility, 'shadow'=>$shadow, 'z-index'=>$this->current_layer);
22647 }
22648
22649 /*-- BACKGROUNDS --*/
22650 if (isset($this->blk[$blvl]['gradient'])) {
22651 $g = $this->grad->parseBackgroundGradient($this->blk[$blvl]['gradient']);
22652 if ($g) {
22653 $gx = $x0;
22654 $gy = $y0;
22655 $this->pageBackgrounds[$blvl][] = array('gradient'=>true, 'x'=>$gx, 'y'=>$gy, 'w'=>$w, 'h'=>$h, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>$s, 'visibility'=>$this->visibility, 'z-index'=>$this->current_layer);
22656 }
22657 }
22658 if (isset($this->blk[$blvl]['background-image'])) {
22659 if (isset($this->blk[$blvl]['background-image']['gradient']) && $this->blk[$blvl]['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $this->blk[$blvl]['background-image']['gradient'] )) {
22660 $g = $this->grad->parseMozGradient( $this->blk[$blvl]['background-image']['gradient'] );
22661 if ($g) {
22662 $gx = $x0;
22663 $gy = $y0;
22664 // origin specifies the background-positioning-area (bpa)
22665 if ($this->blk[$blvl]['background-image']['origin'] == 'padding-box') {
22666 $gx += $this->blk[$blvl]['border_left']['w'];
22667 $w -= ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['border_right']['w']);
22668 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
22669 $gy += $this->blk[$blvl]['border_top']['w'];
22670 }
22671 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
22672 $gy1 = $y1 - $this->blk[$blvl]['border_bottom']['w'];
22673 }
22674 else { $gy1 = $y1; }
22675 $h = $gy1 - $gy;
22676 }
22677 else if ($this->blk[$blvl]['background-image']['origin'] == 'content-box') {
22678 $gx += $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'];
22679 $w -= ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'] + $this->blk[$blvl]['border_right']['w'] + $this->blk[$blvl]['padding_right']);
22680 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
22681 $gy += $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top'];
22682 }
22683 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
22684 $gy1 = $y1 - ($this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom']);
22685 }
22686 else { $gy1 = $y1 - $this->blk[$blvl]['padding_bottom']; }
22687 $h = $gy1 - $gy;
22688 }
22689
22690 if (isset($this->blk[$blvl]['background-image']['size']['w']) && $this->blk[$blvl]['background-image']['size']['w']) {
22691 $size = $this->blk[$blvl]['background-image']['size'];
22692 if ($size['w']!='contain' && $size['w']!='cover') {
22693 if (stristr($size['w'] ,'%')) {
22694 $size['w'] += 0;
22695 $size['w'] /= 100;
22696 $w *= $size['w'];
22697 }
22698 else if ($size['w']!='auto') {
22699 $w = $size['w'];
22700 }
22701 if (stristr($size['h'] ,'%')) {
22702 $size['h'] += 0;
22703 $size['h'] /= 100;
22704 $h *= $size['h'];
22705 }
22706 else if ($size['h']!='auto') {
22707 $h = $size['h'];
22708 }
22709 }
22710 }
22711 $this->pageBackgrounds[$blvl][] = array('gradient'=>true, 'x'=>$gx, 'y'=>$gy, 'w'=>$w, 'h'=>$h, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>$s, 'visibility'=>$this->visibility, 'z-index'=>$this->current_layer);
22712 }
22713 }
22714 else {
22715 $image_id = $this->blk[$blvl]['background-image']['image_id'];
22716 $orig_w = $this->blk[$blvl]['background-image']['orig_w'];
22717 $orig_h = $this->blk[$blvl]['background-image']['orig_h'];
22718 $x_pos = $this->blk[$blvl]['background-image']['x_pos'];
22719 $y_pos = $this->blk[$blvl]['background-image']['y_pos'];
22720 $x_repeat = $this->blk[$blvl]['background-image']['x_repeat'];
22721 $y_repeat = $this->blk[$blvl]['background-image']['y_repeat'];
22722 $resize = $this->blk[$blvl]['background-image']['resize'];
22723 $opacity = $this->blk[$blvl]['background-image']['opacity'];
22724 $itype = $this->blk[$blvl]['background-image']['itype'];
22725 $size = $this->blk[$blvl]['background-image']['size'];
22726 // origin specifies the background-positioning-area (bpa)
22727 $bpa = array('x'=>$x0, 'y'=>$y0, 'w'=>$w, 'h'=>$h);
22728 if ($this->blk[$blvl]['background-image']['origin'] == 'padding-box') {
22729 $bpa['x'] = $x0 + $this->blk[$blvl]['border_left']['w'];
22730 $bpa['w'] = $w - ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['border_right']['w']);
22731 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
22732 $bpa['y'] = $y0 + $this->blk[$blvl]['border_top']['w'];
22733 }
22734 else { $bpa['y'] = $y0; }
22735 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
22736 $bpay = $y1 - $this->blk[$blvl]['border_bottom']['w'];
22737 }
22738 else { $bpay = $y1; }
22739 $bpa['h'] = $bpay - $bpa['y'];
22740 }
22741 else if ($this->blk[$blvl]['background-image']['origin'] == 'content-box') {
22742 $bpa['x'] = $x0 + $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'];
22743 $bpa['w'] = $w - ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'] + $this->blk[$blvl]['border_right']['w'] + $this->blk[$blvl]['padding_right']);
22744 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
22745 $bpa['y'] = $y0 + $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top'];
22746 }
22747 else { $bpa['y'] = $y0 + $this->blk[$blvl]['padding_top']; }
22748 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
22749 $bpay = $y1 - ($this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom']);
22750 }
22751 else { $bpay = $y1 - $this->blk[$blvl]['padding_bottom']; }
22752 $bpa['h'] = $bpay - $bpa['y'];
22753 }
22754 $this->pageBackgrounds[$blvl][] = array('x'=>$x0, 'y'=>$y0, 'w'=>$w, 'h'=>$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, 'visibility'=>$this->visibility, 'z-index'=>$this->current_layer, 'size'=>$size, 'bpa'=>$bpa );
22755 }
22756 }
22757 /*-- END BACKGROUNDS --*/
22758
22759 // Float DIV
22760 $this->blk[$blvl]['bb_painted'][$this->page] = true;
22761
22762 }
22763
22764 /*-- BORDER-RADIUS --*/
22765
22766 function _EllipseArc($x0, $y0, $rx, $ry, $seg = 1, $part=false, $start=false) { // Anticlockwise segment 1-4 TR-TL-BL-BR (part=1 or 2)
22767 $s = '';
22768 if ($rx<0) { $rx = 0; }
22769 if ($ry<0) { $ry = 0; }
22770 $rx *= _MPDFK;
22771 $ry *= _MPDFK;
22772 $astart = 0;
22773 if ($seg == 1) { // Top Right
22774 $afinish = 90;
22775 $nSeg = 4;
22776 }
22777 else if ($seg == 2) { // Top Left
22778 $afinish = 180;
22779 $nSeg = 8;
22780 }
22781 else if ($seg == 3) { // Bottom Left
22782 $afinish = 270;
22783 $nSeg = 12;
22784 }
22785 else { // Bottom Right
22786 $afinish = 360;
22787 $nSeg = 16;
22788 }
22789 $astart = deg2rad((float) $astart);
22790 $afinish = deg2rad((float) $afinish);
22791 $totalAngle = $afinish - $astart;
22792 $dt = $totalAngle / $nSeg; // segment angle
22793 $dtm = $dt/3;
22794 $x0 *= _MPDFK;
22795 $y0 = ($this->h - $y0) * _MPDFK;
22796 $t1 = $astart;
22797 $a0 = $x0 + ($rx * cos($t1));
22798 $b0 = $y0 + ($ry * sin($t1));
22799 $c0 = -$rx * sin($t1);
22800 $d0 = $ry * cos($t1);
22801 $op = false;
22802 for ($i = 1; $i <= $nSeg; $i++) {
22803 // Draw this bit of the total curve
22804 $t1 = ($i * $dt) + $astart;
22805 $a1 = $x0 + ($rx * cos($t1));
22806 $b1 = $y0 + ($ry * sin($t1));
22807 $c1 = -$rx * sin($t1);
22808 $d1 = $ry * cos($t1);
22809 if ($i>($nSeg-4) && (!$part || ($part == 1 && $i<=$nSeg-2) || ($part == 2 && $i>$nSeg-2))) {
22810 if ($start && !$op) {
22811 $s .= sprintf('%.3F %.3F m ', $a0, $b0);
22812 }
22813 $s .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($a0 + ($c0 * $dtm)), ($b0 + ($d0 * $dtm)), ($a1 - ($c1 * $dtm)) , ($b1 - ($d1 * $dtm)), $a1 , $b1 );
22814 $op = true;
22815 }
22816 $a0 = $a1;
22817 $b0 = $b1;
22818 $c0 = $c1;
22819 $d0 = $d1;
22820 }
22821 return $s;
22822 }
22823 /*-- END BORDER-RADIUS --*/
22824
22825
22826
22827 function PaintDivLnBorder($state=0,$blvl=0,$h) {
22828 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
22829 $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y + $h;
22830
22831 $save_y = $this->y;
22832
22833 $w = $this->blk[$blvl]['width'];
22834 $x0 = $this->x; // left
22835 $y0 = $this->y; // top
22836 $x1 = $this->x + $w; // bottom
22837 $y1 = $this->y + $h; // bottom
22838
22839 if ($this->blk[$blvl]['border_top'] && ($state==1 || $state==3)) {
22840 $tbd = $this->blk[$blvl]['border_top'];
22841 if (isset($tbd['s']) && $tbd['s']) {
22842 $this->_setBorderLine($tbd);
22843 $this->y = $y0 + ($tbd['w']/2);
22844 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') {
22845 $this->_setDashBorder($tbd['style'],'',$continuingpage,'T');
22846 $this->Line($x0 + ($tbd['w']/2) , $this->y , $x0 + $w - ($tbd['w']/2), $this->y);
22847 }
22848 else {
22849 $this->SetLineJoin(0);
22850 $this->SetLineCap(0);
22851 $this->Line($x0, $this->y , $x0 + $w, $this->y);
22852 }
22853 $this->y += $tbd['w'];
22854 // Reset Corners and Dash off
22855 $this->SetLineJoin(2);
22856 $this->SetLineCap(2);
22857 $this->SetDash();
22858 }
22859 }
22860 if ($this->blk[$blvl]['border_left']) {
22861 $tbd = $this->blk[$blvl]['border_left'];
22862 if (isset($tbd['s']) && $tbd['s']) {
22863 $this->_setBorderLine($tbd);
22864 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') {
22865 $this->y = $y0 + ($tbd['w']/2);
22866 $this->_setDashBorder($tbd['style'],'',$continuingpage,'L');
22867 $this->Line($x0 + ($tbd['w']/2), $this->y, $x0 + ($tbd['w']/2), $y0 + $h -($tbd['w']/2));
22868 }
22869 else {
22870 $this->y = $y0;
22871 $this->SetLineJoin(0);
22872 $this->SetLineCap(0);
22873 $this->Line($x0 + ($tbd['w']/2), $this->y, $x0 + ($tbd['w']/2), $y0 + $h);
22874 }
22875 $this->y += $tbd['w'];
22876 // Reset Corners and Dash off
22877 $this->SetLineJoin(2);
22878 $this->SetLineCap(2);
22879 $this->SetDash();
22880 }
22881 }
22882 if ($this->blk[$blvl]['border_right']) {
22883 $tbd = $this->blk[$blvl]['border_right'];
22884 if (isset($tbd['s']) && $tbd['s']) {
22885 $this->_setBorderLine($tbd);
22886 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') {
22887 $this->y = $y0 + ($tbd['w']/2);
22888 $this->_setDashBorder($tbd['style'],'',$continuingpage,'R');
22889 $this->Line($x0 + $w - ($tbd['w']/2), $this->y, $x0 + $w - ($tbd['w']/2), $y0 + $h - ($tbd['w']/2));
22890 }
22891 else {
22892 $this->y = $y0;
22893 $this->SetLineJoin(0);
22894 $this->SetLineCap(0);
22895 $this->Line($x0 + $w - ($tbd['w']/2), $this->y, $x0 + $w - ($tbd['w']/2), $y0 + $h);
22896 }
22897 $this->y += $tbd['w'];
22898 // Reset Corners and Dash off
22899 $this->SetLineJoin(2);
22900 $this->SetLineCap(2);
22901 $this->SetDash();
22902 }
22903 }
22904 if ($this->blk[$blvl]['border_bottom'] && $state > 1) {
22905 $tbd = $this->blk[$blvl]['border_bottom'];
22906 if (isset($tbd['s']) && $tbd['s']) {
22907 $this->_setBorderLine($tbd);
22908 $this->y = $y0 + $h - ($tbd['w']/2);
22909 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') {
22910 $this->_setDashBorder($tbd['style'],'',$continuingpage,'B');
22911 $this->Line($x0 + ($tbd['w']/2) , $this->y, $x0 + $w - ($tbd['w']/2), $this->y);
22912 }
22913 else {
22914 $this->SetLineJoin(0);
22915 $this->SetLineCap(0);
22916 $this->Line($x0, $this->y, $x0 + $w, $this->y);
22917 }
22918 $this->y += $tbd['w'];
22919 // Reset Corners and Dash off
22920 $this->SetLineJoin(2);
22921 $this->SetLineCap(2);
22922 $this->SetDash();
22923 }
22924 }
22925 $this->SetDash();
22926 $this->y = $save_y;
22927 }
22928
22929
22930 function PaintImgBorder($objattr,$is_table) {
22931 // Borders are disabled in columns - messes up the repositioning in printcolumnbuffer
22932 if ($this->ColActive) { return ; } // *COLUMNS*
22933 if ($is_table) { $k = $this->shrin_k; } else { $k = 1; }
22934 $h = (isset($objattr['BORDER-HEIGHT']) ? $objattr['BORDER-HEIGHT'] : 0);
22935 $w = (isset($objattr['BORDER-WIDTH']) ? $objattr['BORDER-WIDTH'] : 0);
22936 $x0 = (isset($objattr['BORDER-X']) ? $objattr['BORDER-X'] : 0);
22937 $y0 = (isset($objattr['BORDER-Y']) ? $objattr['BORDER-Y'] : 0);
22938
22939 // BORDERS
22940 if ($objattr['border_top']) {
22941 $tbd = $objattr['border_top'];
22942 if (!empty($tbd['s'])) {
22943 $this->_setBorderLine($tbd,$k);
22944 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],'','','T'); }
22945 $this->Line($x0, $y0, $x0 + $w, $y0);
22946 // Reset Corners and Dash off
22947 $this->SetLineJoin(2);
22948 $this->SetLineCap(2);
22949 $this->SetDash();
22950 }
22951 }
22952 if ($objattr['border_left']) {
22953 $tbd = $objattr['border_left'];
22954 if (!empty($tbd['s'])) {
22955 $this->_setBorderLine($tbd,$k);
22956 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],'','','L'); }
22957 $this->Line($x0, $y0, $x0, $y0 + $h);
22958 // Reset Corners and Dash off
22959 $this->SetLineJoin(2);
22960 $this->SetLineCap(2);
22961 $this->SetDash();
22962 }
22963 }
22964 if ($objattr['border_right']) {
22965 $tbd = $objattr['border_right'];
22966 if (!empty($tbd['s'])) {
22967 $this->_setBorderLine($tbd,$k);
22968 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],'','','R'); }
22969 $this->Line($x0 + $w, $y0, $x0 + $w, $y0 + $h);
22970 // Reset Corners and Dash off
22971 $this->SetLineJoin(2);
22972 $this->SetLineCap(2);
22973 $this->SetDash();
22974 }
22975 }
22976 if ($objattr['border_bottom']) {
22977 $tbd = $objattr['border_bottom'];
22978 if (!empty($tbd['s'])) {
22979 $this->_setBorderLine($tbd,$k);
22980 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],'','','B'); }
22981 $this->Line($x0, $y0 + $h, $x0 + $w, $y0 + $h);
22982 // Reset Corners and Dash off
22983 $this->SetLineJoin(2);
22984 $this->SetLineCap(2);
22985 $this->SetDash();
22986 }
22987 }
22988 $this->SetDash();
22989 $this->SetAlpha(1);
22990 }
22991
22992 /*-- END HTML-CSS --*/
22993
22994
22995
22996
22997 function Reset() {
22998 $this->SetTColor($this->ConvertColor(0));
22999 $this->SetDColor($this->ConvertColor(0));
23000 $this->SetFColor($this->ConvertColor(255));
23001 $this->SetAlpha(1);
23002 $this->colorarray = '';
23003
23004 $this->spanbgcolorarray = '';
23005 $this->spanbgcolor = false;
23006 $this->spanborder = false;
23007 $this->spanborddet = array();
23008
23009 $this->ResetStyles();
23010
23011 $this->HREF = '';
23012 $this->textparam = array();
23013 $this->SetTextOutline();
23014
23015 $this->textvar = 0x00; // mPDF 5.7.1
23016 $this->OTLtags = array();
23017 $this->textshadow = '';
23018
23019 $this->currentLang = $this->default_lang; // mPDF 6
23020 $this->RestrictUnicodeFonts($this->default_available_fonts ); // mPDF 6
23021 $this->SetFont($this->default_font,'',0,false);
23022 $this->SetFontSize($this->default_font_size,false);
23023
23024 $this->currentfontfamily = '';
23025 $this->currentfontsize = '';
23026 $this->currentfontstyle = '';
23027
23028 /*-- TABLES --*/
23029 if ($this->tableLevel && isset($this->table[1][1]['cellLineHeight'])) {
23030 $this->SetLineHeight('',$this->table[1][1]['cellLineHeight']); // *TABLES*
23031 }
23032 else
23033 /*-- END TABLES --*/
23034 if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) {
23035 $this->SetLineHeight('',$this->blk[$this->blklvl]['line_height']); // sets default line height
23036 }
23037
23038 $this->lSpacingCSS = '';
23039 $this->wSpacingCSS = '';
23040 $this->fixedlSpacing = false;
23041 $this->minwSpacing = 0;
23042 $this->SetDash(); //restore to no dash
23043 $this->dash_on = false;
23044 $this->dotted_on = false;
23045 $this->divwidth = 0;
23046 $this->divheight = 0;
23047 $this->cellTextAlign = '';
23048 $this->cellLineHeight = '';
23049 $this->cellLineStackingStrategy = '';
23050 $this->cellLineStackingShift = '';
23051 $this->oldy = -1;
23052
23053 $bodystyle = array();
23054 if (isset($this->cssmgr->CSS['BODY']['FONT-STYLE'])) { $bodystyle['FONT-STYLE'] = $this->cssmgr->CSS['BODY']['FONT-STYLE']; }
23055 if (isset($this->cssmgr->CSS['BODY']['FONT-WEIGHT'])) { $bodystyle['FONT-WEIGHT'] = $this->cssmgr->CSS['BODY']['FONT-WEIGHT']; }
23056 if (isset($this->cssmgr->CSS['BODY']['COLOR'])) { $bodystyle['COLOR'] = $this->cssmgr->CSS['BODY']['COLOR']; }
23057 if (isset($bodystyle)) { $this->setCSS($bodystyle,'BLOCK','BODY'); }
23058
23059 }
23060
23061 /*-- HTML-CSS --*/
23062 function ReadMetaTags($html) {
23063 // changes anykey=anyvalue to anykey="anyvalue" (only do this when this happens inside tags)
23064 $regexp = '/ (\\w+?)=([^\\s>"]+)/si';
23065 $html = preg_replace($regexp," \$1=\"\$2\"",$html);
23066 if (preg_match('/<title>(.*?)<\/title>/si',$html,$m)) {
23067 $this->SetTitle($m[1]);
23068 }
23069 preg_match_all('/<meta [^>]*?(name|content)="([^>]*?)" [^>]*?(name|content)="([^>]*?)".*?>/si',$html,$aux);
23070 $firstattr = $aux[1];
23071 $secondattr = $aux[3];
23072 for( $i = 0 ; $i < count($aux[0]) ; $i++) {
23073
23074 $name = ( strtoupper($firstattr[$i]) == "NAME" )? strtoupper($aux[2][$i]) : strtoupper($aux[4][$i]);
23075 $content = ( strtoupper($firstattr[$i]) == "CONTENT" )? $aux[2][$i] : $aux[4][$i];
23076 switch($name) {
23077 case "KEYWORDS": $this->SetKeywords($content); break;
23078 case "AUTHOR": $this->SetAuthor($content); break;
23079 case "DESCRIPTION": $this->SetSubject($content); break;
23080 }
23081 }
23082 }
23083
23084
23085 function ReadCharset($html) {
23086 // Charset conversion
23087 if ($this->allow_charset_conversion) {
23088 if (preg_match('/<head.*charset=([^\'\"\s]*).*<\/head>/si',$html,$m)) {
23089 if (strtoupper($m[1]) != 'UTF-8') {
23090 $this->charset_in = strtoupper($m[1]);
23091 }
23092 }
23093 }
23094 }
23095
23096 function setCSS($arrayaux,$type='',$tag='') { // type= INLINE | BLOCK | TABLECELL // tag= BODY
23097 if (!is_array($arrayaux)) return; //Removes PHP Warning
23098
23099 // mPDF 5.7.3 inline text-decoration parameters
23100 $preceeding_fontkey = $this->FontFamily . $this->FontStyle;
23101 $preceeding_fontsize = $this->FontSize;
23102 $spanbordset = false;
23103 $spanbgset = false;
23104 // mPDF 6
23105 $prevlevel = (($this->blklvl == 0) ? 0 : $this->blklvl-1);
23106
23107 // Set font size first so that e.g. MARGIN 0.83em works on font size for this element
23108 if (isset($arrayaux['FONT-SIZE'])) {
23109 $v = $arrayaux['FONT-SIZE'];
23110 if(is_numeric($v[0])) {
23111 if ($type == 'BLOCK' && $this->blklvl>0 && isset($this->blk[$this->blklvl-1]['InlineProperties']) && isset($this->blk[$this->blklvl-1]['InlineProperties']['size'])) {
23112 $mmsize = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['InlineProperties']['size']);
23113 }
23114 else if ($type=='TABLECELL') {
23115 $mmsize = $this->ConvertSize($v,$this->default_font_size/_MPDFK);
23116 }
23117 else {
23118 $mmsize = $this->ConvertSize($v,$this->FontSize);
23119 }
23120 $this->SetFontSize( $mmsize*(_MPDFK),false ); //Get size in points (pt)
23121 }
23122 else{
23123 $v = strtoupper($v);
23124 if (isset($this->fontsizes[$v])) {
23125 $this->SetFontSize( $this->fontsizes[$v]* $this->default_font_size,false);
23126 }
23127 }
23128 if ($tag == 'BODY') { $this->SetDefaultFontSize($this->FontSizePt); }
23129 }
23130
23131 // mPDF 6
23132 if (isset($arrayaux['LANG']) && $arrayaux['LANG']) {
23133 if ($this->autoLangToFont && !$this->usingCoreFont) {
23134 if ($arrayaux['LANG'] != $this->default_lang && $arrayaux['LANG'] != 'UTF-8') {
23135 list ($coreSuitable,$mpdf_pdf_unifont) = GetLangOpts($arrayaux['LANG'], $this->useAdobeCJK, $this->fontdata);
23136 if ($mpdf_pdf_unifont) { $arrayaux['FONT-FAMILY'] = $mpdf_pdf_unifont; }
23137 if ($tag == 'BODY') { $this->default_lang = $arrayaux['LANG']; }
23138 }
23139 }
23140 $this->currentLang = $arrayaux['LANG'];
23141 }
23142
23143 // FOR INLINE and BLOCK OR 'BODY'
23144 if (isset($arrayaux['FONT-FAMILY'])) {
23145 $v = $arrayaux['FONT-FAMILY'];
23146 //If it is a font list, get all font types
23147 $aux_fontlist = explode(",",$v);
23148 $found = 0;
23149 foreach($aux_fontlist AS $f) {
23150 $fonttype = trim($f);
23151 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
23152 $fonttype = preg_replace('/ /','',$fonttype);
23153 $v = strtolower(trim($fonttype));
23154 if (isset($this->fonttrans[$v]) && $this->fonttrans[$v]) { $v = $this->fonttrans[$v]; }
23155 if ((!$this->onlyCoreFonts && in_array($v,$this->available_unifonts)) ||
23156 in_array($v,array('ccourier','ctimes','chelvetica')) ||
23157 ($this->onlyCoreFonts && in_array($v,array('courier','times','helvetica','arial'))) ||
23158 in_array($v, array('sjis','uhc','big5','gb'))) {
23159 $fonttype = $v;
23160 $found = 1;
23161 break;
23162 }
23163 }
23164 if (!$found) {
23165 foreach($aux_fontlist AS $f) {
23166 $fonttype = trim($f);
23167 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
23168 $fonttype = preg_replace('/ /','',$fonttype);
23169 $v = strtolower(trim($fonttype));
23170 if (isset($this->fonttrans[$v]) && $this->fonttrans[$v]) { $v = $this->fonttrans[$v]; }
23171 if (in_array($v,$this->sans_fonts) || in_array($v,$this->serif_fonts) || in_array($v,$this->mono_fonts) ) {
23172 $fonttype = $v;
23173 break;
23174 }
23175 }
23176 }
23177
23178 if ($tag == 'BODY') {
23179 $this->SetDefaultFont($fonttype);
23180 }
23181 $this->SetFont($fonttype,$this->currentfontstyle,0,false);
23182 }
23183 else {
23184 $this->SetFont($this->currentfontfamily,$this->currentfontstyle,0,false);
23185 }
23186
23187 foreach($arrayaux as $k => $v) {
23188 if ($type != 'INLINE' && $tag != 'BODY' && $type != 'TABLECELL') {
23189 switch($k){
23190 // BORDERS
23191 case 'BORDER-TOP':
23192 $this->blk[$this->blklvl]['border_top'] = $this->border_details($v);
23193 if ($this->blk[$this->blklvl]['border_top']['s']) { $this->blk[$this->blklvl]['border'] = 1; }
23194 break;
23195 case 'BORDER-BOTTOM':
23196 $this->blk[$this->blklvl]['border_bottom'] = $this->border_details($v);
23197 if ($this->blk[$this->blklvl]['border_bottom']['s']) { $this->blk[$this->blklvl]['border'] = 1; }
23198 break;
23199 case 'BORDER-LEFT':
23200 $this->blk[$this->blklvl]['border_left'] = $this->border_details($v);
23201 if ($this->blk[$this->blklvl]['border_left']['s']) { $this->blk[$this->blklvl]['border'] = 1; }
23202 break;
23203 case 'BORDER-RIGHT':
23204 $this->blk[$this->blklvl]['border_right'] = $this->border_details($v);
23205 if ($this->blk[$this->blklvl]['border_right']['s']) { $this->blk[$this->blklvl]['border'] = 1; }
23206 break;
23207
23208 // PADDING
23209 case 'PADDING-TOP':
23210 $this->blk[$this->blklvl]['padding_top'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23211 break;
23212 case 'PADDING-BOTTOM':
23213 $this->blk[$this->blklvl]['padding_bottom'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23214 break;
23215 case 'PADDING-LEFT':
23216 if (($tag=='UL' || $tag=='OL') && $v == 'auto') {
23217 $this->blk[$this->blklvl]['padding_left'] = 'auto';
23218 break;
23219 }
23220 $this->blk[$this->blklvl]['padding_left'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23221 break;
23222 case 'PADDING-RIGHT':
23223 if (($tag=='UL' || $tag=='OL') && $v == 'auto') {
23224 $this->blk[$this->blklvl]['padding_right'] = 'auto';
23225 break;
23226 }
23227 $this->blk[$this->blklvl]['padding_right'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23228 break;
23229
23230 // MARGINS
23231 case 'MARGIN-TOP':
23232 $tmp = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23233 if (isset($this->blk[$this->blklvl]['lastbottommargin'])) {
23234 if ($tmp > $this->blk[$this->blklvl]['lastbottommargin']) {
23235 $tmp -= $this->blk[$this->blklvl]['lastbottommargin'];
23236 }
23237 else {
23238 $tmp = 0;
23239 }
23240 }
23241 $this->blk[$this->blklvl]['margin_top'] = $tmp;
23242 break;
23243 case 'MARGIN-BOTTOM':
23244 $this->blk[$this->blklvl]['margin_bottom'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23245 break;
23246 case 'MARGIN-LEFT':
23247 $this->blk[$this->blklvl]['margin_left'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23248 break;
23249 case 'MARGIN-RIGHT':
23250 $this->blk[$this->blklvl]['margin_right'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23251 break;
23252
23253 /*-- BORDER-RADIUS --*/
23254 case 'BORDER-TOP-LEFT-RADIUS-H':
23255 $this->blk[$this->blklvl]['border_radius_TL_H'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23256 break;
23257 case 'BORDER-TOP-LEFT-RADIUS-V':
23258 $this->blk[$this->blklvl]['border_radius_TL_V'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23259 break;
23260 case 'BORDER-TOP-RIGHT-RADIUS-H':
23261 $this->blk[$this->blklvl]['border_radius_TR_H'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23262 break;
23263 case 'BORDER-TOP-RIGHT-RADIUS-V':
23264 $this->blk[$this->blklvl]['border_radius_TR_V'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23265 break;
23266 case 'BORDER-BOTTOM-LEFT-RADIUS-H':
23267 $this->blk[$this->blklvl]['border_radius_BL_H'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23268 break;
23269 case 'BORDER-BOTTOM-LEFT-RADIUS-V':
23270 $this->blk[$this->blklvl]['border_radius_BL_V'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23271 break;
23272 case 'BORDER-BOTTOM-RIGHT-RADIUS-H':
23273 $this->blk[$this->blklvl]['border_radius_BR_H'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23274 break;
23275 case 'BORDER-BOTTOM-RIGHT-RADIUS-V':
23276 $this->blk[$this->blklvl]['border_radius_BR_V'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23277 break;
23278 /*-- END BORDER-RADIUS --*/
23279
23280 case 'BOX-SHADOW':
23281 $bs = $this->cssmgr->setCSSboxshadow($v);
23282 if ($bs) { $this->blk[$this->blklvl]['box_shadow'] = $bs; }
23283 break;
23284
23285 case 'BACKGROUND-CLIP':
23286 if (strtoupper($v) == 'PADDING-BOX') { $this->blk[$this->blklvl]['background_clip'] = 'padding-box'; }
23287 else if (strtoupper($v) == 'CONTENT-BOX') { $this->blk[$this->blklvl]['background_clip'] = 'content-box'; }
23288 break;
23289
23290 case 'PAGE-BREAK-AFTER':
23291 if (strtoupper($v) == 'AVOID') { $this->blk[$this->blklvl]['page_break_after_avoid'] = true; }
23292 else if (strtoupper($v) == 'ALWAYS' || strtoupper($v) == 'LEFT' || strtoupper($v) == 'RIGHT') { $this->blk[$this->blklvl]['page_break_after'] = strtoupper($v) ; }
23293 break;
23294
23295 // mPDF 6 pagebreaktype
23296 case 'BOX-DECORATION-BREAK':
23297 if (strtoupper($v) == 'CLONE') { $this->blk[$this->blklvl]['box_decoration_break'] = 'clone'; }
23298 else if (strtoupper($v) == 'SLICE') { $this->blk[$this->blklvl]['box_decoration_break'] = 'slice'; }
23299 break;
23300
23301 case 'WIDTH':
23302 if (strtoupper($v) != 'AUTO') {
23303 $this->blk[$this->blklvl]['css_set_width'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false);
23304 }
23305 break;
23306
23307 // mPDF 6 Lists
23308 // LISTS
23309 case 'LIST-STYLE-TYPE':
23310 $this->blk[$this->blklvl]['list_style_type'] = strtolower($v);
23311 break;
23312 case 'LIST-STYLE-IMAGE':
23313 $this->blk[$this->blklvl]['list_style_image'] = strtolower($v);
23314 break;
23315 case 'LIST-STYLE-POSITION':
23316 $this->blk[$this->blklvl]['list_style_position'] = strtolower($v);
23317 break;
23318
23319
23320 }//end of switch($k)
23321 }
23322
23323
23324 if ($type != 'INLINE' && $type != 'TABLECELL') { // All block-level, including BODY tag
23325 switch($k){
23326
23327 case 'TEXT-INDENT':
23328 // Computed value - to inherit
23329 $this->blk[$this->blklvl]['text_indent'] = $this->ConvertSize($v,$this->blk[$prevlevel]['inner_width'],$this->FontSize,false).'mm';
23330 break;
23331
23332 case 'MARGIN-COLLAPSE': // Custom tag to collapse margins at top and bottom of page
23333 if (strtoupper($v) == 'COLLAPSE') { $this->blk[$this->blklvl]['margin_collapse'] = true; }
23334 break;
23335
23336 case 'LINE-HEIGHT':
23337 $this->blk[$this->blklvl]['line_height'] = $this->fixLineheight($v);
23338 if (!$this->blk[$this->blklvl]['line_height'] ) { $this->blk[$this->blklvl]['line_height'] = 'N'; } // mPDF 6
23339 break;
23340
23341 // mPDF 6
23342 case 'LINE-STACKING-STRATEGY':
23343 $this->blk[$this->blklvl]['line_stacking_strategy'] = strtolower($v);
23344 break;
23345
23346 case 'LINE-STACKING-SHIFT':
23347 $this->blk[$this->blklvl]['line_stacking_shift'] = strtolower($v);
23348 break;
23349
23350 case 'TEXT-ALIGN': //left right center justify
23351 switch (strtoupper($v)) {
23352 case 'LEFT':
23353 $this->blk[$this->blklvl]['align']="L";
23354 break;
23355 case 'CENTER':
23356 $this->blk[$this->blklvl]['align']="C";
23357 break;
23358 case 'RIGHT':
23359 $this->blk[$this->blklvl]['align']="R";
23360 break;
23361 case 'JUSTIFY':
23362 $this->blk[$this->blklvl]['align']="J";
23363 break;
23364 }
23365 break;
23366
23367 /*-- BACKGROUNDS --*/
23368 case 'BACKGROUND-GRADIENT':
23369 if ($type == 'BLOCK') {
23370 $this->blk[$this->blklvl]['gradient'] = $v;
23371 }
23372 break;
23373 /*-- END BACKGROUNDS --*/
23374
23375 case 'DIRECTION':
23376 if ($v) { $this->blk[$this->blklvl]['direction'] = strtolower($v); }
23377 break;
23378
23379 }//end of switch($k)
23380 }
23381
23382 // FOR INLINE ONLY
23383 if ($type == 'INLINE') {
23384 switch($k){
23385 case 'DISPLAY':
23386 if (strtoupper($v) == 'NONE') { $this->inlineDisplayOff = true; }
23387 break;
23388 case 'DIRECTION':
23389 break;
23390 }//end of switch($k)
23391 }
23392 // FOR INLINE ONLY
23393 if ($type == 'INLINE') {
23394 switch($k){
23395 // BORDERS
23396 case 'BORDER-TOP':
23397 $this->spanborddet['T'] = $this->border_details($v);
23398 $this->spanborder = true;
23399 $spanbordset = true;
23400 break;
23401 case 'BORDER-BOTTOM':
23402 $this->spanborddet['B'] = $this->border_details($v);
23403 $this->spanborder = true;
23404 $spanbordset = true;
23405 break;
23406 case 'BORDER-LEFT':
23407 $this->spanborddet['L'] = $this->border_details($v);
23408 $this->spanborder = true;
23409 $spanbordset = true;
23410 break;
23411 case 'BORDER-RIGHT':
23412 $this->spanborddet['R'] = $this->border_details($v);
23413 $this->spanborder = true;
23414 $spanbordset = true;
23415 break;
23416 case 'VISIBILITY': // block is set in OpenTag
23417 $v = strtolower($v);
23418 if ($v == 'visible' || $v == 'hidden' || $v == 'printonly' || $v == 'screenonly') {
23419 $this->textparam['visibility'] = $v;
23420 }
23421 break;
23422 }//end of switch($k)
23423 }
23424
23425 if ($type != 'TABLECELL') {
23426 // FOR INLINE and BLOCK
23427 switch($k){
23428 case 'TEXT-ALIGN': //left right center justify
23429 if (strtoupper($v) == 'NOJUSTIFY' && $this->blk[$this->blklvl]['align']=="J") {
23430 $this->blk[$this->blklvl]['align']="";
23431 }
23432 break;
23433 // bgcolor only - to stay consistent with original html2fpdf
23434 case 'BACKGROUND':
23435 case 'BACKGROUND-COLOR':
23436 $cor = $this->ConvertColor($v);
23437 if ($cor) {
23438 if ($tag == 'BODY') {
23439 $this->bodyBackgroundColor = $cor;
23440 }
23441 else if ($type == 'INLINE') {
23442 $this->spanbgcolorarray = $cor;
23443 $this->spanbgcolor = true;
23444 $spanbgset = true;
23445 }
23446 else {
23447 $this->blk[$this->blklvl]['bgcolorarray'] = $cor;
23448 $this->blk[$this->blklvl]['bgcolor'] = true;
23449 }
23450 }
23451 else if ($type != 'INLINE') {
23452 if ($this->ColActive) {
23453 $this->blk[$this->blklvl]['bgcolorarray'] = $this->blk[$prevlevel]['bgcolorarray'] ;
23454 $this->blk[$this->blklvl]['bgcolor'] = $this->blk[$prevlevel]['bgcolor'] ;
23455 }
23456 }
23457 break;
23458
23459 case 'VERTICAL-ALIGN': //super and sub only dealt with here e.g. <SUB> and <SUP>
23460 switch (strtoupper($v)) {
23461 case 'SUPER':
23462 $this->textvar = ($this->textvar | FA_SUPERSCRIPT); // mPDF 5.7.1
23463 $this->textvar = ($this->textvar & ~FA_SUBSCRIPT);
23464 // mPDF 5.7.3 inline text-decoration parameters
23465 if (isset($this->textparam['text-baseline'])) { $this->textparam['text-baseline'] += ($this->baselineSup)*$preceeding_fontsize; }
23466 else { $this->textparam['text-baseline'] = ($this->baselineSup)*$preceeding_fontsize; }
23467 break;
23468 case 'SUB':
23469 $this->textvar = ($this->textvar | FA_SUBSCRIPT);
23470 $this->textvar = ($this->textvar & ~FA_SUPERSCRIPT);
23471 // mPDF 5.7.3 inline text-decoration parameters
23472 if (isset($this->textparam['text-baseline'])) { $this->textparam['text-baseline'] += ($this->baselineSub)*$preceeding_fontsize; }
23473 else { $this->textparam['text-baseline'] = ($this->baselineSub)*$preceeding_fontsize; }
23474 break;
23475 case 'BASELINE':
23476 $this->textvar = ($this->textvar & ~FA_SUBSCRIPT);
23477 $this->textvar = ($this->textvar & ~FA_SUPERSCRIPT);
23478 // mPDF 5.7.3 inline text-decoration parameters
23479 if (isset($this->textparam['text-baseline'])) { unset($this->textparam['text-baseline']); }
23480 break;
23481 // mPDF 5.7.3 inline text-decoration parameters
23482 default:
23483 $lh = $this->_computeLineheight($this->blk[$this->blklvl]['line_height']);
23484 $sz = $this->ConvertSize($v,$lh,$this->FontSize,false);
23485 $this->textvar = ($this->textvar & ~FA_SUBSCRIPT);
23486 $this->textvar = ($this->textvar & ~FA_SUPERSCRIPT);
23487 if ($sz) {
23488 if ($sz > 0) {
23489 $this->textvar = ($this->textvar | FA_SUPERSCRIPT);
23490 }
23491 else {
23492 $this->textvar = ($this->textvar | FA_SUBSCRIPT);
23493 }
23494 if (isset($this->textparam['text-baseline'])) { $this->textparam['text-baseline'] += $sz; }
23495 else { $this->textparam['text-baseline'] = $sz; }
23496 }
23497
23498 }
23499 break;
23500 }//end of switch($k)
23501 }
23502
23503
23504 // FOR ALL
23505 switch($k){
23506 case 'LETTER-SPACING':
23507 $this->lSpacingCSS = $v;
23508 if (($this->lSpacingCSS || $this->lSpacingCSS==='0') && strtoupper($this->lSpacingCSS) != 'NORMAL') {
23509 $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize);
23510 }
23511 break;
23512
23513 case 'WORD-SPACING':
23514 $this->wSpacingCSS = $v;
23515 if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') {
23516 $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize);
23517 }
23518 break;
23519
23520 case 'FONT-STYLE': // italic normal oblique
23521 switch (strtoupper($v)) {
23522 case 'ITALIC':
23523 case 'OBLIQUE':
23524 $this->SetStyle('I',true);
23525 break;
23526 case 'NORMAL':
23527 $this->SetStyle('I',false);
23528 break;
23529 }
23530 break;
23531
23532 case 'FONT-WEIGHT': // normal bold //Does not support: bolder, lighter, 100..900(step value=100)
23533 switch (strtoupper($v)) {
23534 case 'BOLD':
23535 $this->SetStyle('B',true);
23536 break;
23537 case 'NORMAL':
23538 $this->SetStyle('B',false);
23539 break;
23540 }
23541 break;
23542
23543 case 'FONT-KERNING':
23544 if (strtoupper($v) == 'NORMAL' || (strtoupper($v) == 'AUTO' && $this->useKerning)) {
23545 /*-- OTL --*/
23546 if ($this->CurrentFont['haskernGPOS']) {
23547 if (isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] .= ' kern'; }
23548 else { $this->OTLtags['Plus'] = ' kern'; }
23549 }
23550 /*-- END OTL --*/
23551 else { // *OTL*
23552 $this->textvar = ($this->textvar | FC_KERNING);
23553 } // *OTL*
23554 }
23555 else if (strtoupper($v) == 'NONE' || (strtoupper($v) == 'AUTO' && !$this->useKerning)) {
23556 if (isset($this->OTLtags['Plus'])) $this->OTLtags['Plus'] = str_replace('kern','', $this->OTLtags['Plus'] ); // *OTL*
23557 if (isset($this->OTLtags['FFPlus'])) $this->OTLtags['FFPlus'] = preg_replace('/kern[\d]*/', '', $this->OTLtags['FFPlus'] );
23558 $this->textvar = ($this->textvar & ~FC_KERNING);
23559 }
23560 break;
23561
23562 /*-- OTL --*/
23563 case 'FONT-LANGUAGE-OVERRIDE':
23564 $v =strtoupper($v);
23565 if (strpos($v, 'NORMAL')!==false) { $this->fontLanguageOverride = ''; }
23566 else { $this->fontLanguageOverride = trim($v); }
23567 break;
23568
23569
23570 case 'FONT-VARIANT-POSITION':
23571 if (isset($this->OTLtags['Plus'])) $this->OTLtags['Plus'] = str_replace(array('sups','subs'),'', $this->OTLtags['Plus']);
23572 switch (strtoupper($v)) {
23573 case 'SUPER':
23574 $this->OTLtags['Plus'] .= ' sups';
23575 break;
23576 case 'SUB':
23577 $this->OTLtags['Plus'] .= ' subs';
23578 break;
23579 case 'NORMAL':
23580 break;
23581 }
23582 break;
23583
23584 case 'FONT-VARIANT-CAPS':
23585 $v =strtoupper($v);
23586 if (!isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] = ''; }
23587 $this->OTLtags['Plus'] = str_replace(array('c2sc','smcp','c2pc','pcap','unic','titl'),'', $this->OTLtags['Plus']);
23588 $this->textvar = ($this->textvar & ~FC_SMALLCAPS); // ?????????????? <small-caps>
23589 if (strpos($v, 'ALL-SMALL-CAPS')!==false) { $this->OTLtags['Plus'] .= ' c2sc smcp'; }
23590 else if (strpos($v, 'SMALL-CAPS')!==false) {
23591 if (isset($this->CurrentFont['hassmallcapsGSUB']) && $this->CurrentFont['hassmallcapsGSUB']) { $this->OTLtags['Plus'] .= ' smcp'; }
23592 else { $this->textvar = ($this->textvar | FC_SMALLCAPS); }
23593 }
23594 else if (strpos($v, 'ALL-PETITE-CAPS')!==false) { $this->OTLtags['Plus'] .= ' c2pc pcap'; }
23595 else if (strpos($v, 'PETITE-CAPS')!==false) { $this->OTLtags['Plus'] .= ' pcap'; }
23596 else if (strpos($v, 'UNICASE')!==false) { $this->OTLtags['Plus'] .= ' unic'; }
23597 else if (strpos($v, 'TITLING-CAPS')!==false) { $this->OTLtags['Plus'] .= ' titl'; }
23598 break;
23599
23600 case 'FONT-VARIANT-LIGATURES':
23601 $v =strtoupper($v);
23602 if (!isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] = ''; }
23603 if (!isset($this->OTLtags['Minus'])) { $this->OTLtags['Minus'] = ''; }
23604 if (strpos($v, 'NORMAL')!==false) {
23605 $this->OTLtags['Minus'] = str_replace(array('liga','clig','calt'),'', $this->OTLtags['Minus']);
23606 $this->OTLtags['Plus'] = str_replace(array('dlig','hlig'),'', $this->OTLtags['Plus']);
23607 }
23608 else if (strpos($v, 'NONE')!==false) {
23609 $this->OTLtags['Minus'] .= ' liga clig calt';
23610 $this->OTLtags['Plus'] = str_replace(array('dlig','hlig'),'', $this->OTLtags['Plus']);
23611 }
23612 if (strpos($v, 'NO-COMMON-LIGATURES')!==false) { $this->OTLtags['Minus'] .= ' liga clig'; }
23613 else if (strpos($v, 'COMMON-LIGATURES')!==false) { $this->OTLtags['Minus'] = str_replace(array('liga','clig'),'', $this->OTLtags['Minus']); }
23614 if (strpos($v, 'NO-CONTEXTUAL')!==false) { $this->OTLtags['Minus'] .= ' calt'; }
23615 else if (strpos($v, 'CONTEXTUAL')!==false) { $this->OTLtags['Minus'] = str_replace('calt','', $this->OTLtags['Minus']); }
23616 if (strpos($v, 'NO-DISCRETIONARY-LIGATURES')!==false) { $this->OTLtags['Plus'] = str_replace('dlig','', $this->OTLtags['Plus'] ); }
23617 else if (strpos($v, 'DISCRETIONARY-LIGATURES')!==false) { $this->OTLtags['Plus'] .= ' dlig'; }
23618 if (strpos($v, 'NO-HISTORICAL-LIGATURES')!==false) { $this->OTLtags['Plus'] = str_replace('hlig','', $this->OTLtags['Plus'] ); }
23619 else if (strpos($v, 'HISTORICAL-LIGATURES')!==false) { $this->OTLtags['Plus'] .= ' hlig'; }
23620
23621 break;
23622
23623 case 'FONT-VARIANT-NUMERIC':
23624 $v =strtoupper($v);
23625 if (!isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] = ''; }
23626 if (strpos($v, 'NORMAL')!==false) {
23627 $this->OTLtags['Plus'] = str_replace(array('ordn','zero','lnum','onum','pnum','tnum','frac','afrc'),'', $this->OTLtags['Plus']);
23628 }
23629 if (strpos($v, 'ORDINAL')!==false) { $this->OTLtags['Plus'] .= ' ordn'; }
23630 if (strpos($v, 'SLASHED-ZERO')!==false) { $this->OTLtags['Plus'] .= ' zero'; }
23631 if (strpos($v, 'LINING-NUMS')!==false) { $this->OTLtags['Plus'] .= ' lnum'; $this->OTLtags['Plus'] = str_replace('onum','', $this->OTLtags['Plus'] ); }
23632 else if (strpos($v, 'OLDSTYLE-NUMS')!==false) { $this->OTLtags['Plus'] .= ' onum'; $this->OTLtags['Plus'] = str_replace('lnum','', $this->OTLtags['Plus'] ); }
23633 if (strpos($v, 'PROPORTIONAL-NUMS')!==false) { $this->OTLtags['Plus'] .= ' pnum'; $this->OTLtags['Plus'] = str_replace('tnum','', $this->OTLtags['Plus'] ); }
23634 else if (strpos($v, 'TABULAR-NUMS')!==false) { $this->OTLtags['Plus'] .= ' tnum'; $this->OTLtags['Plus'] = str_replace('pnum','', $this->OTLtags['Plus'] ); }
23635 if (strpos($v, 'DIAGONAL-FRACTIONS')!==false) { $this->OTLtags['Plus'] .= ' frac'; $this->OTLtags['Plus'] = str_replace('afrc','', $this->OTLtags['Plus'] ); }
23636 else if (strpos($v, 'STACKED-FRACTIONS')!==false) { $this->OTLtags['Plus'] .= ' afrc'; $this->OTLtags['Plus'] = str_replace('frac','', $this->OTLtags['Plus'] ); }
23637 break;
23638
23639 case 'FONT-VARIANT-ALTERNATES': // Only supports historical-forms
23640 $v =strtoupper($v);
23641 if (!isset($this->OTLtags['Plus'])) { $this->OTLtags['Plus'] = ''; }
23642 if (strpos($v, 'NORMAL')!==false) {
23643 $this->OTLtags['Plus'] = str_replace('hist','', $this->OTLtags['Plus']);
23644 }
23645 if (strpos($v, 'HISTORICAL-FORMS')!==false) { $this->OTLtags['Plus'] .= ' hist'; }
23646 break;
23647
23648
23649 case 'FONT-FEATURE-SETTINGS':
23650 $v =strtolower($v);
23651 if (strpos($v, 'normal')!==false) {
23652 $this->OTLtags['FFMinus'] = '';
23653 $this->OTLtags['FFPlus'] = '';
23654 }
23655 else {
23656 if (!isset($this->OTLtags['FFPlus'])) { $this->OTLtags['FFPlus'] = ''; }
23657 if (!isset($this->OTLtags['FFMinus'])) { $this->OTLtags['FFMinus'] = ''; }
23658 $tags = preg_split('/[,]/',$v);
23659 foreach($tags AS $t) {
23660 if(preg_match('/[\"\']([a-zA-Z0-9]{4})[\"\']\s*(on|off|\d*){0,1}/', $t, $m)) {
23661 if ($m[2]=='off' || $m[2]==='0') {
23662 if (strpos($this->OTLtags['FFMinus'],$m[1])===false) { $this->OTLtags['FFMinus'] .= ' '.$m[1]; }
23663 $this->OTLtags['FFPlus'] = preg_replace('/'.$m[1].'[\d]*/', '', $this->OTLtags['FFPlus'] );
23664 }
23665 else {
23666 if ($m[2]=='on') { $m[2] = '1'; }
23667 if (strpos($this->OTLtags['FFPlus'],$m[1])===false) { $this->OTLtags['FFPlus'] .= ' '.$m[1].$m[2]; }
23668 $this->OTLtags['FFMinus'] = str_replace($m[1],'', $this->OTLtags['FFMinus'] );
23669 }
23670 }
23671 }
23672 }
23673 break;
23674 /*-- END OTL --*/
23675
23676
23677 case 'TEXT-TRANSFORM': // none uppercase lowercase //Does support: capitalize
23678 switch (strtoupper($v)) { //Not working 100%
23679 case 'CAPITALIZE':
23680 $this->textvar = ($this->textvar | FT_CAPITALIZE); // mPDF 5.7.1
23681 $this->textvar = ($this->textvar & ~FT_UPPERCASE); // mPDF 5.7.1
23682 $this->textvar = ($this->textvar & ~FT_LOWERCASE); // mPDF 5.7.1
23683 break;
23684 case 'UPPERCASE':
23685 $this->textvar = ($this->textvar | FT_UPPERCASE); // mPDF 5.7.1
23686 $this->textvar = ($this->textvar & ~FT_LOWERCASE); // mPDF 5.7.1
23687 $this->textvar = ($this->textvar & ~FT_CAPITALIZE); // mPDF 5.7.1
23688 break;
23689 case 'LOWERCASE':
23690 $this->textvar = ($this->textvar | FT_LOWERCASE); // mPDF 5.7.1
23691 $this->textvar = ($this->textvar & ~FT_UPPERCASE); // mPDF 5.7.1
23692 $this->textvar = ($this->textvar & ~FT_CAPITALIZE); // mPDF 5.7.1
23693 break;
23694 case 'NONE': break;
23695 $this->textvar = ($this->textvar & ~FT_UPPERCASE); // mPDF 5.7.1
23696 $this->textvar = ($this->textvar & ~FT_LOWERCASE); // mPDF 5.7.1
23697 $this->textvar = ($this->textvar & ~FT_CAPITALIZE); // mPDF 5.7.1
23698 }
23699 break;
23700
23701 case 'TEXT-SHADOW':
23702 $ts = $this->cssmgr->setCSStextshadow($v);
23703 if ($ts) { $this->textshadow = $ts; }
23704 break;
23705
23706 case 'HYPHENS':
23707 if (strtoupper($v)=='NONE') {
23708 $this->textparam['hyphens'] = 2;
23709 }
23710 else if (strtoupper($v)=='AUTO') {
23711 $this->textparam['hyphens'] = 1;
23712 }
23713 else if (strtoupper($v)=='MANUAL') {
23714 $this->textparam['hyphens'] = 0;
23715 }
23716 break;
23717
23718 case 'TEXT-OUTLINE':
23719 if (strtoupper($v)=='NONE') {
23720 $this->textparam['outline-s'] = false;
23721 }
23722 break;
23723
23724 case 'TEXT-OUTLINE-WIDTH':
23725 case 'OUTLINE-WIDTH':
23726 switch(strtoupper($v)) {
23727 case 'THIN': $v = '0.03em'; break;
23728 case 'MEDIUM': $v = '0.05em'; break;
23729 case 'THICK': $v = '0.07em'; break;
23730 }
23731 $w = $this->ConvertSize($v,$this->FontSize,$this->FontSize);
23732 if ($w) {
23733 $this->textparam['outline-WIDTH'] = $w;
23734 $this->textparam['outline-s'] = true;
23735 }
23736 else { $this->textparam['outline-s'] = false; }
23737 break;
23738
23739 case 'TEXT-OUTLINE-COLOR':
23740 case 'OUTLINE-COLOR':
23741 if (strtoupper($v) == 'INVERT') {
23742 if ($this->colorarray) {
23743 $cor = $this->colorarray;
23744 $this->textparam['outline-COLOR'] = $this->_invertColor($cor);
23745 }
23746 else {
23747 $this->textparam['outline-COLOR'] = $this->ConvertColor(255);
23748 }
23749 }
23750 else {
23751 $cor = $this->ConvertColor($v);
23752 if ($cor) { $this->textparam['outline-COLOR'] = $cor ; }
23753 }
23754 break;
23755
23756 case 'COLOR': // font color
23757 $cor = $this->ConvertColor($v);
23758 if ($cor) {
23759 $this->colorarray = $cor;
23760 $this->SetTColor($cor);
23761 }
23762 break;
23763
23764
23765 }//end of switch($k)
23766
23767
23768 }//end of foreach
23769
23770 // mPDF 5.7.3 inline text-decoration parameters
23771 // Needs to be set at the end - after vertical-align = super/sub, so that textparam['text-baseline'] is set
23772 if (isset($arrayaux['TEXT-DECORATION'])) {
23773 $v = $arrayaux['TEXT-DECORATION']; // none underline line-through (strikeout) //Does not support: blink
23774 if (stristr($v,'LINE-THROUGH')) {
23775 $this->textvar = ($this->textvar | FD_LINETHROUGH);
23776 // mPDF 5.7.3 inline text-decoration parameters
23777 if (isset($this->textparam['text-baseline'])) { $this->textparam['s-decoration']['baseline'] = $this->textparam['text-baseline']; }
23778 else { $this->textparam['s-decoration']['baseline'] = 0; }
23779 $this->textparam['s-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle;
23780 $this->textparam['s-decoration']['fontsize'] = $this->FontSize;
23781 $this->textparam['s-decoration']['color'] = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
23782 }
23783 if (stristr($v,'UNDERLINE')) {
23784 $this->textvar = ($this->textvar | FD_UNDERLINE);
23785 // mPDF 5.7.3 inline text-decoration parameters
23786 if (isset($this->textparam['text-baseline'])) { $this->textparam['u-decoration']['baseline'] = $this->textparam['text-baseline']; }
23787 else { $this->textparam['u-decoration']['baseline'] = 0; }
23788 $this->textparam['u-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle;
23789 $this->textparam['u-decoration']['fontsize'] = $this->FontSize;
23790 $this->textparam['u-decoration']['color'] = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
23791 }
23792 if (stristr($v,'OVERLINE')) {
23793 $this->textvar = ($this->textvar | FD_OVERLINE);
23794 // mPDF 5.7.3 inline text-decoration parameters
23795 if (isset($this->textparam['text-baseline'])) { $this->textparam['o-decoration']['baseline'] = $this->textparam['text-baseline']; }
23796 else { $this->textparam['o-decoration']['baseline'] = 0; }
23797 $this->textparam['o-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle;
23798 $this->textparam['o-decoration']['fontsize'] = $this->FontSize;
23799 $this->textparam['o-decoration']['color'] = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
23800 }
23801 if (stristr($v,'NONE')) {
23802 $this->textvar = ($this->textvar & ~FD_UNDERLINE);
23803 $this->textvar = ($this->textvar & ~FD_LINETHROUGH);
23804 $this->textvar = ($this->textvar & ~FD_OVERLINE);
23805 // mPDF 5.7.3 inline text-decoration parameters
23806 if (isset($this->textparam['u-decoration'])) { unset($this->textparam['u-decoration']); }
23807 if (isset($this->textparam['s-decoration'])) { unset($this->textparam['s-decoration']); }
23808 if (isset($this->textparam['o-decoration'])) { unset($this->textparam['o-decoration']); }
23809 }
23810 }
23811 // mPDF 6
23812 if ($spanbordset) { // BORDER has been set on this INLINE element
23813 if (isset($this->textparam['text-baseline'])) { $this->textparam['bord-decoration']['baseline'] = $this->textparam['text-baseline']; }
23814 else { $this->textparam['bord-decoration']['baseline'] = 0; }
23815 $this->textparam['bord-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle;
23816 $this->textparam['bord-decoration']['fontsize'] = $this->FontSize;
23817 }
23818 if ($spanbgset) { // BACKGROUND[-COLOR] has been set on this INLINE element
23819 if (isset($this->textparam['text-baseline'])) { $this->textparam['bg-decoration']['baseline'] = $this->textparam['text-baseline']; }
23820 else { $this->textparam['bg-decoration']['baseline'] = 0; }
23821 $this->textparam['bg-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle;
23822 $this->textparam['bg-decoration']['fontsize'] = $this->FontSize;
23823 }
23824
23825
23826 }
23827
23828 /*-- END HTML-CSS --*/
23829
23830
23831 function SetStyle($tag,$enable) {
23832 $this->$tag=$enable;
23833 $style='';
23834 foreach(array('B','I') as $s) {
23835 if($this->$s) {
23836 $style.=$s;
23837 }
23838 }
23839 $this->currentfontstyle=$style;
23840 $this->SetFont('',$style,0,false);
23841 }
23842
23843 // Set multiple styles at one time
23844 function SetStylesArray($arr) {
23845 $style='';
23846 foreach(array('B','I') as $s) {
23847 if (isset($arr[$s])) {
23848 if ($arr[$s]) {
23849 $this->$s = true;
23850 $style.=$s;
23851 }
23852 else { $this->$s = false; }
23853 }
23854 else if ($this->$s) { $style.=$s; }
23855 }
23856 $this->currentfontstyle=$style;
23857 $this->SetFont('',$style,0,false);
23858 }
23859
23860 // Set multiple styles at one $str e.g. "BI"
23861 function SetStyles($str) {
23862 $style='';
23863 foreach(array('B','I') as $s) {
23864 if (strpos($str,$s) !== false) {
23865 $this->$s = true;
23866 $style.=$s;
23867 }
23868 else { $this->$s = false; }
23869 }
23870 $this->currentfontstyle=$style;
23871 $this->SetFont('',$style,0,false);
23872 }
23873
23874 function ResetStyles() {
23875 foreach(array('B','I') as $s) {
23876 $this->$s = false;
23877 }
23878 $this->currentfontstyle='';
23879 $this->SetFont('','',0,false);
23880 }
23881
23882
23883 function DisableTags($str='') {
23884 if ($str == '') { //enable all tags
23885 //Insert new supported tags in the long string below.
23886 $this->enabledtags = "<a><acronym><address><article><aside><b><bdi><bdo><big><blockquote><br><caption><center><cite><code><del><details><dd><div><dl><dt><em><fieldset><figcaption><figure><font><form><h1><h2><h3><h4><h5><h6><hgroup><hr><i><img><input><ins><kbd><legend><li><main><mark><meter><nav><ol><option><p><pre><progress><q><s><samp><section><select><small><span><strike><strong><sub><summary><sup><table><tbody><td><template><textarea><tfoot><th><thead><time><tr><tt><u><ul><var><footer><header><annotation><bookmark><jpgraph><textcircle><barcode><dottab><indexentry><indexinsert><watermarktext><watermarkimage><tts><ttz><tta><column_break><columnbreak><newcolumn><newpage><page_break><pagebreak><formfeed><columns><toc><tocentry><tocpagebreak><pageheader><pagefooter><setpageheader><setpagefooter><sethtmlpageheader><sethtmlpagefooter>";
23887 }
23888 else {
23889 $str = explode(",",$str);
23890 foreach($str as $v) $this->enabledtags = str_replace(trim($v),'',$this->enabledtags);
23891 }
23892 }
23893
23894
23895 /*-- TABLES --*/
23896
23897 function TableCheckMinWidth($maxwidth, $forcewrap = 0, $textbuffer, $checkletter=false) { // mPDF 6
23898 $acclength = 0; // mPDF 6 (accumulated length across > 1 chunk)
23899 $acclongest = 0; // mPDF 6 (accumulated length max across > 1 chunk)
23900 $biggestword=0;
23901 $toonarrow=false;
23902 if ((count($textbuffer) == 0) or ((count($textbuffer) == 1) && ($textbuffer[0][0] == ''))) { return 0; }
23903
23904 foreach ($textbuffer as $chunk) {
23905
23906 $line = $chunk[0];
23907 $OTLdata = (isset($chunk[18]) ? $chunk[18] : NULL);
23908
23909 // mPDF ITERATION
23910 if ($this->iterationCounter) $line = preg_replace('/{iteration ([a-zA-Z0-9_]+)}/','\\1', $line);
23911
23912 // IMAGES & FORM ELEMENTS
23913 if (substr($line,0,3) == "\xbb\xa4\xac") { //inline object - FORM element or IMAGE!
23914 $objattr = $this->_getObjAttr($line);
23915 if ($objattr['type']!='hr' && isset($objattr['width']) && ($objattr['width']/$this->shrin_k) > ($maxwidth + 0.0001) ) {
23916 if (($objattr['width']/$this->shrin_k) > $biggestword) { $biggestword = ($objattr['width']/$this->shrin_k); }
23917 $toonarrow=true;
23918 }
23919 continue;
23920 }
23921
23922 if ($line == "\n") {
23923 $acclength = 0; // mPDF 6 (accumulated length across > 1 chunk)
23924 continue;
23925 }
23926 $line = trim($line );
23927 if (!empty($OTLdata)) { $this->otl->trimOTLdata($OTLdata, true, true); } // *OTL*
23928
23929 // SET FONT SIZE/STYLE from $chunk[n]
23930 // FONTSIZE
23931 if(isset($chunk[11]) and $chunk[11] != '') {
23932 if ($this->shrin_k) {
23933 $this->SetFontSize($chunk[11]/$this->shrin_k,false);
23934 }
23935 else {
23936 $this->SetFontSize($chunk[11],false);
23937 }
23938 }
23939 // FONTFAMILY
23940 if(isset($chunk[4]) and $chunk[4] != '') { $font = $this->SetFont($chunk[4],$this->FontStyle,0,false); }
23941 // B I
23942 if(isset($chunk[2]) and $chunk[2] != '') {
23943 $this->SetStyles($chunk[2]);
23944 }
23945
23946 $lbw = $rbw = 0; // Border widths
23947 if(isset($chunk[16]) && !empty($chunk[16])) { //Border
23948 $this->spanborddet = $chunk[16];
23949 $lbw = (isset($this->spanborddet['L']['w']) ? $this->spanborddet['L']['w'] : 0);
23950 $rbw = (isset($this->spanborddet['R']['w']) ? $this->spanborddet['R']['w'] : 0);
23951 }
23952 if(isset($chunk[15])) { // Word spacing
23953 $this->wSpacingCSS = $chunk[15];
23954 if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') {
23955 $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize)/$this->shrin_k; // mPDF 5.7.3
23956 }
23957 }
23958 if(isset($chunk[14])) { // Letter spacing
23959 $this->lSpacingCSS = $chunk[14];
23960 if (($this->lSpacingCSS || $this->lSpacingCSS==='0') && strtoupper($this->lSpacingCSS) != 'NORMAL') {
23961 $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize)/$this->shrin_k; // mPDF 5.7.3
23962 }
23963 }
23964 if(isset($chunk[8])) { // mPDF 5.7.1
23965 $this->textvar = $chunk[8];
23966 }
23967
23968 // mPDF 6
23969 // If overflow==wrap ($checkletter) OR (No word breaks and contains CJK)
23970 if ($checkletter || (!preg_match('/(\xe2\x80\x8b| )/', trim($line)) && preg_match("/([".$this->pregCJKchars."])/u", $line) ) ) {
23971 if (preg_match("/([".$this->pregCJKchars."])/u", $line) ) { $checkCJK = true; }
23972 else { $checkCJK = false; }
23973
23974 $letters = preg_split('//u', $line);
23975 foreach ($letters as $k=>$letter) {
23976
23977 // mPDF 6
23978 if ($checkCJK) {
23979 if (preg_match("/[".$this->CJKleading."]/u", $letter) && $k>0) { $letter = $letters[$k-1].$letter; }
23980 if (preg_match("/[".$this->CJKfollowing."]/u", $letter) && $k<(count($letters)-1)) { $letter = $letter.$letters[$k+1]; }
23981 }
23982
23983 $letterwidth = $this->GetStringWidth($letter, false, false, $chunk[8]); // Pass $textvar ($chunk[8]), but do OTLdata here
23984 // so don't have to split OTLdata for each word
23985 if ($k==0) { $letterwidth += $lbw; }
23986 if ($k==(count($letters)-1)) { $letterwidth += $rbw; }
23987
23988 //Warn user that maxwidth is insufficient
23989 if ($letterwidth > $maxwidth + 0.0001) {
23990 if ($letterwidth > $biggestword) { $biggestword = $letterwidth ; }
23991 $toonarrow=true;
23992 }
23993 }
23994
23995 }
23996 else {
23997 // mPDF 6
23998 // Need to account for any XAdvance in GPOSinfo (OTLdata = $chunk[18])
23999 $wordXAdvance = array();
24000 if (isset($chunk[18]) && $chunk[18]) {
24001 preg_match_all ( '/(\xe2\x80\x8b| )/', $line, $spaces, PREG_OFFSET_CAPTURE ); // U+200B Zero Width word boundary, or space
24002 $lastoffset = 0;
24003 $k = -1; // Added so that if no spaces found, "last word" later is calculated for the one and only word
24004 foreach ($spaces[0] as $k=>$m) {
24005 $offset = $m[1];
24006 // ...TableCheckMinWidth...
24007 // At this point, BIDI not applied, Writing direction is not set, and XAdvanceL balances XAdvanceR
24008 for ($n=$lastoffset;$n<$offset;$n++) {
24009 if (isset($chunk[18]['GPOSinfo'][$n]['XAdvanceL'])) {
24010 if (isset($wordXAdvance[$k])) { $wordXAdvance[$k] += $chunk[18]['GPOSinfo'][$n]['XAdvanceL']; }
24011 else { $wordXAdvance[$k] = $chunk[18]['GPOSinfo'][$n]['XAdvanceL']; }
24012 }
24013 }
24014 $lastoffset = $offset+1;
24015 }
24016
24017 $k++; // last word
24018 foreach($chunk[18]['GPOSinfo'] AS $n => $gpos) {
24019 if ($n >= $lastoffset && isset($chunk[18]['GPOSinfo'][$n]['XAdvanceL'])) {
24020 if (isset($wordXAdvance[$k])) { $wordXAdvance[$k] += $chunk[18]['GPOSinfo'][$n]['XAdvanceL']; }
24021 else { $wordXAdvance[$k] = $chunk[18]['GPOSinfo'][$n]['XAdvanceL']; }
24022 }
24023 }
24024 }
24025
24026 $words = preg_split('/(\xe2\x80\x8b| )/', $line); // U+200B Zero Width word boundary, or space
24027 foreach ($words as $k=>$word) {
24028 $word = trim($word);
24029 $wordwidth = $this->GetStringWidth($word, false, false, $chunk[8]); // Pass $textvar ($chunk[8]), but do OTLdata here
24030 // so don't have to split OTLdata for each word
24031 if (isset($wordXAdvance[$k])) { $wordwidth += ($wordXAdvance[$k]* 1000/$this->CurrentFont['unitsPerEm']) * ($this->FontSize/ 1000); }
24032 if ($k==0) { $wordwidth += $lbw; }
24033 if ($k==(count($words)-1)) { $wordwidth += $rbw; }
24034
24035 // mPDF 6
24036 if ( count($words)==1 && substr($chunk[0],0,1)!=' ') { $acclength += $wordwidth; }
24037 else if (count($words)>1 && $k==0 && substr($chunk[0],0,1)!=' ') { $acclength += $wordwidth; }
24038 else { $acclength = $wordwidth; }
24039 $acclongest = max($acclongest,$acclength);
24040 if (count($words)==1 && substr($chunk[0],-1,1)==' ') { $acclength = 0; }
24041 else if (count($words)>1 && ($k!=(count($words)-1) || substr($chunk[0],-1,1)==' ')) { $acclength = 0; }
24042
24043 //Warn user that maxwidth is insufficient
24044 if ($wordwidth > $maxwidth + 0.0001) {
24045 if ($wordwidth > $biggestword) { $biggestword = $wordwidth; }
24046 $toonarrow=true;
24047 }
24048 }
24049 }
24050
24051 // mPDF 6 Accumulated length of biggest word - across multiple chunks
24052 if ($acclongest > $maxwidth + 0.0001) {
24053 if ($acclongest > $biggestword) { $biggestword = $acclongest; }
24054 $toonarrow=true;
24055 }
24056
24057 // RESET FONT SIZE/STYLE
24058 // RESETTING VALUES
24059 //Now we must deactivate what we have used
24060 if(isset($chunk[2]) and $chunk[2] != '') {
24061 $this->ResetStyles();
24062 }
24063 if(isset($chunk[4]) and $chunk[4] != '') {
24064 $this->SetFont($this->default_font,$this->FontStyle,0,false);
24065 }
24066 if(isset($chunk[11]) and $chunk[11] != '') {
24067 $this->SetFontSize($this->default_font_size,false);
24068 }
24069 $this->spanborddet = array();
24070 $this->textvar = 0x00; // mPDF 5.7.1
24071 $this->OTLtags = array();
24072 $this->lSpacingCSS = '';
24073 $this->wSpacingCSS = '';
24074 $this->fixedlSpacing = false;
24075 $this->minwSpacing = 0;
24076 }
24077
24078 //Return -(wordsize) if word is bigger than maxwidth
24079 // ADDED
24080 if (($toonarrow) && ($this->table_error_report)) {
24081 $this->Error("Word is too long to fit in table - ".$this->table_error_report_param);
24082 }
24083 if ($toonarrow) return -$biggestword;
24084 else return 1;
24085 }
24086
24087 function shrinkTable(&$table,$k) {
24088 $table['border_spacing_H'] /= $k;
24089 $table['border_spacing_V'] /= $k;
24090
24091 $table['padding']['T'] /= $k;
24092 $table['padding']['R'] /= $k;
24093 $table['padding']['B'] /= $k;
24094 $table['padding']['L'] /= $k;
24095
24096 $table['margin']['T'] /= $k;
24097 $table['margin']['R'] /= $k;
24098 $table['margin']['B'] /= $k;
24099 $table['margin']['L'] /= $k;
24100
24101 $table['border_details']['T']['w'] /= $k;
24102 $table['border_details']['R']['w'] /= $k;
24103 $table['border_details']['B']['w'] /= $k;
24104 $table['border_details']['L']['w'] /= $k;
24105
24106 if (isset($table['max_cell_border_width']['T'])) $table['max_cell_border_width']['T'] /= $k;
24107 if (isset($table['max_cell_border_width']['R'])) $table['max_cell_border_width']['R'] /= $k;
24108 if (isset($table['max_cell_border_width']['B'])) $table['max_cell_border_width']['B'] /= $k;
24109 if (isset($table['max_cell_border_width']['L'])) $table['max_cell_border_width']['L'] /= $k;
24110
24111 if ($this->simpleTables){
24112 $table['simple']['border_details']['T']['w'] /= $k;
24113 $table['simple']['border_details']['R']['w'] /= $k;
24114 $table['simple']['border_details']['B']['w'] /= $k;
24115 $table['simple']['border_details']['L']['w'] /= $k;
24116 }
24117
24118 $table['miw'] /= $k;
24119 $table['maw'] /= $k;
24120
24121 for($j = 0 ; $j < $table['nc'] ; $j++ ) { //columns
24122
24123 $table['wc'][$j]['miw'] /= $k;
24124 $table['wc'][$j]['maw'] /= $k;
24125
24126 if (isset($table['decimal_align'][$j]['maxs0']) && $table['decimal_align'][$j]['maxs0']) { $table['decimal_align'][$j]['maxs0'] /= $k; }
24127 if (isset($table['decimal_align'][$j]['maxs1']) && $table['decimal_align'][$j]['maxs1']) { $table['decimal_align'][$j]['maxs1'] /= $k; }
24128
24129 if (isset($table['wc'][$j]['absmiw']) && $table['wc'][$j]['absmiw'] ) $table['wc'][$j]['absmiw'] /= $k;
24130
24131 for($i = 0 ; $i < $table['nr']; $i++ ) { //rows
24132 $c = &$table['cells'][$i][$j];
24133 if (isset($c) && $c) {
24134 if (!$this->simpleTables){
24135 if ($this->packTableData) {
24136 $cell = $this->_unpackCellBorder($c['borderbin'] );
24137 $cell['border_details']['T']['w'] /= $k;
24138 $cell['border_details']['R']['w'] /= $k;
24139 $cell['border_details']['B']['w'] /= $k;
24140 $cell['border_details']['L']['w'] /= $k;
24141 $cell['border_details']['mbw']['TL'] /= $k;
24142 $cell['border_details']['mbw']['TR'] /= $k;
24143 $cell['border_details']['mbw']['BL'] /= $k;
24144 $cell['border_details']['mbw']['BR'] /= $k;
24145 $cell['border_details']['mbw']['LT'] /= $k;
24146 $cell['border_details']['mbw']['LB'] /= $k;
24147 $cell['border_details']['mbw']['RT'] /= $k;
24148 $cell['border_details']['mbw']['RB'] /= $k;
24149 $c['borderbin'] = $this->_packCellBorder($cell);
24150 }
24151 else {
24152 $c['border_details']['T']['w'] /= $k;
24153 $c['border_details']['R']['w'] /= $k;
24154 $c['border_details']['B']['w'] /= $k;
24155 $c['border_details']['L']['w'] /= $k;
24156 $c['border_details']['mbw']['TL'] /= $k;
24157 $c['border_details']['mbw']['TR'] /= $k;
24158 $c['border_details']['mbw']['BL'] /= $k;
24159 $c['border_details']['mbw']['BR'] /= $k;
24160 $c['border_details']['mbw']['LT'] /= $k;
24161 $c['border_details']['mbw']['LB'] /= $k;
24162 $c['border_details']['mbw']['RT'] /= $k;
24163 $c['border_details']['mbw']['RB'] /= $k;
24164 }
24165 }
24166 $c['padding']['T'] /= $k;
24167 $c['padding']['R'] /= $k;
24168 $c['padding']['B'] /= $k;
24169 $c['padding']['L'] /= $k;
24170 if (isset($c['maxs'])) { $c['maxs'] /= $k; }
24171 if (isset($c['w'])) { $c['w'] /= $k; }
24172 $c['s'] /= $k;
24173 $c['maw'] /= $k;
24174 $c['miw'] /= $k;
24175 if (isset($c['h'])) { $c['h'] /= $k; } // mPDF 5.7.4
24176 if (isset($c['absmiw'])) $c['absmiw'] /= $k;
24177 if (isset($c['nestedmaw'])) $c['nestedmaw'] /= $k;
24178 if (isset($c['nestedmiw'])) $c['nestedmiw'] /= $k;
24179 if (isset($c['textbuffer'])) {
24180 foreach($c['textbuffer'] AS $n=>$tb) {
24181 if (!empty($tb[16])) {
24182 $c['textbuffer'][$n][16]['T']['w'] /= $k;
24183 $c['textbuffer'][$n][16]['B']['w'] /= $k;
24184 $c['textbuffer'][$n][16]['L']['w'] /= $k;
24185 $c['textbuffer'][$n][16]['R']['w'] /= $k;
24186 }
24187 }
24188 }
24189 unset($c);
24190 }
24191 }//rows
24192 }//columns
24193 }
24194
24195 function read_short(&$fh) {
24196 $s = fread($fh,2);
24197 $a = (ord($s[0])<<8) + ord($s[1]);
24198 if ($a & (1 << 15) ) {
24199 $a = ($a - (1 << 16));
24200 }
24201 return $a;
24202 }
24203
24204
24205 function _packCellBorder($cell) {
24206 if (!is_array($cell) || !isset($cell)) { return ''; }
24207
24208 if (!$this->packTableData) { return $cell; }
24209 // = 186 bytes
24210 $bindata = pack("nnda6A10nnda6A10nnda6A10nnda6A10nd9",
24211 $cell['border'],
24212 $cell['border_details']['R']['s'],
24213 $cell['border_details']['R']['w'],
24214 $cell['border_details']['R']['c'],
24215 $cell['border_details']['R']['style'],
24216 $cell['border_details']['R']['dom'],
24217
24218 $cell['border_details']['L']['s'],
24219 $cell['border_details']['L']['w'],
24220 $cell['border_details']['L']['c'],
24221 $cell['border_details']['L']['style'],
24222 $cell['border_details']['L']['dom'],
24223
24224 $cell['border_details']['T']['s'],
24225 $cell['border_details']['T']['w'],
24226 $cell['border_details']['T']['c'],
24227 $cell['border_details']['T']['style'],
24228 $cell['border_details']['T']['dom'],
24229
24230 $cell['border_details']['B']['s'],
24231 $cell['border_details']['B']['w'],
24232 $cell['border_details']['B']['c'],
24233 $cell['border_details']['B']['style'],
24234 $cell['border_details']['B']['dom'],
24235
24236 $cell['border_details']['mbw']['BL'],
24237 $cell['border_details']['mbw']['BR'],
24238 $cell['border_details']['mbw']['RT'],
24239 $cell['border_details']['mbw']['RB'],
24240 $cell['border_details']['mbw']['TL'],
24241 $cell['border_details']['mbw']['TR'],
24242 $cell['border_details']['mbw']['LT'],
24243 $cell['border_details']['mbw']['LB'],
24244
24245 (isset($cell['border_details']['cellposdom']) ? $cell['border_details']['cellposdom'] : 0)
24246 );
24247 return $bindata;
24248 }
24249
24250
24251
24252 function _getBorderWidths($bindata) {
24253 if (!$bindata) { return array(0,0,0,0); }
24254 if (!$this->packTableData) { return array($bindata['border_details']['T']['w'], $bindata['border_details']['R']['w'], $bindata['border_details']['B']['w'], $bindata['border_details']['L']['w']); }
24255
24256 $bd = unpack("nbord/nrs/drw/a6rca/A10rst/nrd/nls/dlw/a6lca/A10lst/nld/nts/dtw/a6tca/A10tst/ntd/nbs/dbw/a6bca/A10bst/nbd/dmbl/dmbr/dmrt/dmrb/dmtl/dmtr/dmlt/dmlb/dcpd", $bindata);
24257 $cell['border_details']['R']['w'] = $bd['rw'];
24258 $cell['border_details']['L']['w'] = $bd['lw'];
24259 $cell['border_details']['T']['w'] = $bd['tw'];
24260 $cell['border_details']['B']['w'] = $bd['bw'];
24261 return array($bd['tw'], $bd['rw'], $bd['bw'], $bd['lw']);
24262 }
24263
24264
24265 function _unpackCellBorder($bindata) {
24266 if (!$bindata) { return array(); }
24267 if (!$this->packTableData) { return $bindata; }
24268
24269 $bd = unpack("nbord/nrs/drw/a6rca/A10rst/nrd/nls/dlw/a6lca/A10lst/nld/nts/dtw/a6tca/A10tst/ntd/nbs/dbw/a6bca/A10bst/nbd/dmbl/dmbr/dmrt/dmrb/dmtl/dmtr/dmlt/dmlb/dcpd", $bindata);
24270
24271 $cell['border'] = $bd['bord'];
24272 $cell['border_details']['R']['s'] = $bd['rs'];
24273 $cell['border_details']['R']['w'] = $bd['rw'];
24274 $cell['border_details']['R']['c'] = str_pad($bd['rca'], 6, "\x00");
24275 $cell['border_details']['R']['style'] = trim($bd['rst']);
24276 $cell['border_details']['R']['dom'] = $bd['rd'];
24277
24278 $cell['border_details']['L']['s'] = $bd['ls'];
24279 $cell['border_details']['L']['w'] = $bd['lw'];
24280 $cell['border_details']['L']['c'] = str_pad($bd['lca'], 6, "\x00");
24281 $cell['border_details']['L']['style'] = trim($bd['lst']);
24282 $cell['border_details']['L']['dom'] = $bd['ld'];
24283
24284 $cell['border_details']['T']['s'] = $bd['ts'];
24285 $cell['border_details']['T']['w'] = $bd['tw'];
24286 $cell['border_details']['T']['c'] = str_pad($bd['tca'], 6, "\x00");
24287 $cell['border_details']['T']['style'] = trim($bd['tst']);
24288 $cell['border_details']['T']['dom'] = $bd['td'];
24289
24290 $cell['border_details']['B']['s'] = $bd['bs'];
24291 $cell['border_details']['B']['w'] = $bd['bw'];
24292 $cell['border_details']['B']['c'] = str_pad($bd['bca'], 6, "\x00");
24293 $cell['border_details']['B']['style'] = trim($bd['bst']);
24294 $cell['border_details']['B']['dom'] = $bd['bd'];
24295
24296 $cell['border_details']['mbw']['BL'] = $bd['mbl'];
24297 $cell['border_details']['mbw']['BR'] = $bd['mbr'];
24298 $cell['border_details']['mbw']['RT'] = $bd['mrt'];
24299 $cell['border_details']['mbw']['RB'] = $bd['mrb'];
24300 $cell['border_details']['mbw']['TL'] = $bd['mtl'];
24301 $cell['border_details']['mbw']['TR'] = $bd['mtr'];
24302 $cell['border_details']['mbw']['LT'] = $bd['mlt'];
24303 $cell['border_details']['mbw']['LB'] = $bd['mlb'];
24304 $cell['border_details']['cellposdom'] = $bd['cpd'];
24305
24306
24307 return($cell);
24308 }
24309
24310
24311 ////////////////////////TABLE CODE (from PDFTable)/////////////////////////////////////
24312 ////////////////////////TABLE CODE (from PDFTable)/////////////////////////////////////
24313 ////////////////////////TABLE CODE (from PDFTable)/////////////////////////////////////
24314 //table Array of (w, h, bc, nr, wc, hr, cells)
24315 //w Width of table
24316 //h Height of table
24317 //nc Number column
24318 //nr Number row
24319 //hr List of height of each row
24320 //wc List of width of each column
24321 //cells List of cells of each rows, cells[i][j] is a cell in the table
24322 function _tableColumnWidth(&$table,$firstpass=false){
24323 $cs = &$table['cells'];
24324
24325 $nc = $table['nc'];
24326 $nr = $table['nr'];
24327 $listspan = array();
24328
24329 if ($table['borders_separate']) {
24330 $tblbw = $table['border_details']['L']['w'] + $table['border_details']['R']['w'] + $table['margin']['L'] + $table['margin']['R'] + $table['padding']['L'] + $table['padding']['R'] + $table['border_spacing_H'];
24331 }
24332 else { $tblbw = $table['max_cell_border_width']['L']/2 + $table['max_cell_border_width']['R']/2 + $table['margin']['L'] + $table['margin']['R']; }
24333
24334 // ADDED table['l'][colno]
24335 // = total length of text approx (using $c['s']) in that column - used to approximately distribute col widths in _tableWidth
24336 //
24337 for($j = 0 ; $j < $nc ; $j++ ) { //columns
24338 $wc = &$table['wc'][$j];
24339 for($i = 0 ; $i < $nr ; $i++ ) { //rows
24340 if (isset($cs[$i][$j]) && $cs[$i][$j]) {
24341 $c = &$cs[$i][$j];
24342
24343 if ($this->simpleTables){
24344 if ($table['borders_separate']) { // NB twice border width
24345 $extrcw = $table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w'] + $c['padding']['L'] + $c['padding']['R'] + $table['border_spacing_H'];
24346 }
24347 else {
24348 $extrcw = $table['simple']['border_details']['L']['w']/2 + $table['simple']['border_details']['R']['w']/2 + $c['padding']['L'] + $c['padding']['R'];
24349 }
24350 }
24351 else {
24352 if ($this->packTableData) {
24353 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
24354 }
24355 else {
24356 $br = $c['border_details']['R']['w'];
24357 $bl = $c['border_details']['L']['w'];
24358 }
24359 if ($table['borders_separate']) { // NB twice border width
24360 $extrcw = $bl + $br + $c['padding']['L'] + $c['padding']['R'] + $table['border_spacing_H'];
24361 }
24362 else {
24363 $extrcw = $bl/2 + $br/2 + $c['padding']['L'] + $c['padding']['R'];
24364 }
24365 }
24366
24367 //$mw = $this->GetStringWidth('W') + $extrcw ;
24368 $mw = $extrcw ; // mPDF 6
24369 if(substr($c['a'],0,1) == 'D') {
24370 $mw = $table['decimal_align'][$j]['maxs0'] + $table['decimal_align'][$j]['maxs1'] + $extrcw ;
24371 }
24372
24373 $c['absmiw'] = $mw;
24374
24375 if (isset($c['R']) && $c['R']) {
24376 $c['maw'] = $c['miw'] = $this->FontSize + $extrcw ;
24377 if (isset($c['w'])) { // If cell width is specified
24378 if ($c['miw'] <$c['w']) { $c['miw'] = $c['w']; }
24379 }
24380 if (!isset($c['colspan'])) {
24381 if ($wc['miw'] < $c['miw']) { $wc['miw'] = $c['miw']; }
24382 if ($wc['maw'] < $c['maw']) { $wc['maw'] = $c['maw']; }
24383
24384 if ($firstpass) {
24385 if (isset($table['l'][$j]) ) {
24386 $table['l'][$j] += $c['miw'] ;
24387 }
24388 else {
24389 $table['l'][$j] = $c['miw'] ;
24390 }
24391 }
24392 }
24393 if ($c['miw'] > $wc['miw']) { $wc['miw'] = $c['miw']; }
24394 if ($wc['miw'] > $wc['maw']) { $wc['maw'] = $wc['miw']; }
24395 continue;
24396 }
24397
24398 if ($firstpass) {
24399 if (isset($c['s'])) { $c['s'] += $extrcw; }
24400 if (isset($c['maxs'])) { $c['maxs'] += $extrcw; }
24401 if (isset($c['nestedmiw'])) { $c['nestedmiw'] += $extrcw; }
24402 if (isset($c['nestedmaw'])) { $c['nestedmaw'] += $extrcw; }
24403 }
24404
24405
24406 // If minimum width has already been set by a nested table or inline object (image/form), use it
24407 if (isset($c['nestedmiw']) && (!isset($this->table[1][1]['overflow']) || $this->table[1][1]['overflow']!='visible')) { $miw = $c['nestedmiw']; }
24408 else { $miw = $mw; }
24409
24410 if (isset($c['maxs']) && $c['maxs'] != '') { $c['s'] = $c['maxs']; }
24411
24412 // If maximum width has already been set by a nested table, use it
24413 if (isset($c['nestedmaw'])) { $c['maw'] = $c['nestedmaw']; }
24414 else $c['maw'] = $c['s'];
24415
24416 if (isset($table['overflow']) && $table['overflow']=='visible' && $table['level']==1) {
24417 if (($c['maw'] + $tblbw) > $this->blk[$this->blklvl]['inner_width']) {
24418 $c['maw'] = $this->blk[$this->blklvl]['inner_width'] - $tblbw;
24419 }
24420 }
24421
24422 if (isset($c['nowrap']) && $c['nowrap']) { $miw = $c['maw']; }
24423
24424 if (isset($c['wpercent']) && $firstpass) {
24425 if (isset($c['colspan'])) { // Not perfect - but % set on colspan is shared equally on cols.
24426 for($k=0;$k<$c['colspan'];$k++) {
24427 $table['wc'][($j+$k)]['wpercent'] = $c['wpercent'] / $c['colspan'];
24428 }
24429 }
24430 else {
24431 if (isset($table['w']) && $table['w']) { $c['w'] = $c['wpercent']/100 * ($table['w'] - $tblbw ); }
24432 $wc['wpercent'] = $c['wpercent'];
24433 }
24434 }
24435
24436 if (isset($table['overflow']) && $table['overflow']=='visible' && $table['level']==1) {
24437 if (isset($c['w']) && ($c['w'] + $tblbw) > $this->blk[$this->blklvl]['inner_width']) {
24438 $c['w'] = $this->blk[$this->blklvl]['inner_width'] - $tblbw;
24439 }
24440 }
24441
24442
24443 if (isset($c['w'])) { // If cell width is specified
24444 if ($miw<$c['w']) { $c['miw'] = $c['w']; } // Cell min width = that specified
24445 if ($miw>$c['w']) { $c['miw'] = $c['w'] = $miw; } // If width specified is less than minimum allowed (W) increase it
24446 // mPDF 5.7.4 Do not set column width in colspan
24447 // cf. http://www.mpdf1.com/forum/discussion/2221/colspan-bug
24448 if (!isset($c['colspan'])) {
24449 if (!isset($wc['w'])) { $wc['w'] = 1; } // If the Col width is not specified = set it to 1
24450 }
24451 // mPDF 5.7.3 cf. http://www.mpdf1.com/forum/discussion/1648/nested-table-bug-
24452 $c['maw'] = $c['w'];
24453 }
24454 else { $c['miw'] = $miw; } // If cell width not specified -> set Cell min width it to minimum allowed (W)
24455
24456 if (isset($c['miw']) && $c['maw'] < $c['miw']) { $c['maw'] = $c['miw']; } // If Cell max width < Minwidth - increase it to =
24457 if (!isset($c['colspan'])) {
24458 if (isset($c['miw']) && $wc['miw'] < $c['miw']) { $wc['miw'] = $c['miw']; } // Update Col Minimum and maximum widths
24459 if ($wc['maw'] < $c['maw']) { $wc['maw'] = $c['maw']; }
24460 if ((isset($wc['absmiw']) && $wc['absmiw'] < $c['absmiw']) || !isset($wc['absmiw'])) { $wc['absmiw'] = $c['absmiw']; } // Update Col Minimum and maximum widths
24461
24462 if (isset($table['l'][$j]) ) {
24463 $table['l'][$j] += $c['s'];
24464 }
24465 else {
24466 $table['l'][$j] = $c['s'];
24467 }
24468
24469 }
24470 else {
24471 $listspan[] = array($i,$j);
24472 }
24473
24474 //Check if minimum width of the whole column is big enough for largest word to fit
24475 // mPDF 6
24476 if (isset($c['textbuffer'])) {
24477 if (isset($table['overflow']) && $table['overflow']=='wrap') { $letter=true; } // check for maximum width of letters
24478 else { $letter=false; }
24479 $minwidth = $this->TableCheckMinWidth($wc['miw']- $extrcw ,0,$c['textbuffer'],$letter);
24480 }
24481 else { $minwidth = 0; }
24482 if ($minwidth < 0) {
24483 //increase minimum width
24484 if (!isset($c['colspan'])) {
24485 $wc['miw'] = max($wc['miw'],((-$minwidth) + $extrcw) );
24486 }
24487 else {
24488 $c['miw'] = max($c['miw'],((-$minwidth) + $extrcw) );
24489 }
24490 }
24491 if (!isset($c['colspan'])) {
24492 if ($wc['miw'] > $wc['maw']) { $wc['maw'] = $wc['miw']; } //update maximum width, if needed
24493 }
24494 }
24495 unset($c);
24496 }//rows
24497 }//columns
24498
24499
24500 // COLUMN SPANS
24501 $wc = &$table['wc'];
24502 foreach ($listspan as $span) {
24503 list($i,$j) = $span;
24504 $c = &$cs[$i][$j];
24505 $lc = $j + $c['colspan'];
24506 if ($lc > $nc) { $lc = $nc; }
24507 $wis = $wisa = 0;
24508 $was = $wasa = 0;
24509 $list = array();
24510 for($k=$j;$k<$lc;$k++) {
24511 if (isset($table['l'][$k]) ) {
24512 if ($c['R']) { $table['l'][$k] += $c['miw']/$c['colspan'] ; }
24513 else { $table['l'][$k] += $c['s']/$c['colspan']; }
24514 }
24515 else {
24516 if ($c['R']) { $table['l'][$k] = $c['miw']/$c['colspan'] ; }
24517 else { $table['l'][$k] = $c['s']/$c['colspan']; }
24518 }
24519 $wis += $wc[$k]['miw']; // $wis is the sum of the column miw in the colspan
24520 $was += $wc[$k]['maw']; // $was is the sum of the column maw in the colspan
24521 if (!isset($c['w'])) {
24522 $list[] = $k;
24523 $wisa += $wc[$k]['miw']; // $wisa is the sum of the column miw in cells with no width specified in the colspan
24524 $wasa += $wc[$k]['maw']; // $wasa is the sum of the column maw in cells with no width specified in the colspan
24525 }
24526 }
24527 if ($c['miw'] > $wis) {
24528 if (!$wis) {
24529 for($k=$j;$k<$lc;$k++) { $wc[$k]['miw'] = $c['miw']/$c['colspan']; }
24530 }
24531 else if (!count($list)) {
24532 $wi = $c['miw'] - $wis;
24533 for($k=$j;$k<$lc;$k++) { $wc[$k]['miw'] += ($wc[$k]['miw']/$wis)*$wi; }
24534 }
24535 else {
24536 $wi = $c['miw'] - $wis;
24537 // mPDF 5.7.2 Extra min width distributed proportionately to all cells in colspan without a specified width
24538 // cf. http://www.mpdf1.com/forum/discussion/1607#Item_4
24539 foreach ($list as $k) { if (!isset($wc[$k]['w']) || !$wc[$k]['w']) $wc[$k]['miw'] += ($wc[$k]['miw']/$wisa)*$wi; } // mPDF 5.7.2
24540 }
24541 }
24542 if ($c['maw'] > $was) {
24543 if (!$wis) {
24544 for($k=$j;$k<$lc;$k++) { $wc[$k]['maw'] = $c['maw']/$c['colspan']; }
24545 }
24546 else if (!count($list)) {
24547 $wi = $c['maw'] - $was;
24548 for($k=$j;$k<$lc;$k++) { $wc[$k]['maw'] += ($wc[$k]['maw']/$was)*$wi; }
24549 }
24550 else {
24551 $wi = $c['maw'] - $was;
24552 // mPDF 5.7.4 Extra max width distributed evenly to all cells in colspan without a specified width
24553 // cf. http://www.mpdf1.com/forum/discussion/2221/colspan-bug
24554 foreach ($list as $k) { $wc[$k]['maw'] += $wi/count($list); }
24555 }
24556 }
24557 unset($c);
24558 }
24559
24560 $checkminwidth = 0;
24561 $checkmaxwidth = 0;
24562 $totallength = 0;
24563
24564 for( $i = 0 ; $i < $nc ; $i++ ) {
24565 $checkminwidth += $table['wc'][$i]['miw'];
24566 $checkmaxwidth += $table['wc'][$i]['maw'];
24567 $totallength += $table['l'][$i];
24568 }
24569
24570 if (!isset($table['w']) && $firstpass) {
24571 $sumpc = 0;
24572 $notset = 0;
24573 for( $i = 0 ; $i < $nc ; $i++ ) {
24574 if (isset($table['wc'][$i]['wpercent']) && $table['wc'][$i]['wpercent']) {
24575 $sumpc += $table['wc'][$i]['wpercent'];
24576 }
24577 else { $notset++; }
24578 }
24579
24580 // If sum of widths as % >= 100% and not all columns are set
24581 // Set a nominal width of 1% for unset columns
24582 if ($sumpc >= 100 && $notset) {
24583 for( $i = 0 ; $i < $nc ; $i++ ) {
24584 if ((!isset($table['wc'][$i]['wpercent']) || !$table['wc'][$i]['wpercent']) &&
24585 (!isset($table['wc'][$i]['w']) || !$table['wc'][$i]['w'])) {
24586 $table['wc'][$i]['wpercent'] = 1;
24587 }
24588 }
24589 }
24590
24591
24592 if ($sumpc) { // if any percents are set
24593 $sumnonpc = (100 - $sumpc);
24594 $sumpc = max($sumpc,100);
24595 $miwleft = 0;
24596 $miwleftcount = 0;
24597 $miwsurplusnonpc = 0;
24598 $maxcalcmiw = 0;
24599 $mawleft = 0;
24600 $mawleftcount = 0;
24601 $mawsurplusnonpc = 0;
24602 $maxcalcmaw = 0;
24603 $mawnon = 0;
24604 $miwnon = 0;
24605 for( $i = 0 ; $i < $nc ; $i++ ) {
24606 if (isset($table['wc'][$i]['wpercent'])) {
24607 $maxcalcmiw = max($maxcalcmiw, ($table['wc'][$i]['miw'] * $sumpc /$table['wc'][$i]['wpercent']) );
24608 $maxcalcmaw = max($maxcalcmaw, ($table['wc'][$i]['maw'] * $sumpc /$table['wc'][$i]['wpercent']) );
24609 }
24610 else {
24611 $miwleft += $table['wc'][$i]['miw'];
24612 $mawleft += $table['wc'][$i]['maw'];
24613 if (!isset($table['wc'][$i]['w'])) { $miwleftcount++; $mawleftcount++; }
24614 }
24615 }
24616 if ($miwleft && $sumnonpc > 0) { $miwnon = $miwleft * 100 / $sumnonpc; }
24617 if ($mawleft && $sumnonpc > 0) { $mawnon = $mawleft * 100 / $sumnonpc; }
24618 if (($miwnon > $checkminwidth || $maxcalcmiw > $checkminwidth) && $this->keep_table_proportions) {
24619 if ($miwnon > $maxcalcmiw) {
24620 $miwsurplusnonpc = round((($miwnon * $sumnonpc / 100) - $miwleft),3);
24621 $checkminwidth = $miwnon;
24622 }
24623 else { $checkminwidth = $maxcalcmiw; }
24624 for( $i = 0 ; $i < $nc ; $i++ ) {
24625 if (isset($table['wc'][$i]['wpercent'])) {
24626 $newmiw = $checkminwidth * $table['wc'][$i]['wpercent']/100;
24627 if ($table['wc'][$i]['miw'] < $newmiw) {
24628 $table['wc'][$i]['miw'] = $newmiw;
24629 }
24630 $table['wc'][$i]['w'] = 1;
24631 }
24632 else if ($miwsurplusnonpc && !$table['wc'][$i]['w']) {
24633 $table['wc'][$i]['miw'] += $miwsurplusnonpc / $miwleftcount;
24634 }
24635 }
24636 }
24637 if (($mawnon > $checkmaxwidth || $maxcalcmaw > $checkmaxwidth )) {
24638 if ($mawnon > $maxcalcmaw) {
24639 $mawsurplusnonpc = round((($mawnon * $sumnonpc / 100) - $mawleft),3);
24640 $checkmaxwidth = $mawnon;
24641 }
24642 else { $checkmaxwidth = $maxcalcmaw; }
24643 for( $i = 0 ; $i < $nc ; $i++ ) {
24644 if (isset($table['wc'][$i]['wpercent'])) {
24645 $newmaw = $checkmaxwidth * $table['wc'][$i]['wpercent']/100;
24646 if ($table['wc'][$i]['maw'] < $newmaw) {
24647 $table['wc'][$i]['maw'] = $newmaw;
24648 }
24649 $table['wc'][$i]['w'] = 1;
24650 }
24651 else if ($mawsurplusnonpc && !$table['wc'][$i]['w']) {
24652 $table['wc'][$i]['maw'] += $mawsurplusnonpc / $mawleftcount;
24653 }
24654 if ($table['wc'][$i]['maw'] < $table['wc'][$i]['miw']) { $table['wc'][$i]['maw'] = $table['wc'][$i]['miw']; }
24655 }
24656 }
24657 if ($checkminwidth > $checkmaxwidth) { $checkmaxwidth = $checkminwidth; }
24658 }
24659 }
24660
24661 if (isset($table['wpercent']) && $table['wpercent']) {
24662 $checkminwidth *= (100 / $table['wpercent']);
24663 $checkmaxwidth *= (100 / $table['wpercent']);
24664 }
24665
24666
24667 $checkminwidth += $tblbw ;
24668 $checkmaxwidth += $tblbw ;
24669
24670 // Table['miw'] set by percent in first pass may be larger than sum of column miw
24671 if ((isset($table['miw']) && $checkminwidth > $table['miw']) || !isset($table['miw'])) { $table['miw'] = $checkminwidth; }
24672 if ((isset($table['maw']) && $checkmaxwidth > $table['maw']) || !isset($table['maw'])) { $table['maw'] = $checkmaxwidth; }
24673 $table['tl'] = $totallength ;
24674
24675
24676 // mPDF 6
24677 if ($this->table_rotate) {
24678 $mxw = $this->tbrot_maxw;
24679 }
24680 else {
24681 $mxw = $this->blk[$this->blklvl]['inner_width'];
24682 }
24683 if(!isset($table['overflow'])) { $table['overflow'] = null; }
24684 if ($table['overflow']=='visible') {
24685 return array(0,0);
24686 }
24687 else if ($table['overflow']=='hidden' && !$this->table_rotate && !$this->ColActive && $checkminwidth > $mxw) {
24688 $table['w'] = $table['miw'];
24689 return array(0,0);
24690 }
24691 //else if ($table['overflow']=='wrap') { return array(0,0); } // mPDF 6
24692
24693 if (isset($table['w']) && $table['w'] ) {
24694 if ($table['w'] >= $checkminwidth && $table['w'] <= $mxw) { $table['maw'] = $mxw = $table['w']; }
24695 else if ($table['w'] >= $checkminwidth && $table['w'] > $mxw && $this->keep_table_proportions) { $checkminwidth = $table['w']; }
24696 else if ($table['w'] < $checkminwidth && $checkminwidth < $mxw && $this->keep_table_proportions) { $table['maw'] = $table['w'] = $checkminwidth; } // mPDF 5.7.4
24697 else {
24698 unset($table['w']);
24699 }
24700
24701 }
24702 $ratio = $checkminwidth/$mxw;
24703 if ($checkminwidth > $mxw) { return array(($ratio +0.001),$checkminwidth); } // 0.001 to allow for rounded numbers when resizing
24704 unset($cs);
24705 return array(0,0);
24706 }
24707
24708
24709
24710 function _tableWidth(&$table){
24711 $widthcols = &$table['wc'];
24712 $numcols = $table['nc'];
24713 $tablewidth = 0;
24714 if ($table['borders_separate']) {
24715 $tblbw = $table['border_details']['L']['w'] + $table['border_details']['R']['w'] + $table['margin']['L'] + $table['margin']['R'] + $table['padding']['L'] + $table['padding']['R'] + $table['border_spacing_H'];
24716 }
24717 else { $tblbw = $table['max_cell_border_width']['L']/2 + $table['max_cell_border_width']['R']/2 + $table['margin']['L'] + $table['margin']['R']; }
24718
24719 if ($table['level']>1 && isset($table['w'])) {
24720 if (isset($table['wpercent']) && $table['wpercent']) {
24721 $table['w'] = $temppgwidth = (($table['w']-$tblbw) * $table['wpercent'] / 100) + $tblbw ;
24722 }
24723 else {
24724 $temppgwidth = $table['w'] ;
24725 }
24726 }
24727 else if ($this->table_rotate) {
24728 $temppgwidth = $this->tbrot_maxw;
24729 // If it is less than 1/20th of the remaining page height to finish the DIV (i.e. DIV padding + table bottom margin)
24730 // then allow for this
24731 $enddiv = $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'];
24732 if ($enddiv/$temppgwidth <0.05) { $temppgwidth -= $enddiv; }
24733 }
24734 else {
24735 if (isset($table['w']) && $table['w']< $this->blk[$this->blklvl]['inner_width']) {
24736 $notfullwidth = 1;
24737 $temppgwidth = $table['w'] ;
24738 }
24739 else if ($table['overflow']=='visible' && $table['level'] ==1) {
24740 $temppgwidth = null;
24741 }
24742 else if ($table['overflow']=='hidden' && !$this->ColActive && isset($table['w']) && $table['w'] > $this->blk[$this->blklvl]['inner_width'] && $table['w']==$table['miw']) {
24743 //$temppgwidth = $this->blk[$this->blklvl]['inner_width'];
24744 $temppgwidth = $table['w'] ;
24745 }
24746 else { $temppgwidth = $this->blk[$this->blklvl]['inner_width']; }
24747 }
24748
24749
24750 $totaltextlength = 0; // Added - to sum $table['l'][colno]
24751 $totalatextlength = 0; // Added - to sum $table['l'][colno] for those columns where width not set
24752 $percentages_set = 0;
24753 for ( $i = 0 ; $i < $numcols ; $i++ ) {
24754 if (isset($widthcols[$i]['wpercent'])) { $tablewidth += $widthcols[$i]['maw']; $percentages_set = 1; }
24755 else if (isset($widthcols[$i]['w'])) { $tablewidth += $widthcols[$i]['miw']; }
24756 else { $tablewidth += $widthcols[$i]['maw']; }
24757 $totaltextlength += $table['l'][$i];
24758 }
24759 if (!$totaltextlength) { $totaltextlength =1; }
24760 $tablewidth += $tblbw; // Outer half of table borders
24761
24762 if ($tablewidth > $temppgwidth) {
24763 $table['w'] = $temppgwidth;
24764 }
24765 // if any widths set as percentages and max width fits < page width
24766 else if ($tablewidth < $temppgwidth && !isset($table['w']) && $percentages_set) {
24767 $table['w'] = $table['maw'];
24768 }
24769 // if table width is set and is > allowed width
24770 if (isset($table['w']) && $table['w'] > $temppgwidth) { $table['w'] = $temppgwidth; }
24771
24772 // IF the table width is now set - Need to distribute columns widths
24773 // mPDF 5.7.3
24774 // If the table width is already set to the maximum width (e.g. nested table), then use maximum column widths exactly
24775 if (isset($table['w']) && ($table['w'] == $tablewidth) && !$percentages_set) {
24776 // This sets the columns all to maximum width
24777 for ($i=0;$i<$numcols;$i++) {
24778 $widthcols[$i] = $widthcols[$i]['maw'];
24779 }
24780 }
24781 // Else If the table width is set distribute width using algorithm
24782 else if (isset($table['w'])) {
24783 $wis = $wisa = 0;
24784 $list = array();
24785 $notsetlist = array();
24786 for( $i = 0 ; $i < $numcols ; $i++ ) {
24787 $wis += $widthcols[$i]['miw'];
24788 if (!isset($widthcols[$i]['w']) || ($widthcols[$i]['w'] && $table['w'] > $temppgwidth && !$this->keep_table_proportions && !$notfullwidth )){
24789 $list[] = $i;
24790 $wisa += $widthcols[$i]['miw'];
24791 $totalatextlength += $table['l'][$i];
24792 }
24793 }
24794 if (!$totalatextlength) { $totalatextlength =1; }
24795
24796 // Allocate spare (more than col's minimum width) across the cols according to their approx total text length
24797 // Do it by setting minimum width here
24798 if ($table['w'] > $wis + $tblbw) {
24799 // First set any cell widths set as percentages
24800 if ($table['w'] < $temppgwidth || $this->keep_table_proportions) {
24801 for($k=0;$k<$numcols;$k++) {
24802 if (isset($widthcols[$k]['wpercent'])) {
24803 $curr = $widthcols[$k]['miw'];
24804 $widthcols[$k]['miw'] = ($table['w']-$tblbw) * $widthcols[$k]['wpercent']/100;
24805 $wis += $widthcols[$k]['miw'] - $curr;
24806 $wisa += $widthcols[$k]['miw'] - $curr;
24807 }
24808 }
24809 }
24810 // Now allocate surplus up to maximum width of each column
24811 $surplus = 0; $ttl = 0; // number of surplus columns
24812 if (!count($list)) {
24813 $wi = ($table['w']-($wis + $tblbw)); // i.e. extra space to distribute
24814 for($k=0;$k<$numcols;$k++) {
24815 $spareratio = ($table['l'][$k] / $totaltextlength); // gives ratio to divide up free space
24816 // Don't allocate more than Maximum required width - save rest in surplus
24817 if ($widthcols[$k]['miw'] + ($wi * $spareratio) >= $widthcols[$k]['maw']) { // mPDF 5.7.3
24818 $surplus += ($wi * $spareratio) - ($widthcols[$k]['maw']-$widthcols[$k]['miw']);
24819 $widthcols[$k]['miw'] = $widthcols[$k]['maw'];
24820 }
24821 else {
24822 $notsetlist[] = $k;
24823 $ttl += $table['l'][$k];
24824 $widthcols[$k]['miw'] += ($wi * $spareratio);
24825 }
24826
24827 }
24828 }
24829 else {
24830 $wi = ($table['w'] - ($wis + $tblbw)); // i.e. extra space to distribute
24831 foreach ($list as $k) {
24832 $spareratio = ($table['l'][$k] / $totalatextlength); // gives ratio to divide up free space
24833 // Don't allocate more than Maximum required width - save rest in surplus
24834 if ($widthcols[$k]['miw'] + ($wi * $spareratio) >= $widthcols[$k]['maw']) { // mPDF 5.7.3
24835 $surplus += ($wi * $spareratio) - ($widthcols[$k]['maw']-$widthcols[$k]['miw']);
24836 $widthcols[$k]['miw'] = $widthcols[$k]['maw'];
24837 }
24838 else {
24839 $notsetlist[] = $k;
24840 $ttl += $table['l'][$k];
24841 $widthcols[$k]['miw'] += ($wi * $spareratio);
24842 }
24843 }
24844 }
24845 // If surplus still left over apportion it across columns
24846 if ($surplus) {
24847 // if some are set only add to remaining - otherwise add to all of them
24848 if (count($notsetlist) && count($notsetlist) < $numcols) {
24849 foreach ($notsetlist AS $i) {
24850 if ($ttl) $widthcols[$i]['miw'] += $surplus * $table['l'][$i] / $ttl ;
24851 }
24852 }
24853 // If some widths are defined, and others have been added up to their maxmum
24854 else if (count($list) && count($list) < $numcols) {
24855 foreach ($list AS $i) {
24856 $widthcols[$i]['miw'] += $surplus / count($list) ;
24857 }
24858 }
24859 else if ($numcols) { // If all columns
24860 $ttl = array_sum($table['l']);
24861 for ($i=0;$i<$numcols;$i++) {
24862 $widthcols[$i]['miw'] += $surplus * $table['l'][$i] / $ttl;
24863 }
24864 }
24865 }
24866
24867 }
24868
24869 // This sets the columns all to minimum width (which has been increased above if appropriate)
24870 for ($i=0;$i<$numcols;$i++) {
24871 $widthcols[$i] = $widthcols[$i]['miw'];
24872 }
24873
24874 // TABLE NOT WIDE ENOUGH EVEN FOR MINIMUM CONTENT WIDTH
24875 // If sum of column widths set are too wide for table
24876 $checktablewidth = 0;
24877 for ( $i = 0 ; $i < $numcols ; $i++ ) {
24878 $checktablewidth += $widthcols[$i];
24879 }
24880 if ($checktablewidth > ($temppgwidth + 0.001 - $tblbw)) {
24881 $usedup = 0; $numleft = 0;
24882 for ($i=0;$i<$numcols;$i++) {
24883 if ((isset($widthcols[$i]) && $widthcols[$i] > (($temppgwidth - $tblbw) / $numcols)) && (!isset($widthcols[$i]['w']))) {
24884 $numleft++;
24885 unset($widthcols[$i]);
24886 }
24887 else { $usedup += $widthcols[$i]; }
24888 }
24889 for ($i=0;$i<$numcols;$i++) {
24890 if (!isset($widthcols[$i]) || !$widthcols[$i]) {
24891 $widthcols[$i] = ((($temppgwidth - $tblbw) - $usedup)/ ($numleft));
24892 }
24893 }
24894 }
24895
24896 }
24897 else { //table has no width defined
24898 $table['w'] = $tablewidth;
24899 for ( $i = 0 ; $i < $numcols ; $i++) {
24900 if (isset($widthcols[$i]['wpercent']) && $this->keep_table_proportions) { $colwidth = $widthcols[$i]['maw']; }
24901 else if (isset($widthcols[$i]['w'])) { $colwidth = $widthcols[$i]['miw']; }
24902 else { $colwidth = $widthcols[$i]['maw']; }
24903 unset($widthcols[$i]);
24904 $widthcols[$i] = $colwidth;
24905 }
24906 }
24907
24908 if ($table['overflow']=='visible' && $table['level'] ==1) {
24909 if ($tablewidth > $this->blk[$this->blklvl]['inner_width']) {
24910 for ($j = 0 ; $j < $numcols; $j++) { //columns
24911 for ($i = 0 ; $i < $table['nr']; $i++) { //rows
24912 if (isset($table['cells'][$i][$j]) && $table['cells'][$i][$j]) {
24913 $colspan = (isset($table['cells'][$i][$j]['colspan']) ? $table['cells'][$i][$j]['colspan'] : 1);
24914 if ($colspan > 1) {
24915 $w = 0;
24916 for ($c = $j; $c < ($j + $colspan); $c++) {
24917 $w += $widthcols[$c];
24918 }
24919 if ($w > $this->blk[$this->blklvl]['inner_width']) {
24920 $diff = $w - ($this->blk[$this->blklvl]['inner_width'] - $tblbw);
24921 for ($c = $j; $c < ($j + $colspan); $c++) {
24922 $widthcols[$c] -= $diff * ($widthcols[$c]/$w);
24923 }
24924 $table['w'] -= $diff;
24925 $table['csp'][$j] = $w - $diff;
24926 }
24927 }
24928 }
24929
24930 }
24931 }
24932 }
24933 $pgNo = 0;
24934 $currWc = 0;
24935 for ($i = 0 ; $i < $numcols; $i++) { //columns
24936 if (isset($table['csp'][$i])) {
24937 $w = $table['csp'][$i];
24938 unset($table['csp'][$i]);
24939 }
24940 else { $w = $widthcols[$i]; }
24941 if (($currWc + $w + $tblbw) > $this->blk[$this->blklvl]['inner_width']) {
24942 $pgNo++;
24943 $currWc = $widthcols[$i] ;
24944 }
24945 else { $currWc += $widthcols[$i] ; }
24946 $table['colPg'][$i] = $pgNo;
24947 }
24948 }
24949 }
24950
24951
24952
24953 function _tableHeight(&$table){
24954 $level = $table['level'];
24955 $levelid = $table['levelid'];
24956 $cells = &$table['cells'];
24957 $numcols = $table['nc'];
24958 $numrows = $table['nr'];
24959 $listspan = array();
24960 $checkmaxheight = 0;
24961 $headerrowheight = 0;
24962 $checkmaxheightplus = 0;
24963 $headerrowheightplus = 0;
24964 $firstrowheight = 0;
24965
24966 $footerrowheight = 0;
24967 $footerrowheightplus = 0;
24968 if ($this->table_rotate) {
24969 $temppgheight = $this->tbrot_maxh;
24970 $remainingpage = $this->tbrot_maxh;
24971 }
24972 else {
24973 $temppgheight = ($this->h - $this->bMargin - $this->tMargin) - $this->kwt_height;
24974 $remainingpage = ($this->h - $this->bMargin - $this->y) - $this->kwt_height;
24975
24976 // If it is less than 1/20th of the remaining page height to finish the DIV (i.e. DIV padding + table bottom margin)
24977 // then allow for this
24978 $enddiv = $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'] + $table['margin']['B'];
24979 if ($remainingpage > $enddiv && $enddiv/$remainingpage <0.05) { $remainingpage -= $enddiv; }
24980 else if ($remainingpage == 0) { $remainingpage = 0.001; }
24981 if ($temppgheight > $enddiv && $enddiv/$temppgheight <0.05) { $temppgheight -= $enddiv; }
24982 else if ($temppgheight == 0) { $temppgheight = 0.001; }
24983 }
24984 if ($remainingpage < 0) { $remainingpage = 0.001; }
24985 if ($temppgheight < 0) { $temppgheight = 0.001; }
24986
24987 for( $i = 0 ; $i < $numrows ; $i++ ) { //rows
24988 $heightrow = &$table['hr'][$i];
24989 for( $j = 0 ; $j < $numcols ; $j++ ) { //columns
24990 if (isset($cells[$i][$j]) && $cells[$i][$j]) {
24991 $c = &$cells[$i][$j];
24992
24993 if ($this->simpleTables){
24994 if ($table['borders_separate']) { // NB twice border width
24995 $extraWLR = ($table['simple']['border_details']['L']['w']+$table['simple']['border_details']['R']['w']) + ($c['padding']['L']+$c['padding']['R'])+$table['border_spacing_H'];
24996 $extrh = ($table['simple']['border_details']['T']['w']+$table['simple']['border_details']['B']['w']) + ($c['padding']['T']+$c['padding']['B'])+$table['border_spacing_V'];
24997 }
24998 else {
24999 $extraWLR = ($table['simple']['border_details']['L']['w']+$table['simple']['border_details']['R']['w'])/2 + ($c['padding']['L']+$c['padding']['R']);
25000 $extrh = ($table['simple']['border_details']['T']['w']+$table['simple']['border_details']['B']['w'])/2 + ($c['padding']['T']+$c['padding']['B']);
25001 }
25002 }
25003 else {
25004 if ($this->packTableData) {
25005 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
25006 }
25007 else {
25008 $bt = $c['border_details']['T']['w'];
25009 $bb = $c['border_details']['B']['w'];
25010 $br = $c['border_details']['R']['w'];
25011 $bl = $c['border_details']['L']['w'];
25012 }
25013 if ($table['borders_separate']) { // NB twice border width
25014 $extraWLR = $bl + $br + $c['padding']['L'] + $c['padding']['R'] + $table['border_spacing_H'];
25015 $extrh = $bt + $bb + $c['padding']['T'] + $c['padding']['B'] + $table['border_spacing_V'];
25016 }
25017 else {
25018 $extraWLR = $bl/2 + $br/2 + $c['padding']['L'] + $c['padding']['R'];
25019 $extrh = $bt/2 + $bb/2 + $c['padding']['T']+$c['padding']['B'];
25020 }
25021 }
25022
25023 if ($table['overflow']=='visible' && $level==1)
25024 list($x,$cw) = $this->_splitTableGetWidth($table, $i,$j);
25025 else
25026 list($x,$cw) = $this->_tableGetWidth($table, $i,$j);
25027
25028
25029 // Get CELL HEIGHT
25030 // ++ extra parameter forces wrap to break word
25031 if ($c['R'] && isset($c['textbuffer'])) {
25032 $str = '';
25033 foreach($c['textbuffer'] AS $t) { $str .= $t[0].' '; }
25034 $str = rtrim($str);
25035 $s_fs = $this->FontSizePt;
25036 $s_f = $this->FontFamily;
25037 $s_st = $this->FontStyle;
25038 $this->SetFont($c['textbuffer'][0][4],$c['textbuffer'][0][2],$c['textbuffer'][0][11] / $this->shrin_k,true,true);
25039 $tempch = $this->GetStringWidth($str , true,$c['textbuffer'][0][18],$c['textbuffer'][0][8]);
25040 if ($c['R'] >= 45 && $c['R'] < 90) {
25041 $tempch = ((sin(deg2rad($c['R']))) * $tempch ) + ((sin(deg2rad($c['R']))) * (($c['textbuffer'][0][11]/_MPDFK) / $this->shrin_k));
25042 }
25043 $this->SetFont($s_f,$s_st,$s_fs,true,true);
25044 $ch = ($tempch ) + $extrh ;
25045 }
25046 else {
25047 if (isset($c['textbuffer']) && !empty($c['textbuffer'])) {
25048 $this->cellLineHeight = $c['cellLineHeight'];
25049 $this->cellLineStackingStrategy = $c['cellLineStackingStrategy'];
25050 $this->cellLineStackingShift = $c['cellLineStackingShift'];
25051 $this->divwidth = $cw-$extraWLR;
25052 $tempch = $this->printbuffer($c['textbuffer'],'',true,true);
25053 }
25054 else { $tempch = 0; }
25055
25056 // Added cellpadding top and bottom. (Lineheight already adjusted)
25057 $ch = $tempch + $extrh ;
25058 }
25059 //If height is defined and it is bigger than calculated $ch then update values
25060 if (isset($c['h']) && $c['h'] > $ch) {
25061 $c['mih'] = $ch; //in order to keep valign working
25062 $ch = $c['h'];
25063 }
25064 else $c['mih'] = $ch;
25065 if (isset($c['rowspan'])) $listspan[] = array($i,$j);
25066 elseif ($heightrow < $ch) $heightrow = $ch;
25067
25068 // this is the extra used in _tableWrite to determine whether to trigger a page change
25069 if ($table['borders_separate']) {
25070 if ($i == ($numrows-1) || (isset($c['rowspan']) && ($i+$c['rowspan']) == ($numrows)) ) {
25071 $extra = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2;
25072 }
25073 else {
25074 $extra = $table['border_spacing_V']/2;
25075 }
25076 }
25077 else {
25078 if (!$this->simpleTables){
25079 $extra = $bb/2;
25080 }
25081 else if ($this->simpleTables){
25082 $extra = $table['simple']['border_details']['B']['w'] /2;
25083 }
25084 }
25085 if (isset($table['is_thead'][$i]) && $table['is_thead'][$i]) {
25086 if ($j==0) {
25087 $headerrowheight += $ch;
25088 $headerrowheightplus += $ch+$extra;
25089 }
25090 }
25091 else if (isset($table['is_tfoot'][$i]) && $table['is_tfoot'][$i]) {
25092 if ($j==0) {
25093 $footerrowheight += $ch;
25094 $footerrowheightplus += $ch+$extra;
25095 }
25096 }
25097 else {
25098 $checkmaxheight = max($checkmaxheight,$ch);
25099 $checkmaxheightplus = max($checkmaxheightplus,$ch+$extra);
25100 }
25101 if ($this->tableLevel==1 && $i == (isset($table['headernrows']) ? $table['headernrows'] : 0)) {
25102 $firstrowheight = max($ch,$firstrowheight);
25103 }
25104 unset($c);
25105 }
25106 }//end of columns
25107 }//end of rows
25108
25109 $heightrow = &$table['hr'];
25110 foreach ($listspan as $span) {
25111 list($i,$j) = $span;
25112 $c = &$cells[$i][$j];
25113 $lr = $i + $c['rowspan'];
25114 if ($lr > $numrows) $lr = $numrows;
25115 $hs = $hsa = 0;
25116 $list = array();
25117 for($k=$i;$k<$lr;$k++) {
25118 $hs += $heightrow[$k];
25119 // mPDF 6
25120 $sh = false; // specified height
25121 for( $m = 0 ; $m < $numcols ; $m++ ) { //columns
25122 $tc = &$cells[$k][$m];
25123 if (isset($tc['rowspan'])) { continue; }
25124 if (isset($tc['h'])) { $sh = true; break; }
25125 }
25126 if (!$sh) { $list[] = $k; }
25127 }
25128
25129 if ($table['borders_separate']) {
25130 if ($i == ($numrows-1) || ($i+$c['rowspan']) == ($numrows) ) {
25131 $extra = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2;
25132 }
25133 else {
25134 $extra = $table['border_spacing_V']/2;
25135 }
25136 }
25137 else {
25138 if (!$this->simpleTables){
25139 if ($this->packTableData) {
25140 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
25141 }
25142 else {
25143 $bb = $c['border_details']['B']['w'];
25144 }
25145 $extra = $bb/2;
25146 }
25147 else if ($this->simpleTables){
25148 $extra = $table['simple']['border_details']['B']['w'] /2;
25149 }
25150 }
25151 if (!empty($table['is_thead'][$i])) {
25152 $headerrowheight = max($headerrowheight,$hs);
25153 $headerrowheightplus = max($headerrowheightplus,$hs+$extra);
25154 }
25155 else if (!empty($table['is_tfoot'][$i])) {
25156 $footerrowheight = max($footerrowheight,$hs);
25157 $footerrowheightplus = max($footerrowheightplus,$hs+$extra);
25158 }
25159 else {
25160 $checkmaxheight = max($checkmaxheight,$hs);
25161 $checkmaxheightplus = max($checkmaxheightplus,$hs+$extra);
25162 }
25163 if ($this->tableLevel==1 && $i == (isset($table['headernrows']) ? $table['headernrows'] : 0)) { $firstrowheight = max($hs,$firstrowheight); }
25164
25165 if ($c['mih'] > $hs) {
25166 if (!$hs) {
25167 for($k=$i;$k<$lr;$k++) $heightrow[$k] = $c['mih']/$c['rowspan'];
25168 }
25169 elseif (!count($list)) { // no rows in the rowspan have a height specified, so share amongst all rows equally
25170 $hi = $c['mih'] - $hs;
25171 for($k=$i;$k<$lr;$k++) $heightrow[$k] += ($heightrow[$k]/$hs)*$hi;
25172 }
25173 else {
25174 $hi = $c['mih'] - $hs; // mPDF 6
25175 foreach ($list as $k) $heightrow[$k] += $hi/(count($list)); // mPDF 6
25176 }
25177 }
25178 unset($c);
25179
25180 // If rowspans overlap so that one or more rows do not have a height set...
25181 // i.e. for one or more rows, the only cells (explicit) in that row have rowspan>1
25182 // so heightrow is still == 0
25183 if ($heightrow[$i]==0) {
25184 // Get row extent to analyse above and below
25185 $top = $i;
25186 foreach ($listspan as $checkspan) {
25187 list($cki,$ckj) = $checkspan;
25188 $c = &$cells[$cki][$ckj];
25189 if (isset($c['rowspan']) && $c['rowspan']>1) {
25190 if (($cki + $c['rowspan']-1) >= $i) { $top = min($top, $cki); }
25191 }
25192 }
25193 $bottom = $i + $c['rowspan']-1;
25194 // Check for overconstrained conditions
25195 for ($k=$top; $k<=$bottom; $k++) {
25196 // if ['hr'] for any of the others is also 0, then abort (too complicated)
25197 if ($k != $i && $heightrow[$k]==0) { break(1); }
25198 // check again that top and bottom are not crossed by rowspans - or abort (too complicated)
25199 if ($k==$top) {
25200 // ???? take account of colspan as well???
25201 for( $m = 0 ; $m < $numcols ; $m++ ) { //columns
25202 if (!isset($cells[$k][$m]) || $cells[$k][$m]==0) {
25203 break(2);
25204 }
25205 }
25206 }
25207 else if ($k==$bottom) {
25208 // ???? take account of colspan as well???
25209 for( $m = 0 ; $m < $numcols ; $m++ ) { //columns
25210 $c = &$cells[$k][$m];
25211 if (isset($c['rowspan']) && $c['rowspan']>1) {
25212 break(2);
25213 }
25214 }
25215 }
25216 }
25217 // By columns add up col height using ['h'] if set or ['mih'] if not
25218 // Intentionally do not substract border-spacing
25219 $colH = array();
25220 $extH = 0;
25221 $newhr = array();
25222 for( $m = 0 ; $m < $numcols ; $m++ ) { //columns
25223 for ($k=$top; $k<=$bottom; $k++) {
25224 if (isset($cells[$k][$m]) && $cells[$k][$m]!=0) {
25225 $c = &$cells[$k][$m];
25226 if (isset($c['h']) && $c['h']) {
25227 $useh = $c['h'];
25228 }
25229 // ???? take account of colspan as well???
25230 else {
25231 $useh = $c['mih'];
25232 }
25233 if (isset($colH[$m])) { $colH[$m] += $useh; }
25234 else { $colH[$m] = $useh; }
25235 if (!isset($c['rowspan']) || $c['rowspan']<2) { $newhr[$k] = max((isset($newhr[$k]) ? $newhr[$k] : 0), $useh); }
25236 }
25237 }
25238 $extH = max($extH, $colH[$m]); // mPDF 6
25239 }
25240 $newhr[$i] = $extH - array_sum($newhr);
25241 for ($k=$top; $k<=$bottom; $k++) { $heightrow[$k] = $newhr[$k]; }
25242 }
25243
25244
25245 unset($c);
25246 }
25247
25248 $table['h'] = array_sum($heightrow);
25249 unset($heightrow);
25250
25251 if ($table['borders_separate']) {
25252 $table['h'] += $table['margin']['T'] + $table['margin']['B'] + $table['border_details']['T']['w'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] + $table['padding']['T'] + $table['padding']['B'];
25253 }
25254 else {
25255 $table['h'] += $table['margin']['T'] + $table['margin']['B'] + $table['max_cell_border_width']['T']/2 + $table['max_cell_border_width']['B']/2;
25256 }
25257
25258 $maxrowheight = $checkmaxheightplus + $headerrowheightplus + $footerrowheightplus;
25259 $maxfirstrowheight = $firstrowheight + $headerrowheightplus + $footerrowheightplus; // includes thead, 1st row and tfoot
25260 return array($table['h'],$maxrowheight,$temppgheight,$remainingpage,$maxfirstrowheight);
25261 }
25262
25263 function _tableGetWidth(&$table, $i,$j){
25264 $cell = &$table['cells'][$i][$j];
25265 if ($cell) {
25266 if (isset($cell['x0'])) { return array($cell['x0'], $cell['w0']); }
25267 $x = 0;
25268 $widthcols = &$table['wc'];
25269 for( $k = 0 ; $k < $j ; $k++ ) $x += $widthcols[$k];
25270 $w = $widthcols[$j];
25271 if (isset($cell['colspan'])) {
25272 for ( $k = $j+$cell['colspan']-1 ; $k > $j ; $k-- ) $w += $widthcols[$k];
25273 }
25274 $cell['x0'] = $x;
25275 $cell['w0'] = $w;
25276 return array($x, $w);
25277 }
25278 return array(0,0);
25279 }
25280
25281 function _splitTableGetWidth(&$table, $i,$j){
25282 $cell = &$table['cells'][$i][$j];
25283 if ($cell) {
25284 if (isset($cell['x0'])) return array($cell['x0'], $cell['w0']);
25285 $x = 0;
25286 $widthcols = &$table['wc'];
25287 $pg = $table['colPg'][$j];
25288 for( $k = 0 ; $k < $j ; $k++ ) {
25289 if ($table['colPg'][$k]==$pg) $x += $widthcols[$k];
25290 }
25291 $w = $widthcols[$j];
25292 if (isset($cell['colspan'])) {
25293 for ( $k = $j+$cell['colspan']-1 ; $k > $j ; $k-- ) if ($table['colPg'][$k]==$pg) $w += $widthcols[$k];
25294 }
25295 $cell['x0'] = $x;
25296 $cell['w0'] = $w;
25297 return array($x, $w);
25298 }
25299 return array(0,0);
25300 }
25301
25302
25303 function _tableGetHeight(&$table, $i,$j){
25304 $cell = &$table['cells'][$i][$j];
25305 if ($cell){
25306 if (isset($cell['y0'])) return array($cell['y0'], $cell['h0']);
25307 $y = 0;
25308 $heightrow = &$table['hr'];
25309 for ($k=0;$k<$i;$k++) $y += $heightrow[$k];
25310 $h = $heightrow[$i];
25311 if (isset($cell['rowspan'])){
25312 for ($k=$i+$cell['rowspan']-1;$k>$i;$k--)
25313 $h += $heightrow[$k];
25314 }
25315 $cell['y0'] = $y;
25316 $cell['h0'] = $h;
25317 return array($y, $h);
25318 }
25319 return array(0,0);
25320 }
25321
25322 function _tableGetMaxRowHeight($table, $row) {
25323 if ($row==$table['nc']-1) { return $table['hr'][$row]; }
25324 $maxrowheight = $table['hr'][$row];
25325 for ($i=$row+1;$i<$table['nr'];$i++) {
25326 $cellsset = 0;
25327 for ($j=0;$j<$table['nc'];$j++) {
25328 if ($table['cells'][$i][$j]) {
25329 if (isset($table['cells'][$i][$j]['colspan'])) { $cellsset += $table['cells'][$i][$j]['colspan']; }
25330 else $cellsset += 1;
25331 }
25332 }
25333 if ($cellsset == $table['nc']) { return $maxrowheight; }
25334 else { $maxrowheight += $table['hr'][$i]; }
25335 }
25336 return $maxrowheight;
25337 }
25338
25339
25340 // CHANGED TO ALLOW TABLE BORDER TO BE SPECIFIED CORRECTLY - added border_details
25341 function _tableRect($x, $y, $w, $h, $bord=-1, $details=array(), $buffer=false, $bSeparate=false, $cort='cell', $tablecorner='', $bsv=0, $bsh=0) {
25342 $cellBorderOverlay = array();
25343
25344 if ($bord==-1) { $this->Rect($x, $y, $w, $h); }
25345 else if ($this->simpleTables && ($cort=='cell')) {
25346 $this->SetLineWidth($details['L']['w']);
25347 if ($details['L']['c']) {
25348 $this->SetDColor($details['L']['c']);
25349 }
25350 else { $this->SetDColor($this->ConvertColor(0)); }
25351 $this->SetLineJoin(0);
25352 $this->Rect($x, $y, $w, $h);
25353 }
25354 else if ($bord){
25355 if (!$bSeparate && $buffer) {
25356 $priority = 'LRTB';
25357 for($p=0;$p<strlen($priority);$p++) {
25358 $side = $priority[$p];
25359 $details['p'] = $side ;
25360
25361 $dom = 0;
25362 if (isset($details[$side]['w'])) { $dom += ($details[$side]['w'] * 100000); }
25363 if (isset($details[$side]['style'])) { $dom += (array_search($details[$side]['style'],$this->borderstyles)*100) ; }
25364 if (isset($details[$side]['dom'])) { $dom += ($details[$side]['dom']*10); }
25365
25366 // Precedence to darker colours at joins
25367 $coldom = 0;
25368 if (isset($details[$side]['c']) && is_array($details[$side]['c'])) {
25369 if ($details[$side]['c']{0}==3) { // RGB
25370 $coldom = 10-(((ord($details[$side]['c']{1})*1.00)+(ord($details[$side]['c']{2})*1.00)+(ord($details[$side]['c']{3})*1.00))/76.5);
25371 }
25372 } // 10 black - 0 white
25373 if ($coldom) { $dom += $coldom; }
25374 // Lastly precedence to RIGHT and BOTTOM cells at joins
25375 if (isset($details['cellposdom'])) { $dom += $details['cellposdom']; }
25376
25377 $save = false;
25378 if ($side == 'T' && $this->issetBorder($bord, _BORDER_TOP)) { $cbord = _BORDER_TOP; $save = true; }
25379 else if ($side == 'L' && $this->issetBorder($bord, _BORDER_LEFT)) { $cbord = _BORDER_LEFT; $save = true; }
25380 else if ($side == 'R' && $this->issetBorder($bord, _BORDER_RIGHT)) { $cbord = _BORDER_RIGHT; $save = true; }
25381 else if ($side == 'B' && $this->issetBorder($bord, _BORDER_BOTTOM)) { $cbord = _BORDER_BOTTOM; $save = true; }
25382
25383 if ($save) {
25384 $this->cellBorderBuffer[] = pack("A16nCnda6A10d14",
25385 str_pad(sprintf("%08.7f", $dom),16,"0",STR_PAD_LEFT),
25386 $cbord,
25387 ord($side),
25388 $details[$side]['s'],
25389 $details[$side]['w'],
25390 $details[$side]['c'],
25391 $details[$side]['style'],
25392 $x, $y, $w, $h,
25393 $details['mbw']['BL'],
25394 $details['mbw']['BR'],
25395 $details['mbw']['RT'],
25396 $details['mbw']['RB'],
25397 $details['mbw']['TL'],
25398 $details['mbw']['TR'],
25399 $details['mbw']['LT'],
25400 $details['mbw']['LB'],
25401 $details['cellposdom'],
25402 0
25403 );
25404 if ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'groove' || $details[$side]['style'] == 'inset' || $details[$side]['style'] == 'outset' || $details[$side]['style'] == 'double' ) {
25405 $details[$side]['overlay'] = true;
25406 $this->cellBorderBuffer[] = pack("A16nCnda6A10d14",
25407 str_pad(sprintf("%08.7f", ($dom+4)),16,"0",STR_PAD_LEFT),
25408 $cbord,
25409 ord($side),
25410 $details[$side]['s'],
25411 $details[$side]['w'],
25412 $details[$side]['c'],
25413 $details[$side]['style'],
25414 $x, $y, $w, $h,
25415 $details['mbw']['BL'],
25416 $details['mbw']['BR'],
25417 $details['mbw']['RT'],
25418 $details['mbw']['RB'],
25419 $details['mbw']['TL'],
25420 $details['mbw']['TR'],
25421 $details['mbw']['LT'],
25422 $details['mbw']['LB'],
25423 $details['cellposdom'],
25424 1
25425 );
25426 }
25427 }
25428 }
25429 return;
25430 }
25431
25432 if (isset($details['p']) && strlen($details['p'])>1) { $priority = $details['p']; }
25433 else { $priority='LTRB'; }
25434 $Tw = 0;
25435 $Rw = 0;
25436 $Bw = 0;
25437 $Lw = 0;
25438 if (isset($details['T']['w'])) { $Tw = $details['T']['w']; }
25439 if (isset($details['R']['w'])) { $Rw = $details['R']['w']; }
25440 if (isset($details['B']['w'])) { $Bw = $details['B']['w']; }
25441 if (isset($details['L']['w'])) { $Lw = $details['L']['w']; }
25442
25443 $x2 = $x + $w; $y2 = $y + $h;
25444 $oldlinewidth = $this->LineWidth;
25445
25446 for($p=0;$p<strlen($priority);$p++) {
25447 $side = $priority[$p];
25448 $xadj = 0;
25449 $xadj2 = 0;
25450 $yadj = 0;
25451 $yadj2 = 0;
25452 $print = false;
25453 if ($Tw && $side=='T' && $this->issetBorder($bord, _BORDER_TOP)) { // TOP
25454 $ly1 = $y;
25455 $ly2 = $y;
25456 $lx1 = $x;
25457 $lx2 = $x2;
25458 $this->SetLineWidth($Tw);
25459 if ($cort == 'cell' || strpos($tablecorner,'L')!==false) {
25460 if ($Tw > $Lw) $xadj = ($Tw - $Lw)/2;
25461 if ($Tw < $Lw) $xadj = ($Tw + $Lw)/2;
25462 }
25463 else { $xadj = $Tw/2 - $bsh/2; }
25464 if ($cort == 'cell' || strpos($tablecorner,'R')!==false) {
25465 if ($Tw > $Rw) $xadj2 = ($Tw - $Rw)/2;
25466 if ($Tw < $Rw) $xadj2 = ($Tw + $Rw)/2;
25467 }
25468 else { $xadj2 = $Tw/2 - $bsh/2; }
25469 if (!$bSeparate && $details['mbw']['TL']) {
25470 $xadj = ($Tw - $details['mbw']['TL'])/2 ;
25471 }
25472 if (!$bSeparate && $details['mbw']['TR']) {
25473 $xadj2 = ($Tw - $details['mbw']['TR'])/2;
25474 }
25475 $print = true;
25476 }
25477 if ($Lw && $side=='L' && $this->issetBorder($bord, _BORDER_LEFT)) { // LEFT
25478 $ly1 = $y;
25479 $ly2 = $y2;
25480 $lx1 = $x;
25481 $lx2 = $x;
25482 $this->SetLineWidth($Lw);
25483 if ($cort == 'cell' || strpos($tablecorner,'T')!==false) {
25484 if ($Lw > $Tw) $yadj = ($Lw - $Tw)/2;
25485 if ($Lw < $Tw) $yadj = ($Lw + $Tw)/2;
25486 }
25487 else { $yadj = $Lw/2 - $bsv/2; }
25488 if ($cort == 'cell' || strpos($tablecorner,'B')!==false) {
25489 if ($Lw > $Bw) $yadj2 = ($Lw - $Bw)/2;
25490 if ($Lw < $Bw) $yadj2 = ($Lw + $Bw)/2;
25491 }
25492 else { $yadj2 = $Lw/2 - $bsv/2; }
25493 if (!$bSeparate && $details['mbw']['LT']) {
25494 $yadj = ($Lw - $details['mbw']['LT'])/2;
25495 }
25496 if (!$bSeparate && $details['mbw']['LB']) {
25497 $yadj2 = ($Lw - $details['mbw']['LB'])/2;
25498 }
25499 $print = true;
25500 }
25501 if ($Rw && $side=='R' && $this->issetBorder($bord, _BORDER_RIGHT)) { // RIGHT
25502 $ly1 = $y;
25503 $ly2 = $y2;
25504 $lx1 = $x2;
25505 $lx2 = $x2;
25506 $this->SetLineWidth($Rw);
25507 if ($cort == 'cell' || strpos($tablecorner,'T')!==false) {
25508 if ($Rw < $Tw) $yadj = ($Rw + $Tw)/2;
25509 if ($Rw > $Tw) $yadj = ($Rw - $Tw)/2;
25510 }
25511 else { $yadj = $Rw/2 - $bsv/2; }
25512
25513 if ($cort == 'cell' || strpos($tablecorner,'B')!==false) {
25514 if ($Rw > $Bw) $yadj2 = ($Rw - $Bw)/2;
25515 if ($Rw < $Bw) $yadj2 = ($Rw + $Bw)/2;
25516 }
25517 else { $yadj2 = $Rw/2 - $bsv/2; }
25518
25519 if (!$bSeparate && $details['mbw']['RT']) {
25520 $yadj = ($Rw - $details['mbw']['RT'])/2;
25521 }
25522 if (!$bSeparate && $details['mbw']['RB']) {
25523 $yadj2 = ($Rw - $details['mbw']['RB'])/2;
25524 }
25525 $print = true;
25526 }
25527 if ($Bw && $side=='B' && $this->issetBorder($bord, _BORDER_BOTTOM)) { // BOTTOM
25528 $ly1 = $y2;
25529 $ly2 = $y2;
25530 $lx1 = $x;
25531 $lx2 = $x2;
25532 $this->SetLineWidth($Bw);
25533 if ($cort == 'cell' || strpos($tablecorner,'L')!==false) {
25534 if ($Bw > $Lw) $xadj = ($Bw - $Lw)/2;
25535 if ($Bw < $Lw) $xadj = ($Bw + $Lw)/2;
25536 }
25537 else { $xadj = $Bw/2 - $bsh/2; }
25538 if ($cort == 'cell' || strpos($tablecorner,'R')!==false) {
25539 if ($Bw > $Rw) $xadj2 = ($Bw - $Rw)/2;
25540 if ($Bw < $Rw) $xadj2 = ($Bw + $Rw)/2;
25541 }
25542 else { $xadj2 = $Bw/2 - $bsh/2; }
25543 if (!$bSeparate && $details['mbw']['BL']) {
25544 $xadj = ($Bw - $details['mbw']['BL'])/2;
25545 }
25546 if (!$bSeparate && $details['mbw']['BR']) {
25547 $xadj2 = ($Bw - $details['mbw']['BR'])/2;
25548 }
25549 $print = true;
25550 }
25551
25552 // Now draw line
25553 if ($print) {
25554 /*-- TABLES-ADVANCED-BORDERS --*/
25555 if ($details[$side]['style'] == 'double') {
25556 if (!isset($details[$side]['overlay']) || !$details[$side]['overlay'] || $bSeparate) {
25557 if ($details[$side]['c']) {
25558 $this->SetDColor($details[$side]['c']);
25559 }
25560 else { $this->SetDColor($this->ConvertColor(0)); }
25561 $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2);
25562 }
25563 if ((isset($details[$side]['overlay']) && $details[$side]['overlay']) || $bSeparate) {
25564 if ($bSeparate && $cort=='table') {
25565 if ($side=='T') {
25566 $xadj -= $this->LineWidth/2;
25567 $xadj2 -= $this->LineWidth;
25568 if ($this->issetBorder($bord, _BORDER_LEFT)) {
25569 $xadj += $this->LineWidth/2;
25570 }
25571 if ($this->issetBorder($bord, _BORDER_RIGHT)) {
25572 $xadj2 += $this->LineWidth;
25573 }
25574 }
25575 if ($side=='L') {
25576 $yadj -= $this->LineWidth/2;
25577 $yadj2 -= $this->LineWidth;
25578 if ($this->issetBorder($bord, _BORDER_TOP)) {
25579 $yadj += $this->LineWidth/2;
25580 }
25581 if ($this->issetBorder($bord, _BORDER_BOTTOM)) {
25582 $yadj2 += $this->LineWidth;
25583 }
25584 }
25585 if ($side=='B') {
25586 $xadj -= $this->LineWidth/2;
25587 $xadj2 -= $this->LineWidth;
25588 if ($this->issetBorder($bord, _BORDER_LEFT)) {
25589 $xadj += $this->LineWidth/2;
25590 }
25591 if ($this->issetBorder($bord, _BORDER_RIGHT)) {
25592 $xadj2 += $this->LineWidth;
25593 }
25594 }
25595 if ($side=='R') {
25596 $yadj -= $this->LineWidth/2;
25597 $yadj2 -= $this->LineWidth;
25598 if ($this->issetBorder($bord, _BORDER_TOP)) {
25599 $yadj += $this->LineWidth/2;
25600 }
25601 if ($this->issetBorder($bord, _BORDER_BOTTOM)) {
25602 $yadj2 += $this->LineWidth;
25603 }
25604 }
25605 }
25606
25607 $this->SetLineWidth($this->LineWidth/3);
25608
25609 $tbcol = $this->ConvertColor(255);
25610 for($l=0; $l <= $this->blklvl; $l++) {
25611 if ($this->blk[$l]['bgcolor']) {
25612 $tbcol = ($this->blk[$l]['bgcolorarray']);
25613 }
25614 }
25615
25616 if ($bSeparate) {
25617 $cellBorderOverlay[] = array(
25618 'x' => $lx1 + $xadj,
25619 'y' => $ly1 + $yadj,
25620 'x2' => $lx2 - $xadj2,
25621 'y2' => $ly2 - $yadj2,
25622 'col' => $tbcol,
25623 'lw' => $this->LineWidth,
25624 );
25625 }
25626 else {
25627 $this->SetDColor($tbcol);
25628 $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2);
25629 }
25630 }
25631 }
25632
25633
25634 else if (isset($details[$side]['style']) && ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'groove' || $details[$side]['style'] == 'inset' || $details[$side]['style'] == 'outset')) {
25635 if (!isset($details[$side]['overlay']) || !$details[$side]['overlay'] || $bSeparate) {
25636 if ($details[$side]['c']) {
25637 $this->SetDColor($details[$side]['c']);
25638 }
25639 else { $this->SetDColor($this->ConvertColor(0)); }
25640 if ($details[$side]['style'] == 'outset' || $details[$side]['style'] == 'groove') {
25641 $nc = $this->_darkenColor($details[$side]['c']);
25642 $this->SetDColor($nc);
25643 }
25644 else if ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'inset') {
25645 $nc = $this->_lightenColor($details[$side]['c']);
25646 $this->SetDColor($nc);
25647 }
25648 $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2);
25649 }
25650 if ((isset($details[$side]['overlay']) && $details[$side]['overlay']) || $bSeparate) {
25651 if ($details[$side]['c']) {
25652 $this->SetDColor($details[$side]['c']);
25653 }
25654 else { $this->SetDColor($this->ConvertColor(0)); }
25655 $doubleadj = ($this->LineWidth)/3;
25656 $this->SetLineWidth($this->LineWidth/2);
25657 $xadj3 = $yadj3 = $wadj3 = $hadj3 = 0;
25658
25659 if ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'inset') {
25660 $nc = $this->_darkenColor($details[$side]['c']);
25661
25662 if ($bSeparate && $cort=='table') {
25663 if ($side=='T') {
25664 $yadj3 = $this->LineWidth/2;
25665 $xadj3 = -$this->LineWidth/2;
25666 $wadj3 = $this->LineWidth;
25667 if ($this->issetBorder($bord, _BORDER_LEFT)) {
25668 $xadj3 += $this->LineWidth; $wadj3 -= $this->LineWidth;
25669 }
25670 if ($this->issetBorder($bord, _BORDER_RIGHT)) {
25671 $wadj3 -= $this->LineWidth*2;
25672 }
25673 }
25674 if ($side=='L') {
25675 $xadj3 = $this->LineWidth/2;
25676 $yadj3 = -$this->LineWidth/2;
25677 $hadj3 = $this->LineWidth;
25678 if ($this->issetBorder($bord, _BORDER_TOP)) {
25679 $yadj3 += $this->LineWidth; $hadj3 -= $this->LineWidth;
25680 }
25681 if ($this->issetBorder($bord, _BORDER_BOTTOM)) {
25682 $hadj3 -= $this->LineWidth*2;
25683 }
25684 }
25685 if ($side=='B') {
25686 $yadj3 = $this->LineWidth/2;
25687 $xadj3 = -$this->LineWidth/2;
25688 $wadj3 = $this->LineWidth;
25689 }
25690 if ($side=='R') {
25691 $xadj3 = $this->LineWidth/2;
25692 $yadj3 = -$this->LineWidth/2;
25693 $hadj3 = $this->LineWidth;
25694 }
25695 }
25696
25697 else if ($side=='T') { $yadj3 = $this->LineWidth/2; $xadj3 = $this->LineWidth/2; $wadj3 = -$this->LineWidth*2; }
25698 else if ($side=='L') { $xadj3 = $this->LineWidth/2; $yadj3 = $this->LineWidth/2; $hadj3 = -$this->LineWidth*2; }
25699
25700 else if ($side=='B' && $bSeparate) { $yadj3 = $this->LineWidth/2; $wadj3 = $this->LineWidth/2; }
25701 else if ($side=='R' && $bSeparate) { $xadj3 = $this->LineWidth/2; $hadj3 = $this->LineWidth/2; }
25702
25703 else if ($side=='B') { $yadj3 = $this->LineWidth/2; $xadj3 = $this->LineWidth/2; }
25704 else if ($side=='R') { $xadj3 = $this->LineWidth/2; $yadj3 = $this->LineWidth/2; }
25705 }
25706 else {
25707 $nc = $this->_lightenColor($details[$side]['c']);
25708
25709 if ($bSeparate && $cort=='table') {
25710 if ($side=='T') {
25711 $yadj3 = $this->LineWidth/2;
25712 $xadj3 = -$this->LineWidth/2;
25713 $wadj3 = $this->LineWidth;
25714 if ($this->issetBorder($bord, _BORDER_LEFT)) {
25715 $xadj3 += $this->LineWidth; $wadj3 -= $this->LineWidth;
25716 }
25717 }
25718 if ($side=='L') {
25719 $xadj3 = $this->LineWidth/2;
25720 $yadj3 = -$this->LineWidth/2;
25721 $hadj3 = $this->LineWidth;
25722 if ($this->issetBorder($bord, _BORDER_TOP)) {
25723 $yadj3 += $this->LineWidth; $hadj3 -= $this->LineWidth;
25724 }
25725 }
25726 if ($side=='B') {
25727 $yadj3 = $this->LineWidth/2;
25728 $xadj3 = -$this->LineWidth/2;
25729 $wadj3 = $this->LineWidth;
25730 if ($this->issetBorder($bord, _BORDER_LEFT)) {
25731 $xadj3 += $this->LineWidth; $wadj3 -= $this->LineWidth;
25732 }
25733 }
25734 if ($side=='R') {
25735 $xadj3 = $this->LineWidth/2;
25736 $yadj3 = -$this->LineWidth/2;
25737 $hadj3 = $this->LineWidth;
25738 if ($this->issetBorder($bord, _BORDER_TOP)) {
25739 $yadj3 += $this->LineWidth; $hadj3 -= $this->LineWidth;
25740 }
25741 }
25742 }
25743
25744 else if ($side=='T') { $yadj3 = $this->LineWidth/2; $xadj3 = $this->LineWidth/2; }
25745 else if ($side=='L') { $xadj3 = $this->LineWidth/2; $yadj3 = $this->LineWidth/2; }
25746
25747 else if ($side=='B' && $bSeparate) { $yadj3 = $this->LineWidth/2; $xadj3 = $this->LineWidth/2; }
25748 else if ($side=='R' && $bSeparate) { $xadj3 = $this->LineWidth/2; $yadj3 = $this->LineWidth/2; }
25749
25750 else if ($side=='B') { $yadj3 = $this->LineWidth/2; $xadj3 = -$this->LineWidth/2; $wadj3 = $this->LineWidth; }
25751 else if ($side=='R') { $xadj3 = $this->LineWidth/2; $yadj3 = -$this->LineWidth/2; $hadj3 = $this->LineWidth; }
25752
25753 }
25754
25755 if ($bSeparate) {
25756 $cellBorderOverlay[] = array(
25757 'x' => $lx1 + $xadj + $xadj3,
25758 'y' => $ly1 + $yadj + $yadj3,
25759 'x2' => $lx2 - $xadj2 + $xadj3 + $wadj3,
25760 'y2' => $ly2 - $yadj2 + $yadj3 + $hadj3,
25761 'col' => $nc,
25762 'lw' => $this->LineWidth,
25763 );
25764 }
25765 else {
25766 $this->SetDColor($nc);
25767 $this->Line($lx1 + $xadj + $xadj3, $ly1 + $yadj + $yadj3, $lx2 - $xadj2 + $xadj3 + $wadj3, $ly2 - $yadj2 + $yadj3 + $hadj3);
25768 }
25769 }
25770 }
25771
25772
25773 else {
25774 /*-- END TABLES-ADVANCED-BORDERS --*/
25775 if ($details[$side]['style'] == 'dashed') {
25776 $dashsize = 2; // final dash will be this + 1*linewidth
25777 $dashsizek = 1.5; // ratio of Dash/Blank
25778 $this->SetDash($dashsize,($dashsize/$dashsizek)+($this->LineWidth*2));
25779 }
25780 else if ($details[$side]['style'] == 'dotted') {
25781 $this->SetLineJoin(1);
25782 $this->SetLineCap(1);
25783 $this->SetDash(0.001,($this->LineWidth*2));
25784 }
25785 if ($details[$side]['c']) {
25786 $this->SetDColor($details[$side]['c']);
25787 }
25788 else { $this->SetDColor($this->ConvertColor(0)); }
25789 $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2);
25790 /*-- TABLES-ADVANCED-BORDERS --*/
25791 }
25792 /*-- END TABLES-ADVANCED-BORDERS --*/
25793
25794 // Reset Corners
25795 $this->SetDash();
25796 //BUTT style line cap
25797 $this->SetLineCap(2);
25798 }
25799 }
25800
25801 if ($bSeparate && count($cellBorderOverlay)) {
25802 foreach($cellBorderOverlay AS $cbo) {
25803 $this->SetLineWidth($cbo['lw']);
25804 $this->SetDColor($cbo['col']);
25805 $this->Line($cbo['x'], $cbo['y'], $cbo['x2'], $cbo['y2']);
25806 }
25807 }
25808
25809 // $this->SetLineWidth($oldlinewidth);
25810 // $this->SetDColor($this->ConvertColor(0));
25811 }
25812 }
25813
25814
25815 /*-- TABLES --*/
25816 /*-- TABLES-ADVANCED-BORDERS --*/
25817 function _lightenColor($c) {
25818 if (is_array($c)) { die('Color error in _lightencolor'); }
25819 if ($c{0}==3 || $c{0}==5) { // RGB
25820 list($h,$s,$l) = $this->rgb2hsl(ord($c{1})/255,ord($c{2})/255,ord($c{3})/255);
25821 $l += ((1 - $l)*0.8);
25822 list($r,$g,$b) = $this->hsl2rgb($h,$s,$l);
25823 $ret = array(3,$r,$g,$b);
25824 }
25825 else if ($c{0}==4 || $c{0}==6) { // CMYK
25826 $ret = array(4, max(0,(ord($c{1})-20)), max(0,(ord($c{2})-20)), max(0,(ord($c{3})-20)), max(0,(ord($c{4})-20)) );
25827 }
25828 else if ($c{0}==1) { // Grayscale
25829 $ret = array(1,min(255,(ord($c{1})+32)));
25830 }
25831 $c = array_pad($ret, 6, 0);
25832 $cstr = pack("a1ccccc", $c[0], ($c[1] & 0xFF), ($c[2] & 0xFF), ($c[3] & 0xFF), ($c[4] & 0xFF), ($c[5] & 0xFF) );
25833 return $cstr;
25834 }
25835
25836
25837 function _darkenColor($c) {
25838 if (is_array($c)) { die('Color error in _darkenColor'); }
25839 if ($c{0}==3 || $c{0}==5) { // RGB
25840 list($h,$s,$l) = $this->rgb2hsl(ord($c{1})/255,ord($c{2})/255,ord($c{3})/255);
25841 $s *= 0.25;
25842 $l *= 0.75;
25843 list($r,$g,$b) = $this->hsl2rgb($h,$s,$l);
25844 $ret = array(3,$r,$g,$b);
25845 }
25846 else if ($c{0}==4 || $c{0}==6) { // CMYK
25847 $ret = array(4, min(100,(ord($c{1})+20)), min(100,(ord($c{2})+20)), min(100,(ord($c{3})+20)), min(100,(ord($c{4})+20)) );
25848 }
25849 else if ($c{0}==1) { // Grayscale
25850 $ret = array(1,max(0,(ord($c{1})-32)));
25851 }
25852 $c = array_pad($ret, 6, 0);
25853 $cstr = pack("a1ccccc", $c[0], ($c[1] & 0xFF), ($c[2] & 0xFF), ($c[3] & 0xFF), ($c[4] & 0xFF), ($c[5] & 0xFF) );
25854 return $cstr;
25855 }
25856
25857 /*-- END TABLES-ADVANCED-BORDERS --*/
25858
25859
25860
25861 function setBorder(&$var, $flag, $set = true) {
25862 $flag = intval($flag);
25863 if ($set) { $set = true; }
25864 $var = intval($var);
25865 $var = $set ? ($var | $flag) : ($var & ~$flag);
25866 }
25867 function issetBorder($var, $flag) {
25868 $flag = intval($flag);
25869 $var = intval($var);
25870 return (($var & $flag) == $flag);
25871 }
25872
25873
25874 function _table2cellBorder(&$tableb, &$cbdb, &$cellb, $bval) {
25875 if ($tableb && $tableb['w'] > $cbdb['w']) {
25876 $cbdb = $tableb;
25877 $this->setBorder($cellb, $bval);
25878 }
25879 else if ($tableb && $tableb['w'] == $cbdb['w']
25880 && array_search($tableb['style'],$this->borderstyles) > array_search($cbdb['style'],$this->borderstyles)) {
25881 $cbdb = $tableb;
25882 $this->setBorder($cellb, $bval);
25883 }
25884 }
25885
25886 // FIX BORDERS ********************************************
25887 function _fixTableBorders(&$table){
25888 if (!$table['borders_separate'] && $table['border_details']['L']['w']) {
25889 $table['max_cell_border_width']['L'] = $table['border_details']['L']['w'];
25890 }
25891 if (!$table['borders_separate'] && $table['border_details']['R']['w']) {
25892 $table['max_cell_border_width']['R'] = $table['border_details']['R']['w'];
25893 }
25894 if (!$table['borders_separate'] && $table['border_details']['T']['w']) {
25895 $table['max_cell_border_width']['T'] = $table['border_details']['T']['w'];
25896 }
25897 if (!$table['borders_separate'] && $table['border_details']['B']['w']) {
25898 $table['max_cell_border_width']['B'] = $table['border_details']['B']['w'];
25899 }
25900 if ($this->simpleTables) { return; }
25901 $cells = &$table['cells'];
25902 $numcols = $table['nc'];
25903 $numrows = $table['nr'];
25904 /*-- TABLES-ADVANCED-BORDERS --*/
25905 if (isset($table['topntail']) && $table['topntail']) { $tntborddet = $this->border_details($table['topntail']); }
25906 if (isset($table['thead-underline']) && $table['thead-underline']) { $thuborddet = $this->border_details($table['thead-underline']); }
25907 /*-- END TABLES-ADVANCED-BORDERS --*/
25908
25909 for( $i = 0 ; $i < $numrows ; $i++ ) { //Rows
25910 for( $j = 0 ; $j < $numcols ; $j++ ) { //Columns
25911 if (isset($cells[$i][$j]) && $cells[$i][$j]) {
25912 $cell = &$cells[$i][$j];
25913 if ($this->packTableData) {
25914 $cbord = $this->_unpackCellBorder($cell['borderbin']);
25915 }
25916 else {
25917 $cbord = &$cells[$i][$j];
25918 }
25919
25920 // mPDF 5.7.3
25921 if (!$cbord['border'] && $cbord['border']!==0 && isset($table['border']) && $table['border'] && $this->table_border_attr_set) {
25922 $cbord['border'] = $table['border'];
25923 $cbord['border_details'] = $table['border_details'];
25924 }
25925
25926 if (isset($cell['colspan']) && $cell['colspan']>1) { $ccolsp = $cell['colspan']; }
25927 else { $ccolsp = 1; }
25928 if (isset($cell['rowspan']) && $cell['rowspan']>1) { $crowsp = $cell['rowspan']; }
25929 else { $crowsp = 1; }
25930
25931 $cbord['border_details']['cellposdom'] = ((($i+1)/$numrows) / 10000 ) + ((($j+1)/$numcols) / 10 );
25932 // Inherit Cell border from Table border
25933 if ($this->table_border_css_set && !$table['borders_separate']) {
25934 if ($i == 0) {
25935 $this->_table2cellBorder($table['border_details']['T'], $cbord['border_details']['T'], $cbord['border'], _BORDER_TOP);
25936 }
25937 if ($i == ($numrows-1) || ($i+$crowsp) == ($numrows) ) {
25938 $this->_table2cellBorder($table['border_details']['B'], $cbord['border_details']['B'], $cbord['border'], _BORDER_BOTTOM);
25939 }
25940 if ($j == 0) {
25941 $this->_table2cellBorder($table['border_details']['L'], $cbord['border_details']['L'], $cbord['border'], _BORDER_LEFT);
25942 }
25943 if ($j == ($numcols-1) || ($j+$ccolsp) == ($numcols) ) {
25944 $this->_table2cellBorder($table['border_details']['R'], $cbord['border_details']['R'], $cbord['border'], _BORDER_RIGHT);
25945 }
25946 }
25947
25948 /*-- TABLES-ADVANCED-BORDERS --*/
25949 $fixbottom = true;
25950 if (isset($table['topntail']) && $table['topntail']) {
25951 if ($i == 0) {
25952 $cbord['border_details']['T'] = $tntborddet;
25953 $this->setBorder($cbord['border'], _BORDER_TOP);
25954 }
25955 if ($this->tableLevel==1 && $table['headernrows']>0 && $i == $table['headernrows']-1) {
25956 $cbord['border_details']['B'] = $tntborddet;
25957 $this->setBorder($cbord['border'], _BORDER_BOTTOM);
25958 $fixbottom = false;
25959 }
25960 else if ($this->tableLevel==1 && $table['headernrows']>0 && $i == $table['headernrows']) {
25961 if (!$table['borders_separate']) {
25962 $cbord['border_details']['T'] = $tntborddet;
25963 $this->setBorder($cbord['border'], _BORDER_TOP);
25964 }
25965 }
25966 if ($this->tableLevel==1 && $table['footernrows']>0 && $i == ($numrows-$table['footernrows']-1)) {
25967 if (!$table['borders_separate']) {
25968 $cbord['border_details']['B'] = $tntborddet;
25969 $this->setBorder($cbord['border'], _BORDER_BOTTOM);
25970 $fixbottom = false;
25971 }
25972 }
25973 else if ($this->tableLevel==1 && $table['footernrows']>0 && $i == ($numrows-$table['footernrows'])) {
25974 $cbord['border_details']['T'] = $tntborddet;
25975 $this->setBorder($cbord['border'], _BORDER_TOP);
25976 }
25977 if ($this->tabletheadjustfinished) { // $this->tabletheadjustfinished called from tableheader
25978 if (!$table['borders_separate']) {
25979 $cbord['border_details']['T'] = $tntborddet;
25980 $this->setBorder($cbord['border'], _BORDER_TOP);
25981 }
25982 }
25983 if ($i == ($numrows-1) || ($i+$crowsp) == ($numrows) ) {
25984 $cbord['border_details']['B'] = $tntborddet;
25985 $this->setBorder($cbord['border'], _BORDER_BOTTOM);
25986 }
25987 }
25988 if (isset($table['thead-underline']) && $table['thead-underline']) {
25989 if ($table['borders_separate']) {
25990 if ($i == 0) {
25991 $cbord['border_details']['B'] = $thuborddet;
25992 $this->setBorder($cbord['border'], _BORDER_BOTTOM);
25993 $fixbottom = false;
25994 }
25995 }
25996 else {
25997 if ($this->tableLevel==1 && $table['headernrows']>0 && $i == $table['headernrows']-1) {
25998 $cbord['border_details']['T'] = $thuborddet;
25999 $this->setBorder($cbord['border'], _BORDER_TOP);
26000 }
26001 else if ($this->tabletheadjustfinished) { // $this->tabletheadjustfinished called from tableheader
26002 $cbord['border_details']['T'] = $thuborddet;
26003 $this->setBorder($cbord['border'], _BORDER_TOP);
26004 }
26005 }
26006 }
26007
26008 // Collapse Border - Algorithm for conflicting borders
26009 // Hidden >> Width >> double>solid>dashed>dotted... >> style set on cell>table >> top/left>bottom/right
26010 // Do not turn off border which is overridden
26011 // Needed for page break for TOP/BOTTOM both to be defined in Collapsed borders
26012 // Means it is painted twice. (Left/Right can still disable overridden border)
26013 if (!$table['borders_separate']) {
26014 if (($i < ($numrows-1) || ($i+$crowsp) < $numrows ) && $fixbottom ) { // Bottom
26015 for ($cspi = 0; $cspi<$ccolsp; $cspi++) {
26016 // already defined Top for adjacent cell below
26017 if (isset($cells[($i+$crowsp)][$j+$cspi])) {
26018 if ($this->packTableData) {
26019 $adjc = $cells[($i+$crowsp)][$j+$cspi];
26020 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
26021 }
26022 else { $celladj =& $cells[($i+$crowsp)][$j+$cspi]; }
26023 }
26024 else { $celladj = false; }
26025 if ($celladj && $celladj['border_details']['T']['s'] == 1) {
26026 $csadj = $celladj['border_details']['T']['w'];
26027 $csthis = $cbord['border_details']['B']['w'];
26028 // Hidden
26029 if ($cbord['border_details']['B']['style']=='hidden') {
26030 $celladj['border_details']['T'] = $cbord['border_details']['B'];
26031 $this->setBorder($celladj['border'] , _BORDER_TOP, false);
26032 $this->setBorder($cbord['border'] , _BORDER_BOTTOM , false);
26033 }
26034 else if ($celladj['border_details']['T']['style']=='hidden') {
26035 $cbord['border_details']['B'] = $celladj['border_details']['T'];
26036 $this->setBorder($cbord['border'] , _BORDER_BOTTOM , false);
26037 $this->setBorder($celladj['border'] , _BORDER_TOP, false);
26038 }
26039 // Width
26040 else if ($csthis > $csadj) {
26041 if (!isset($cells[($i+$crowsp)][$j+$cspi]['colspan']) || (isset($cells[($i+$crowsp)][$j+$cspi]['colspan']) && $cells[($i+$crowsp)][$j+$cspi]['colspan']<2)) { // don't overwrite bordering cells that span
26042 $celladj['border_details']['T'] = $cbord['border_details']['B'];
26043 $this->setBorder($cbord['border'] , _BORDER_BOTTOM);
26044 }
26045 }
26046 else if ($csadj > $csthis) {
26047 if ($ccolsp < 2) { // don't overwrite this cell if it spans
26048 $cbord['border_details']['B'] = $celladj['border_details']['T'];
26049 $this->setBorder($celladj['border'] , _BORDER_TOP);
26050 }
26051 }
26052
26053 // double>solid>dashed>dotted...
26054 else if (array_search($cbord['border_details']['B']['style'],$this->borderstyles) > array_search($celladj['border_details']['T']['style'],$this->borderstyles)) {
26055 if (!isset($cells[($i+$crowsp)][$j+$cspi]['colspan']) || (isset($cells[($i+$crowsp)][$j+$cspi]['colspan']) && $cells[($i+$crowsp)][$j+$cspi]['colspan']<2)) { // don't overwrite bordering cells that span
26056 $celladj['border_details']['T'] = $cbord['border_details']['B'];
26057 $this->setBorder($cbord['border'] , _BORDER_BOTTOM );
26058 }
26059 }
26060 else if (array_search($celladj['border_details']['T']['style'],$this->borderstyles) > array_search($cbord['border_details']['B']['style'],$this->borderstyles)) {
26061 if ($ccolsp < 2) { // don't overwrite this cell if it spans
26062 $cbord['border_details']['B'] = $celladj['border_details']['T'];
26063 $this->setBorder($celladj['border'] , _BORDER_TOP);
26064 }
26065 }
26066
26067
26068
26069 // Style set on cell vs. table
26070 else if ($celladj['border_details']['T']['dom'] > $cbord['border_details']['B']['dom']) {
26071 if ($ccolsp < 2) { // don't overwrite this cell if it spans
26072 $cbord['border_details']['B'] = $celladj['border_details']['T'];
26073 $this->setBorder($celladj['border'] , _BORDER_TOP);
26074 }
26075 }
26076 // Style set on cell vs. table - OR - LEFT/TOP (cell) in preference to BOTTOM/RIGHT
26077 else {
26078 if (!isset($cells[($i+$crowsp)][$j+$cspi]['colspan']) || (isset($cells[($i+$crowsp)][$j+$cspi]['colspan']) && $cells[($i+$crowsp)][$j+$cspi]['colspan']<2)) { // don't overwrite bordering cells that span
26079 $celladj['border_details']['T'] = $cbord['border_details']['B'];
26080 $this->setBorder($cbord['border'] , _BORDER_BOTTOM );
26081 }
26082 }
26083 }
26084 else if ($celladj) {
26085 if (!isset($cells[($i+$crowsp)][$j+$cspi]['colspan']) || (isset($cells[($i+$crowsp)][$j+$cspi]['colspan']) && $cells[($i+$crowsp)][$j+$cspi]['colspan']<2)) { // don't overwrite bordering cells that span
26086 $celladj['border_details']['T'] = $cbord['border_details']['B'];
26087 }
26088 }
26089 // mPDF 5.7.4
26090 if ($celladj && $this->packTableData) {
26091 $cells[$i+$crowsp][$j+$cspi]['borderbin'] = $this->_packCellBorder($celladj);
26092 }
26093 unset($celladj);
26094 }
26095 }
26096
26097 if ($j < ($numcols-1) || ($j+$ccolsp) < $numcols ) { // Right-Left
26098 for ($cspi = 0; $cspi<$crowsp; $cspi++) {
26099 // already defined Left for adjacent cell to R
26100 if (isset($cells[($i+$cspi)][$j+$ccolsp])) {
26101 if ($this->packTableData) {
26102 $adjc = $cells[($i+$cspi)][$j+$ccolsp];
26103 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
26104 }
26105 else { $celladj =& $cells[$i+$cspi][$j+$ccolsp]; }
26106 }
26107 else { $celladj = false; }
26108 if ($celladj && $celladj['border_details']['L']['s'] == 1) {
26109 $csadj = $celladj['border_details']['L']['w'];
26110 $csthis = $cbord['border_details']['R']['w'];
26111 // Hidden
26112 if ($cbord['border_details']['R']['style']=='hidden') {
26113 $celladj['border_details']['L'] = $cbord['border_details']['R'];
26114 $this->setBorder($celladj['border'] , _BORDER_LEFT, false);
26115 $this->setBorder($cbord['border'] , _BORDER_RIGHT , false);
26116 }
26117 else if ($celladj['border_details']['L']['style']=='hidden') {
26118 $cbord['border_details']['R'] = $celladj['border_details']['L'];
26119 $this->setBorder($cbord['border'] , _BORDER_RIGHT , false);
26120 $this->setBorder($celladj['border'] , _BORDER_LEFT, false);
26121 }
26122 // Width
26123 else if ($csthis > $csadj) {
26124 if (!isset($cells[($i+$cspi)][$j+$ccolsp]['rowspan']) || (isset($cells[($i+$cspi)][$j+$ccolsp]['rowspan']) && $cells[($i+$cspi)][$j+$ccolsp]['rowspan']<2)) { // don't overwrite bordering cells that span
26125 $celladj['border_details']['L'] = $cbord['border_details']['R'];
26126 $this->setBorder($cbord['border'] , _BORDER_RIGHT);
26127 $this->setBorder($celladj['border'] , _BORDER_LEFT, false);
26128 }
26129 }
26130 else if ($csadj > $csthis) {
26131 if ($crowsp < 2) { // don't overwrite this cell if it spans
26132 $cbord['border_details']['R'] = $celladj['border_details']['L'];
26133 $this->setBorder($cbord['border'] , _BORDER_RIGHT, false);
26134 $this->setBorder($celladj['border'] , _BORDER_LEFT);
26135 }
26136 }
26137
26138 // double>solid>dashed>dotted...
26139 else if (array_search($cbord['border_details']['R']['style'],$this->borderstyles) > array_search($celladj['border_details']['L']['style'],$this->borderstyles)) {
26140 if (!isset($cells[($i+$cspi)][$j+$ccolsp]['rowspan']) || (isset($cells[($i+$cspi)][$j+$ccolsp]['rowspan']) && $cells[($i+$cspi)][$j+$ccolsp]['rowspan']<2)) { // don't overwrite bordering cells that span
26141 $celladj['border_details']['L'] = $cbord['border_details']['R'];
26142 $this->setBorder($celladj['border'] , _BORDER_LEFT, false);
26143 $this->setBorder($cbord['border'] , _BORDER_RIGHT);
26144 }
26145 }
26146 else if (array_search($celladj['border_details']['L']['style'],$this->borderstyles) > array_search($cbord['border_details']['R']['style'],$this->borderstyles)) {
26147 if ($crowsp < 2) { // don't overwrite this cell if it spans
26148 $cbord['border_details']['R'] = $celladj['border_details']['L'];
26149 $this->setBorder($cbord['border'] , _BORDER_RIGHT , false);
26150 $this->setBorder($celladj['border'] , _BORDER_LEFT);
26151 }
26152 }
26153
26154
26155 // Style set on cell vs. table
26156 else if ($celladj['border_details']['L']['dom'] > $cbord['border_details']['R']['dom']) {
26157 if ($crowsp < 2) { // don't overwrite this cell if it spans
26158 $cbord['border_details']['R'] = $celladj['border_details']['L'];
26159 $this->setBorder($celladj['border'] , _BORDER_LEFT);
26160 }
26161 }
26162 // Style set on cell vs. table - OR - LEFT/TOP (cell) in preference to BOTTOM/RIGHT
26163 else {
26164 if (!isset($cells[($i+$cspi)][$j+$ccolsp]['rowspan']) || (isset($cells[($i+$cspi)][$j+$ccolsp]['rowspan']) && $cells[($i+$cspi)][$j+$ccolsp]['rowspan']<2)) { // don't overwrite bordering cells that span
26165 $celladj['border_details']['L'] = $cbord['border_details']['R'];
26166 $this->setBorder($cbord['border'] , _BORDER_RIGHT);
26167 }
26168 }
26169 }
26170 else if ($celladj) {
26171 // if right-cell border is not set
26172 if (!isset($cells[($i+$cspi)][$j+$ccolsp]['rowspan']) || (isset($cells[($i+$cspi)][$j+$ccolsp]['rowspan']) && $cells[($i+$cspi)][$j+$ccolsp]['rowspan']<2)) { // don't overwrite bordering cells that span
26173 $celladj['border_details']['L'] = $cbord['border_details']['R'];
26174 }
26175 }
26176 // mPDF 5.7.4
26177 if ($celladj && $this->packTableData) {
26178 $cells[$i+$cspi][$j+$ccolsp]['borderbin'] = $this->_packCellBorder($celladj);
26179 }
26180 unset($celladj);
26181 }
26182 }
26183 }
26184
26185
26186 // Set maximum cell border width meeting at LRTB edges of cell - used for extended cell border
26187 // ['border_details']['mbw']['LT'] = meeting border width - Left border - Top end
26188 if (!$table['borders_separate']) {
26189 $cbord['border_details']['mbw']['BL'] = max($cbord['border_details']['mbw']['BL'], $cbord['border_details']['L']['w']);
26190 $cbord['border_details']['mbw']['BR'] = max($cbord['border_details']['mbw']['BR'], $cbord['border_details']['R']['w']);
26191 $cbord['border_details']['mbw']['RT'] = max($cbord['border_details']['mbw']['RT'], $cbord['border_details']['T']['w']);
26192 $cbord['border_details']['mbw']['RB'] = max($cbord['border_details']['mbw']['RB'], $cbord['border_details']['B']['w']);
26193 $cbord['border_details']['mbw']['TL'] = max($cbord['border_details']['mbw']['TL'], $cbord['border_details']['L']['w']);
26194 $cbord['border_details']['mbw']['TR'] = max($cbord['border_details']['mbw']['TR'], $cbord['border_details']['R']['w']);
26195 $cbord['border_details']['mbw']['LT'] = max($cbord['border_details']['mbw']['LT'], $cbord['border_details']['T']['w']);
26196 $cbord['border_details']['mbw']['LB'] = max($cbord['border_details']['mbw']['LB'], $cbord['border_details']['B']['w']);
26197 if (($i+$crowsp) < $numrows && isset($cells[$i+$crowsp][$j])) { // Has Bottom adjoining cell
26198 if ($this->packTableData) {
26199 $adjc = $cells[$i+$crowsp][$j];
26200 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
26201 }
26202 else { $celladj =& $cells[$i+$crowsp][$j]; }
26203 $cbord['border_details']['mbw']['BL'] = max($cbord['border_details']['mbw']['BL'], $celladj['border_details']['L']['w'], $celladj['border_details']['mbw']['TL']);
26204 $cbord['border_details']['mbw']['BR'] = max($cbord['border_details']['mbw']['BR'], $celladj['border_details']['R']['w'], $celladj['border_details']['mbw']['TR']);
26205 $cbord['border_details']['mbw']['LB'] = max($cbord['border_details']['mbw']['LB'], $celladj['border_details']['mbw']['LT']);
26206 $cbord['border_details']['mbw']['RB'] = max($cbord['border_details']['mbw']['RB'], $celladj['border_details']['mbw']['RT']);
26207 unset($celladj);
26208 }
26209 if (($j+$ccolsp) < $numcols && isset($cells[$i][$j+$ccolsp])) { // Has Right adjoining cell
26210 if ($this->packTableData) {
26211 $adjc = $cells[$i][$j+$ccolsp];
26212 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
26213 }
26214 else { $celladj =& $cells[$i][$j+$ccolsp]; }
26215 $cbord['border_details']['mbw']['RT'] = max($cbord['border_details']['mbw']['RT'], $celladj['border_details']['T']['w'], $celladj['border_details']['mbw']['LT']);
26216 $cbord['border_details']['mbw']['RB'] = max($cbord['border_details']['mbw']['RB'], $celladj['border_details']['B']['w'], $celladj['border_details']['mbw']['LB']);
26217 $cbord['border_details']['mbw']['TR'] = max($cbord['border_details']['mbw']['TR'], $celladj['border_details']['mbw']['TL']);
26218 $cbord['border_details']['mbw']['BR'] = max($cbord['border_details']['mbw']['BR'], $celladj['border_details']['mbw']['BL']);
26219 unset($celladj);
26220 }
26221
26222 if ($i > 0 && isset($cells[$i-1][$j]) && (($this->packTableData && $cells[$i-1][$j]['borderbin']) || $cells[$i-1][$j]['border'])) { // Has Top adjoining cell
26223 if ($this->packTableData) {
26224 $adjc = $cells[$i-1][$j];
26225 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
26226 }
26227 else { $celladj =& $cells[$i-1][$j]; }
26228 $cbord['border_details']['mbw']['TL'] = max($cbord['border_details']['mbw']['TL'], $celladj['border_details']['L']['w'], $celladj['border_details']['mbw']['BL']);
26229 $cbord['border_details']['mbw']['TR'] = max($cbord['border_details']['mbw']['TR'], $celladj['border_details']['R']['w'], $celladj['border_details']['mbw']['BR']);
26230 $cbord['border_details']['mbw']['LT'] = max($cbord['border_details']['mbw']['LT'], $celladj['border_details']['mbw']['LB']);
26231 $cbord['border_details']['mbw']['RT'] = max($cbord['border_details']['mbw']['RT'], $celladj['border_details']['mbw']['RB']);
26232
26233 if ($celladj['border_details']['mbw']['BL']) {
26234 $celladj['border_details']['mbw']['BL'] = max($cbord['border_details']['mbw']['TL'], $celladj['border_details']['mbw']['BL']);
26235 }
26236 if ($celladj['border_details']['mbw']['BR'] ) {
26237 $celladj['border_details']['mbw']['BR'] = max($celladj['border_details']['mbw']['BR'], $cbord['border_details']['mbw']['TR']);
26238 }
26239 if ($this->packTableData) { $cells[$i-1][$j]['borderbin'] = $this->_packCellBorder($celladj); }
26240 unset($celladj);
26241 }
26242 if ($j > 0 && isset($cells[$i][$j-1]) && (($this->packTableData && $cells[$i][$j-1]['borderbin']) || $cells[$i][$j-1]['border'])) { // Has Left adjoining cell
26243 if ($this->packTableData) {
26244 $adjc = $cells[$i][$j-1];
26245 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
26246 }
26247 else { $celladj =& $cells[$i][$j-1]; }
26248 $cbord['border_details']['mbw']['LT'] = max($cbord['border_details']['mbw']['LT'], $celladj['border_details']['T']['w'], $celladj['border_details']['mbw']['RT']);
26249 $cbord['border_details']['mbw']['LB'] = max($cbord['border_details']['mbw']['LB'], $celladj['border_details']['B']['w'], $celladj['border_details']['mbw']['RB']);
26250 $cbord['border_details']['mbw']['BL'] = max($cbord['border_details']['mbw']['BL'], $celladj['border_details']['mbw']['BR']);
26251 $cbord['border_details']['mbw']['TL'] = max($cbord['border_details']['mbw']['TL'], $celladj['border_details']['mbw']['TR']);
26252
26253 if ($celladj['border_details']['mbw']['RT']) {
26254 $celladj['border_details']['mbw']['RT'] = max($celladj['border_details']['mbw']['RT'], $cbord['border_details']['mbw']['LT']);
26255 }
26256 if ($celladj['border_details']['mbw']['RB']) {
26257 $celladj['border_details']['mbw']['RB'] = max($celladj['border_details']['mbw']['RB'], $cbord['border_details']['mbw']['LB']);
26258 }
26259 if ($this->packTableData) { $cells[$i][$j-1]['borderbin'] = $this->_packCellBorder($celladj); }
26260 unset($celladj);
26261 }
26262
26263
26264 // Update maximum cell border width at LRTB edges of table - used for overall table width
26265 if ($j == 0 && $cbord['border_details']['L']['w']) {
26266 $table['max_cell_border_width']['L'] = max($table['max_cell_border_width']['L'],$cbord['border_details']['L']['w']);
26267 }
26268 if (($j == ($numcols-1) || ($j+$ccolsp) == $numcols ) && $cbord['border_details']['R']['w']) {
26269 $table['max_cell_border_width']['R'] = max($table['max_cell_border_width']['R'],$cbord['border_details']['R']['w']);
26270 }
26271 if ($i == 0 && $cbord['border_details']['T']['w']) {
26272 $table['max_cell_border_width']['T'] = max($table['max_cell_border_width']['T'],$cbord['border_details']['T']['w']);
26273 }
26274 if (($i == ($numrows-1) || ($i+$crowsp) == $numrows ) && $cbord['border_details']['B']['w']) {
26275 $table['max_cell_border_width']['B'] = max($table['max_cell_border_width']['B'],$cbord['border_details']['B']['w']);
26276 }
26277 }
26278 /*-- END TABLES-ADVANCED-BORDERS --*/
26279
26280 if ($this->packTableData) { $cell['borderbin'] = $this->_packCellBorder($cbord); }
26281
26282 unset($cbord );
26283
26284 unset($cell );
26285 }
26286 }
26287 }
26288 unset($cell );
26289 }
26290 // END FIX BORDERS ************************************************************************************
26291
26292
26293 function _reverseTableDir(&$table) {
26294 $cells = &$table['cells'];
26295 $numcols = $table['nc'];
26296 $numrows = $table['nr'];
26297 for( $i = 0 ; $i < $numrows ; $i++ ) { //Rows
26298 $row = array();
26299 for( $j = ($numcols-1) ; $j >= 0 ; $j-- ) { //Columns
26300 if (isset($cells[$i][$j]) && $cells[$i][$j]) {
26301 $cell = &$cells[$i][$j];
26302 $col = $numcols - $j - 1;
26303 if (isset($cell['colspan']) && $cell['colspan'] > 1) { $col -= ($cell['colspan']-1); }
26304 // Nested content
26305 if (isset($cell['textbuffer'])) {
26306 for ($n=0; $n < count($cell['textbuffer']); $n++) {
26307 $t = $cell['textbuffer'][$n][0];
26308 if (substr($t,0,19) == "\xbb\xa4\xactype=nestedtable") {
26309 $objattr = $this->_getObjAttr($t);
26310 $objattr['col'] = $col;
26311 $cell['textbuffer'][$n][0] = "\xbb\xa4\xactype=nestedtable,objattr=".serialize($objattr)."\xbb\xa4\xac";
26312 $this->table[($this->tableLevel+1)][$objattr['nestedcontent']]['nestedpos'][1] = $col;
26313 }
26314 }
26315 }
26316 $row[$col] = $cells[$i][$j];
26317 unset($cell);
26318 }
26319 }
26320 for($f=0; $f < $numcols; $f++) {
26321 if (!isset($row[$f])) { $row[$f] = 0; }
26322 }
26323 $table['cells'][$i] = $row;
26324 }
26325 }
26326
26327
26328 function _tableWrite(&$table, $split=false, $startrow=0, $startcol=0, $splitpg=0, $rety = 0){
26329 $level = $table['level'];
26330 $levelid = $table['levelid'];
26331
26332 $cells = &$table['cells'];
26333 $numcols = $table['nc'];
26334 $numrows = $table['nr'];
26335 $maxbwtop = 0;
26336 if ($this->ColActive && $level==1) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
26337
26338 if (!$split || ($startrow==0 && $splitpg==0) || $startrow>0){
26339 // TABLE TOP MARGIN
26340 if ($table['margin']['T']) {
26341 if (!$this->table_rotate && $level==1) {
26342 $this->DivLn($table['margin']['T'],$this->blklvl,true,1); // collapsible
26343 }
26344 else {
26345 $this->y += ($table['margin']['T']);
26346 }
26347 }
26348 // Advance down page by half width of top border
26349 if ($table['borders_separate']) {
26350 if ($startrow>0 && (!isset($table['is_thead']) || count($table['is_thead'])==0))
26351 $adv = $table['border_spacing_V']/2;
26352 else
26353 $adv = $table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V']/2;
26354 }
26355 else {
26356 $adv = $table['max_cell_border_width']['T']/2;
26357 }
26358 if (!$this->table_rotate && $level==1) { $this->DivLn($adv); }
26359 else { $this->y += $adv; }
26360 }
26361
26362 if ($level==1) {
26363 $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['padding_left'] + $this->blk[$this->blklvl]['border_left']['w'];
26364 $x0 = $this->x;
26365 $y0 = $this->y;
26366 $right = $x0 + $this->blk[$this->blklvl]['inner_width'];
26367 $outerfilled = $this->y; // Keep track of how far down the outer DIV bgcolor is painted (NB rowspans)
26368 $this->outerfilled = $this->y;
26369 $this->colsums = array();
26370 }
26371 else {
26372 $x0 = $this->x;
26373 $y0 = $this->y;
26374 $right = $x0 + $table['w'];
26375 }
26376
26377 if ($this->table_rotate) {
26378 $temppgwidth = $this->tbrot_maxw;
26379 $this->PageBreakTrigger = $pagetrigger = $y0 + ($this->blk[$this->blklvl]['inner_width']);
26380 if ($level==1) {
26381 $this->tbrot_y0 = $this->y - $adv - $table['margin']['T'] ;
26382 $this->tbrot_x0 = $this->x;
26383 $this->tbrot_w = $table['w'];
26384 if ($table['borders_separate']) { $this->tbrot_h = $table['margin']['T'] + $table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V']/2; }
26385 else { $this->tbrot_h = $table['margin']['T'] + $table['padding']['T'] + $table['max_cell_border_width']['T']; }
26386 }
26387 }
26388 else {
26389 $this->PageBreakTrigger = $pagetrigger = ($this->h - $this->bMargin);
26390 if ($level==1) {
26391 $temppgwidth = $this->blk[$this->blklvl]['inner_width'];
26392 if (isset($table['a']) and ($table['w'] < $this->blk[$this->blklvl]['inner_width'])) {
26393 if ($table['a']=='C') { $x0 += ((($right-$x0) - $table['w'])/2); }
26394 else if ($table['a']=='R') { $x0 = $right - $table['w']; }
26395 }
26396 }
26397 else {
26398 $temppgwidth = $table['w'];
26399 }
26400 }
26401 if(!isset($table['overflow'])) { $table['overflow'] = null; }
26402 if ($table['overflow']=='hidden' && $level==1 && !$this->table_rotate && !$this->ColActive) {
26403 //Bounding rectangle to clip
26404 $this->tableClipPath = sprintf('q %.3F %.3F %.3F %.3F re W n',$x0*_MPDFK,$this->h*_MPDFK,$this->blk[$this->blklvl]['inner_width']*_MPDFK,-$this->h*_MPDFK);
26405 $this->_out($this->tableClipPath);
26406 }
26407 else { $this->tableClipPath = ''; }
26408
26409
26410 if ($table['borders_separate']) { $indent = $table['margin']['L'] + $table['border_details']['L']['w'] + $table['padding']['L'] + $table['border_spacing_H']/2; }
26411 else { $indent = $table['margin']['L'] + $table['max_cell_border_width']['L']/2; }
26412 $x0 += $indent;
26413
26414 $returny = 0;
26415 $lastCol = 0;
26416 $tableheader = array();
26417 $tablefooter = array();
26418 $tableheaderrowheight = 0;
26419 $tablefooterrowheight = 0;
26420 $footery = 0;
26421
26422 // mPD 3.0 Set the Page & Column where table starts
26423 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
26424 $tablestartpage = 'EVEN';
26425 }
26426 else if (($this->mirrorMargins) && (($this->page)%2==1)) { // ODD
26427 $tablestartpage = 'ODD';
26428 }
26429 else { $tablestartpage = ''; }
26430 if ($this->ColActive) { $tablestartcolumn = $this->CurrCol; }
26431 else { $tablestartcolumn = ''; }
26432
26433 $y = $h = 0;
26434 for( $i = 0; $i < $numrows ; $i++ ) { //Rows
26435 if ($this->progressBar) { $this->UpdateProgressBar(7,intval(30 + ($i*40/$numrows)),' '); } // *PROGRESS-BAR*
26436 if (isset($table['is_tfoot'][$i]) && $table['is_tfoot'][$i] && $level==1) {
26437 $tablefooterrowheight += $table['hr'][$i];
26438 $tablefooter[$i][0]['trbackground-images'] = $table['trbackground-images'][$i];
26439 $tablefooter[$i][0]['trgradients'] = $table['trgradients'][$i];
26440 $tablefooter[$i][0]['trbgcolor'] = $table['bgcolor'][$i];
26441 for( $j = $startcol ; $j < $numcols ; $j++ ) { //Columns
26442 if (isset($cells[$i][$j]) && $cells[$i][$j]) {
26443 $cell = &$cells[$i][$j];
26444 if ($split) {
26445 if ($table['colPg'][$j] != $splitpg) { continue; }
26446 list($x,$w) = $this->_splitTableGetWidth($table, $i, $j);
26447 $js = $j - $startcol;
26448 }
26449 else {
26450 list($x,$w) = $this->_tableGetWidth($table, $i, $j);
26451 $js = $j;
26452 }
26453
26454 list($y,$h) = $this->_tableGetHeight($table, $i, $j);
26455 $x += $x0;
26456 $y += $y0;
26457 //Get info of tfoot ==>> table footer
26458 $tablefooter[$i][$js]['x'] = $x;
26459 $tablefooter[$i][$js]['y'] = $y;
26460 $tablefooter[$i][$js]['h'] = $h;
26461 $tablefooter[$i][$js]['w'] = $w;
26462 if (isset($cell['textbuffer'])) { $tablefooter[$i][$js]['textbuffer'] = $cell['textbuffer']; }
26463 else { $tablefooter[$i][$js]['textbuffer'] = ''; }
26464 $tablefooter[$i][$js]['a'] = $cell['a'];
26465 $tablefooter[$i][$js]['R'] = $cell['R'];
26466 $tablefooter[$i][$js]['va'] = $cell['va'];
26467 $tablefooter[$i][$js]['mih'] = $cell['mih'];
26468 if (isset($cell['gradient'])) $tablefooter[$i][$js]['gradient'] = $cell['gradient']; // *BACKGROUNDS*
26469 if (isset($cell['background-image'])) $tablefooter[$i][$js]['background-image'] = $cell['background-image']; // *BACKGROUNDS*
26470 //CELL FILL BGCOLOR
26471 if (!$this->simpleTables){
26472 if ($this->packTableData) {
26473 $c = $this->_unpackCellBorder($cell['borderbin']);
26474 $tablefooter[$i][$js]['border'] = $c['border'];
26475 $tablefooter[$i][$js]['border_details'] = $c['border_details'];
26476 }
26477 else {
26478 $tablefooter[$i][$js]['border'] = $cell['border'];
26479 $tablefooter[$i][$js]['border_details'] = $cell['border_details'];
26480 }
26481 }
26482 else if ($this->simpleTables){
26483 $tablefooter[$i][$js]['border'] = $table['simple']['border'];
26484 $tablefooter[$i][$js]['border_details'] = $table['simple']['border_details'];
26485 }
26486 $tablefooter[$i][$js]['bgcolor'] = $cell['bgcolor'];
26487 $tablefooter[$i][$js]['padding'] = $cell['padding'];
26488 if (isset($cell['rowspan'])) $tablefooter[$i][$js]['rowspan'] = $cell['rowspan'];
26489 if (isset($cell['colspan'])) $tablefooter[$i][$js]['colspan'] = $cell['colspan'];
26490 if (isset($cell['direction'])) $tablefooter[$i][$js]['direction'] = $cell['direction'];
26491 if (isset($cell['cellLineHeight'])) $tablefooter[$i][$js]['cellLineHeight'] = $cell['cellLineHeight'];
26492 if (isset($cell['cellLineStackingStrategy'])) $tablefooter[$i][$js]['cellLineStackingStrategy'] = $cell['cellLineStackingStrategy'];
26493 if (isset($cell['cellLineStackingShift'])) $tablefooter[$i][$js]['cellLineStackingShift'] = $cell['cellLineStackingShift'];
26494 }
26495 }
26496 }
26497 }
26498
26499 if ($level==1) { $this->_out('___TABLE___BACKGROUNDS'.$this->uniqstr); }
26500 $tableheaderadj = 0;
26501 $tablefooteradj = 0;
26502
26503 $tablestartpageno = $this->page;
26504
26505 //Draw Table Contents and Borders
26506 for( $i = 0; $i < $numrows ; $i++ ) { //Rows
26507 if ($split && $startrow > 0) {
26508 $thnr = (isset($table['is_thead']) ? count($table['is_thead']) : 0);
26509 if ($i >= $thnr && $i < $startrow) { continue; }
26510 if ($i == $startrow){ $returny = $rety - $tableheaderrowheight; }
26511 }
26512
26513 // Get Maximum row/cell height in row - including rowspan>1 + 1 overlapping
26514 $maxrowheight = $this->_tableGetMaxRowHeight($table, $i);
26515
26516 $skippage = false;
26517 $newpagestarted = false;
26518 for( $j = $startcol ; $j < $numcols ; $j++ ) { //Columns
26519 if ($split) {
26520 if ($table['colPg'][$j] > $splitpg) { break; }
26521 $lastCol = $j;
26522 }
26523 if (isset($cells[$i][$j]) && $cells[$i][$j]) {
26524 $cell = &$cells[$i][$j];
26525 if ($split) {
26526 $lastCol = $j + (isset($cell['colspan']) ? ($cell['colspan']-1) : 0) ;
26527 list($x,$w) = $this->_splitTableGetWidth($table, $i, $j);
26528 }
26529 else { list($x,$w) = $this->_tableGetWidth($table, $i, $j); }
26530
26531 list($y,$h) = $this->_tableGetHeight($table, $i, $j);
26532 $x += $x0;
26533 $y += $y0;
26534 $y -= $returny;
26535
26536 if ($table['borders_separate']) {
26537 if (!empty($tablefooter) || $i == ($numrows-1) || (isset($cell['rowspan']) && ($i+$cell['rowspan']) == $numrows) || (!isset($cell['rowspan']) && ($i+1) == $numrows) ) {
26538 $extra = $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2;
26539 //$extra = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2;
26540 }
26541 else {
26542 $extra = $table['border_spacing_V']/2;
26543 }
26544 }
26545 else { $extra = $table['max_cell_border_width']['B']/2; }
26546
26547 if ($j==$startcol && ((($y + $maxrowheight + $extra ) > ($pagetrigger+0.001)) || (($this->keepColumns || !$this->ColActive) && !empty($tablefooter) && ($y + $maxrowheight + $tablefooterrowheight + $extra) > $pagetrigger) && ($this->tableLevel==1 && $i < ($numrows - $table['headernrows']))) && ($y0 >0 || $x0 > 0) && !$this->InFooter && $this->autoPageBreak ) {
26548
26549 if (!$skippage) {
26550 $finalSpread = true;
26551 $firstSpread = true;
26552 if ($split) {
26553 for($t=$startcol; $t<$numcols; $t++) {
26554 // Are there more columns to print on a next page?
26555 if ($table['colPg'][$t] > $splitpg) {
26556 $finalSpread = false;
26557 break;
26558 }
26559 }
26560 if ($startcol>0) { $firstSpread = false; }
26561 }
26562
26563 if (($this->keepColumns || !$this->ColActive) && !empty($tablefooter) && $i > 0 ) {
26564 $this->y = $y;
26565 $ya = $this->y;
26566 $this->TableHeaderFooter($tablefooter,$tablestartpage,$tablestartcolumn,'F',$level, $firstSpread, $finalSpread);
26567 if ($this->table_rotate) {
26568 $this->tbrot_h += $this->y - $ya ;
26569 }
26570 $tablefooteradj = $this->y - $ya ;
26571 }
26572 $y -= $y0;
26573 $returny += $y;
26574
26575 $oldcolumn = $this->CurrCol;
26576 if ($this->AcceptPageBreak()) {
26577 $newpagestarted = true;
26578 $this->y = $y + $y0;
26579
26580 // Move down to account for border-spacing or
26581 // extra half border width in case page breaks in middle
26582 if($i>0 && !$this->table_rotate && $level==1 && !$this->ColActive) {
26583 if ($table['borders_separate']) {
26584 $adv = $table['border_spacing_V']/2;
26585 // If table footer
26586 if (($this->keepColumns || !$this->ColActive) && !empty($tablefooter) && $i > 0 ) {
26587 $adv += ($table['padding']['B'] + $table['border_details']['B']['w']);
26588 }
26589 }
26590 else {
26591 $maxbwtop = 0;
26592 $maxbwbottom = 0;
26593 if (!$this->simpleTables){
26594 if (!empty($tablefooter)) { $maxbwbottom = $table['max_cell_border_width']['B']; }
26595 else {
26596 $brow = $i-1;
26597 for( $ctj = 0 ; $ctj < $numcols ; $ctj++ ) {
26598 if (isset($cells[$brow][$ctj]) && $cells[$brow][$ctj]) {
26599 if ($this->packTableData) {
26600 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($cells[$brow][$ctj]['borderbin']);
26601 }
26602 else {
26603 $bb = $cells[$brow][$ctj]['border_details']['B']['w'];
26604 }
26605 $maxbwbottom = max($maxbwbottom , $bb);
26606 }
26607 }
26608 }
26609 if (!empty($tableheader)) { $maxbwtop = $table['max_cell_border_width']['T']; }
26610 else {
26611 $trow = $i-1;
26612 for( $ctj = 0 ; $ctj < $numcols ; $ctj++ ) {
26613 if (isset($cells[$trow][$ctj]) && $cells[$trow][$ctj]) {
26614 if ($this->packTableData) {
26615 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($cells[$trow][$ctj]['borderbin']);
26616 }
26617 else {
26618 $bt = $cells[$trow][$ctj]['border_details']['T']['w'];
26619 }
26620 $maxbwtop = max($maxbwtop , $bt);
26621 }
26622 }
26623 }
26624 }
26625 else if ($this->simpleTables){
26626 $maxbwtop = $table['simple']['border_details']['T']['w'];
26627 $maxbwbottom = $table['simple']['border_details']['B']['w'];
26628 }
26629 $adv = $maxbwbottom /2;
26630 }
26631 $this->y += $adv;
26632 }
26633
26634 // Rotated table split over pages - needs this->y for borders/backgrounds
26635 if($i>0 && $this->table_rotate && $level==1) {
26636 // $this->y = $y0 + $this->tbrot_w;
26637 }
26638
26639 if ($this->tableClipPath ) { $this->_out("Q"); }
26640
26641 $bx = $x0;
26642 $by = $y0;
26643
26644 if ($table['borders_separate']) {
26645 $bx -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['border_spacing_H']/2);
26646 if ($tablestartpageno != $this->page) { // IF already broken across a previous pagebreak
26647 $by += $table['max_cell_border_width']['T']/2;
26648 if (empty($tableheader)) { $by -= ($table['border_spacing_V']/2); }
26649 }
26650 else {
26651 $by -= ($table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V']/2);
26652 }
26653 }
26654
26655 else if ($tablestartpageno != $this->page && !empty($tableheader)) { $by += $maxbwtop /2; }
26656
26657 $by -= $tableheaderadj;
26658 $bh = $this->y - $by + $tablefooteradj;
26659 if (!$table['borders_separate']) { $bh -= $adv ; }
26660 if ($split) {
26661 $bw = 0;
26662 for($t=$startcol; $t<$numcols; $t++) {
26663 if ($table['colPg'][$t] == $splitpg) { $bw += $table['wc'][$t]; }
26664 if ($table['colPg'][$t] > $splitpg) { break; }
26665 }
26666 if ($table['borders_separate']) {
26667 if ($firstSpread) {
26668 $bw += $table['padding']['L'] + $table['border_details']['L']['w'] + $table['border_spacing_H'];
26669 }
26670 else {
26671 $bx += ($table['padding']['L'] + $table['border_details']['L']['w']);
26672 $bw += $table['border_spacing_H'];
26673 }
26674 if ($finalSpread) {
26675 $bw += $table['padding']['R'] + $table['border_details']['R']['w']/2 + $table['border_spacing_H'];
26676 }
26677 }
26678 }
26679 else {
26680 $bw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
26681 }
26682
26683 if ($this->splitTableBorderWidth && ($this->keepColumns || !$this->ColActive) && empty($tablefooter) && $i > 0 && $table['border_details']['B']['w']) {
26684 $prevDrawColor = $this->DrawColor;
26685 $lw = $this->LineWidth;
26686 $this->SetLineWidth($this->splitTableBorderWidth);
26687 $this->SetDColor($table['border_details']['B']['c']);
26688 $this->SetLineJoin(0);
26689 $this->SetLineCap(0);
26690 $blx = $bx;
26691 $blw = $bw;
26692 if (!$table['borders_separate']) {
26693 $blx -= ($table['max_cell_border_width']['L']/2);
26694 $blw += ($table['max_cell_border_width']['L']/2 + $table['max_cell_border_width']['R']/2);
26695 }
26696 $this->Line($blx,$this->y+($this->splitTableBorderWidth/2),$blx+$blw,$this->y+($this->splitTableBorderWidth/2));
26697 $this->DrawColor = $prevDrawColor;
26698 $this->_out($this->DrawColor);
26699 $this->SetLineWidth($lw);
26700 $this->SetLineJoin(2);
26701 $this->SetLineCap(2);
26702 }
26703
26704 if (!$this->ColActive && ($i > 0 || $j > 0)) {
26705 if (isset($table['bgcolor'][-1])) {
26706 $color = $this->ConvertColor($table['bgcolor'][-1]);
26707 if ($color) {
26708 if (!$table['borders_separate']) { $bh -= $table['max_cell_border_width']['B']/2; }
26709 $this->tableBackgrounds[$level*9][] = array('gradient'=>false, 'x'=>$bx, 'y'=>$by, 'w'=>$bw, 'h'=>$bh, 'col'=>$color);
26710 }
26711 }
26712
26713 /*-- BACKGROUNDS --*/
26714 if (isset($table['gradient'])) {
26715 $g = $this->grad->parseBackgroundGradient($table['gradient']);
26716 if ($g) {
26717 $this->tableBackgrounds[$level*9+1][] = array('gradient'=>true, 'x'=>$bx, 'y'=>$by, 'w'=>$bw, 'h'=>$bh, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
26718 }
26719 }
26720
26721 if (isset($table['background-image'])) {
26722 if ($table['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['background-image']['gradient'] )) {
26723 $g = $this->grad->parseMozGradient( $table['background-image']['gradient'] );
26724 if ($g) {
26725 $this->tableBackgrounds[$level*9+1][] = array('gradient'=>true, 'x'=>$bx, 'y'=>$by, 'w'=>$bw, 'h'=>$bh, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
26726 }
26727 }
26728 else {
26729 $image_id = $table['background-image']['image_id'];
26730 $orig_w = $table['background-image']['orig_w'];
26731 $orig_h = $table['background-image']['orig_h'];
26732 $x_pos = $table['background-image']['x_pos'];
26733 $y_pos = $table['background-image']['y_pos'];
26734 $x_repeat = $table['background-image']['x_repeat'];
26735 $y_repeat = $table['background-image']['y_repeat'];
26736 $resize = $table['background-image']['resize'];
26737 $opacity = $table['background-image']['opacity'];
26738 $itype = $table['background-image']['itype'];
26739 $this->tableBackgrounds[$level*9+2][] = array('x'=>$bx, 'y'=>$by, 'w'=>$bw, 'h'=>$bh, '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);
26740 }
26741 }
26742 /*-- END BACKGROUNDS --*/
26743 }
26744
26745 // $this->AcceptPageBreak() has moved tablebuffer to $this->pages content
26746 if ($this->tableBackgrounds) {
26747 $s = $this->PrintTableBackgrounds();
26748 if ($this->bufferoutput) {
26749 $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS'.$this->uniqstr.')/', '\\1'."\n".$s."\n", $this->headerbuffer);
26750 $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS'.$this->uniqstr.')/', " ", $this->headerbuffer );
26751 }
26752 else {
26753 $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS'.$this->uniqstr.')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
26754 $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS'.$this->uniqstr.')/', " ", $this->pages[$this->page]);
26755 }
26756 $this->tableBackgrounds = array();
26757 }
26758
26759 if ($split) {
26760 if ($i == 0 && $j == 0) { $y0 = -1; }
26761 else if ($finalSpread) {
26762 $splitpg = 0;
26763 $startcol = 0;
26764 $startrow = $i;
26765 }
26766 else {
26767 $splitpg++;
26768 $startcol = $t;
26769 $returny -= $y;
26770 }
26771 return array(false, $startrow, $startcol, $splitpg, $returny, $y0);
26772 }
26773
26774 $this->AddPage($this->CurOrientation);
26775
26776 $this->_out('___TABLE___BACKGROUNDS'.$this->uniqstr);
26777
26778
26779 if ($this->tableClipPath ) { $this->_out($this->tableClipPath); }
26780
26781 // Added to correct for OddEven Margins
26782 $x= $x + $this->MarginCorrection;
26783 $x0= $x0 + $this->MarginCorrection;
26784
26785 if ($this->splitTableBorderWidth && ($this->keepColumns || !$this->ColActive) && empty($tableheader) && $i > 0 && $table['border_details']['T']['w'] ) {
26786 $prevDrawColor = $this->DrawColor;
26787 $lw = $this->LineWidth;
26788 $this->SetLineWidth($this->splitTableBorderWidth);
26789 $this->SetDColor($table['border_details']['T']['c']);
26790 $this->SetLineJoin(0);
26791 $this->SetLineCap(0);
26792 $blx += $this->MarginCorrection;
26793 $this->Line($blx,$this->y-($this->splitTableBorderWidth/2),$blx+$blw,$this->y-($this->splitTableBorderWidth/2));
26794 $this->DrawColor = $prevDrawColor;
26795 $this->_out($this->DrawColor);
26796 $this->SetLineWidth($lw);
26797 $this->SetLineJoin(2);
26798 $this->SetLineCap(2);
26799 }
26800
26801 // Move down to account for half of top border-spacing or
26802 // extra half border width in case page was broken in middle
26803 if($i>0 && !$this->table_rotate && $level==1 && $table['headernrows']==0) {
26804 if ($table['borders_separate']) { $adv = $table['border_spacing_V']/2; }
26805 else {
26806 $maxbwtop = 0;
26807 for( $ctj = 0 ; $ctj < $numcols ; $ctj++ ) {
26808 if (isset($cells[$i][$ctj]) && $cells[$i][$ctj]) {
26809 if (!$this->simpleTables){
26810 if ($this->packTableData) {
26811 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($cells[$i][$ctj]['borderbin']);
26812 }
26813 else {
26814 $bt = $cells[$i][$ctj]['border_details']['T']['w'];
26815 }
26816 $maxbwtop = max($maxbwtop, $bt);
26817 }
26818 else if ($this->simpleTables){
26819 $maxbwtop = max($maxbwtop, $table['simple']['border_details']['T']['w']);
26820 }
26821 }
26822 }
26823 $adv = $maxbwtop /2;
26824 }
26825 $this->y += $adv;
26826 }
26827
26828
26829 if ($this->table_rotate) {
26830 $this->tbrot_x0 = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['padding_left'] + $this->blk[$this->blklvl]['border_left']['w'];
26831 if ($table['borders_separate']) { $this->tbrot_h = $table['margin']['T'] + $table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V']/2; }
26832 else { $this->tbrot_h = $table['margin']['T'] + $table['max_cell_border_width']['T'] ; }
26833 $this->tbrot_y0 = $this->y;
26834 $pagetrigger = $y0 - $tableheaderadj + ($this->blk[$this->blklvl]['inner_width']);
26835 }
26836 else {
26837 $pagetrigger = $this->PageBreakTrigger;
26838 }
26839
26840 if ($this->kwt_saved && $level==1) {
26841 $this->kwt_moved = true;
26842 }
26843
26844
26845 if (!empty($tableheader)) {
26846 $ya = $this->y;
26847 $this->TableHeaderFooter($tableheader,$tablestartpage,$tablestartcolumn,'H',$level);
26848 if ($this->table_rotate) {
26849 $this->tbrot_h = $this->y - $ya ;
26850 }
26851 $tableheaderadj = $this->y - $ya ;
26852 }
26853
26854 else if ($i==0 && !$this->table_rotate && $level==1 && !$this->ColActive) {
26855 // Advance down page
26856 if ($table['borders_separate']) { $adv = $table['border_spacing_V']/2 + $table['border_details']['T']['w'] + $table['padding']['T']; }
26857 else { $adv = $table['max_cell_border_width']['T'] /2 ; }
26858 if ($adv) {
26859 if ($this->table_rotate) {
26860 $this->y += ($adv);
26861 }
26862 else {
26863 $this->DivLn($adv,$this->blklvl,true);
26864 }
26865 }
26866 }
26867
26868 $outerfilled = 0;
26869 $y = $y0 = $this->y;
26870 }
26871
26872 /*-- COLUMNS --*/
26873 // COLS
26874 // COLUMN CHANGE
26875 if ($this->CurrCol != $oldcolumn) {
26876 // Added to correct for Columns
26877 $x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
26878 $x0 += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
26879 if ($this->CurrCol == 0) { // just added a page - possibly with tableheader
26880 $y0 = $this->y; // this->y0 is global used by Columns - $y0 is internal to tablewrite
26881 }
26882 else {
26883 $y0 = $this->y0; // this->y0 is global used by Columns - $y0 is internal to tablewrite
26884 }
26885 $y = $y0;
26886 $outerfilled = 0;
26887 if ($this->CurrCol != 0 && ($this->keepColumns && $this->ColActive) && !empty($tableheader) && $i > 0 ) {
26888 $this->x = $x;
26889 $this->y = $y;
26890 $this->TableHeaderFooter($tableheader,$tablestartpage,$tablestartcolumn,'H',$level);
26891 $y0 = $y=$this->y;
26892 }
26893 }
26894 /*-- END COLUMNS --*/
26895 }
26896 $skippage = true;
26897 }
26898
26899 $this->x = $x;
26900 $this->y = $y;
26901
26902 if ($this->kwt_saved && $level==1) {
26903 $this->printkwtbuffer();
26904 $x0 = $x = $this->x;
26905 $y0 = $y = $this->y;
26906 $this->kwt_moved = false;
26907 $this->kwt_saved = false;
26908 }
26909
26910
26911 // Set the Page & Column where table actually starts
26912 if ($i==0 && $j==0 && $level==1) {
26913 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
26914 $tablestartpage = 'EVEN';
26915 }
26916 else if (($this->mirrorMargins) && (($this->page)%2==1)) { // ODD
26917 $tablestartpage = 'ODD';
26918 }
26919 else { $tablestartpage = ''; }
26920 $tablestartpageno = $this->page;
26921 if ($this->ColActive) { $tablestartcolumn = $this->CurrCol; } // *COLUMNS*
26922 }
26923
26924
26925 //ALIGN
26926 $align = $cell['a'];
26927
26928
26929 /*-- COLUMNS --*/
26930 // If outside columns, this is done in PaintDivBB
26931 if ($this->ColActive) {
26932 //OUTER FILL BGCOLOR of DIVS
26933 if ($this->blklvl > 0 && ($j==0) && !$this->table_rotate && $level==1) {
26934 $firstblockfill = $this->GetFirstBlockFill();
26935 if ($firstblockfill && $this->blklvl >= $firstblockfill) {
26936 $divh = $maxrowheight;
26937 // Last row
26938 if ((!isset($cell['rowspan']) && $i == $numrows-1) || (isset($cell['rowspan']) && (($i == $numrows-1 && $cell['rowspan']<2) || ($cell['rowspan']>1 && ($i + $cell['rowspan']-1) == $numrows-1)))) {
26939 if ($table['borders_separate']) {
26940 $adv = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2;
26941 }
26942 else {
26943 $adv = $table['margin']['B'] + $table['max_cell_border_width']['B']/2;
26944 }
26945 $divh += $adv; //last row: fill bottom half of bottom border (y advanced at end)
26946 }
26947
26948 if (($this->y + $divh) > $outerfilled ) { // if not already painted by previous rowspan
26949 $bak_x = $this->x;
26950 $bak_y = $this->y;
26951 if ($outerfilled > $this->y) {
26952 $divh = ($this->y + $divh) - $outerfilled;
26953 $this->y = $outerfilled;
26954 }
26955
26956 $this->DivLn($divh,-3,false);
26957 $outerfilled = $this->y + $divh;
26958 // Reset current block fill
26959 $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
26960 if ($bcor ) $this->SetFColor($bcor);
26961 $this->x = $bak_x;
26962 $this->y = $bak_y;
26963 }
26964 }
26965 }
26966 }
26967
26968
26969 //TABLE BACKGROUND FILL BGCOLOR - for cellSpacing
26970 if ($this->ColActive) {
26971 if ($table['borders_separate']) {
26972 $fill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0;
26973 if ($fill) {
26974 $color = $this->ConvertColor($fill);
26975 if ($color) {
26976 $xadj = ($table['border_spacing_H']/2);
26977 $yadj = ($table['border_spacing_V']/2);
26978 $wadj = $table['border_spacing_H'];
26979 $hadj = $table['border_spacing_V'];
26980 if ($i == 0) { // Top
26981 $yadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
26982 $hadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
26983 }
26984 if ($j == 0) { // Left
26985 $xadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
26986 $wadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
26987 }
26988 if ($i == ($numrows-1) || (isset($cell['rowspan']) && ($i+$cell['rowspan']) == $numrows) || (!isset($cell['rowspan']) && ($i+1) == $numrows)) { // Bottom
26989 $hadj += $table['padding']['B'] + $table['border_details']['B']['w'] ;
26990 }
26991 if ($j == ($numcols-1) || (isset($cell['colspan']) && ($j+$cell['colspan']) == $numcols) || (!isset($cell['colspan']) && ($j+1) == $numcols)) { // Right
26992 $wadj += $table['padding']['R'] + $table['border_details']['R']['w'] ;
26993 }
26994 $this->SetFColor($color);
26995 $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F');
26996 }
26997 }
26998 }
26999 }
27000 /*-- END COLUMNS --*/
27001
27002 if ($table['empty_cells']!='hide' || !empty($cell['textbuffer']) || (isset($cell['nestedcontent']) && $cell['nestedcontent']) || !$table['borders_separate'] ) { $paintcell = true; }
27003 else { $paintcell = false; }
27004
27005 //Set Borders
27006 $bord = 0;
27007 $bord_det = array();
27008
27009 if (!$this->simpleTables){
27010 if ($this->packTableData) {
27011 $c = $this->_unpackCellBorder($cell['borderbin']);
27012 $bord = $c['border'];
27013 $bord_det = $c['border_details'];
27014 }
27015 else {
27016 $bord = $cell['border'];
27017 $bord_det = $cell['border_details'];
27018 }
27019 }
27020 else if ($this->simpleTables){
27021 $bord = $table['simple']['border'];
27022 $bord_det = $table['simple']['border_details'];
27023 }
27024
27025 //TABLE ROW OR CELL FILL BGCOLOR
27026 $fill = 0;
27027 if (isset($cell['bgcolor']) && $cell['bgcolor'] && $cell['bgcolor']!='transparent') {
27028 $fill = $cell['bgcolor'];
27029 $leveladj = 6;
27030 }
27031 else if (isset($table['bgcolor'][$i]) && $table['bgcolor'][$i] && $table['bgcolor'][$i]!='transparent') { // Row color
27032 $fill = $table['bgcolor'][$i];
27033 $leveladj = 3;
27034 }
27035 if ($fill && $paintcell) {
27036 $color = $this->ConvertColor($fill);
27037 if ($color) {
27038 if ($table['borders_separate']) {
27039 if ($this->ColActive) {
27040 $this->SetFColor($color);
27041 $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');
27042 }
27043 else {
27044 $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);
27045 }
27046 }
27047 else {
27048 if ($this->ColActive) {
27049 $this->SetFColor($color);
27050 $this->Rect($x, $y, $w, $h, 'F');
27051 }
27052 else {
27053 $this->tableBackgrounds[$level*9+$leveladj][] = array('gradient'=>false, 'x'=>$x, 'y'=>$y, 'w'=>$w, 'h'=>$h, 'col'=>$color);
27054 }
27055 }
27056 }
27057 }
27058
27059 /*-- BACKGROUNDS --*/
27060 if (isset($cell['gradient']) && $cell['gradient'] && $paintcell){
27061 $g = $this->grad->parseBackgroundGradient($cell['gradient']);
27062 if ($g) {
27063 if ($table['borders_separate']) {
27064 $px = $x+ ($table['border_spacing_H']/2);
27065 $py = $y+ ($table['border_spacing_V']/2);
27066 $pw = $w- $table['border_spacing_H'];
27067 $ph = $h- $table['border_spacing_V'];
27068 }
27069 else {
27070 $px = $x;
27071 $py = $y;
27072 $pw = $w;
27073 $ph = $h;
27074 }
27075 if ($this->ColActive) {
27076 $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
27077 }
27078 else {
27079 $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'=>'');
27080 }
27081 }
27082 }
27083
27084 if (isset($cell['background-image']) && $paintcell) {
27085 if (isset($cell['background-image']['gradient']) && $cell['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $cell['background-image']['gradient'] )) {
27086 $g = $this->grad->parseMozGradient( $cell['background-image']['gradient'] );
27087 if ($g) {
27088 if ($table['borders_separate']) {
27089 $px = $x+ ($table['border_spacing_H']/2);
27090 $py = $y+ ($table['border_spacing_V']/2);
27091 $pw = $w- $table['border_spacing_H'];
27092 $ph = $h- $table['border_spacing_V'];
27093 }
27094 else {
27095 $px = $x;
27096 $py = $y;
27097 $pw = $w;
27098 $ph = $h;
27099 }
27100 if ($this->ColActive) {
27101 $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
27102 }
27103 else {
27104 $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'=>'');
27105 }
27106 }
27107 }
27108 else if (isset($cell['background-image']['image_id']) && $cell['background-image']['image_id']) { // Background pattern
27109 $n = count($this->patterns)+1;
27110 if ($table['borders_separate']) {
27111 $px = $x+ ($table['border_spacing_H']/2);
27112 $py = $y+ ($table['border_spacing_V']/2);
27113 $pw = $w- $table['border_spacing_H'];
27114 $ph = $h- $table['border_spacing_V'];
27115 }
27116 else {
27117 $px = $x;
27118 $py = $y;
27119 $pw = $w;
27120 $ph = $h;
27121 }
27122 if ($this->ColActive) {
27123 list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($cell['background-image']['orig_w'], $cell['background-image']['orig_h'], $pw, $ph, $cell['background-image']['resize'], $cell['background-image']['x_repeat'], $cell['background-image']['y_repeat']);
27124 $this->patterns[$n] = array('x'=>$px, 'y'=>$py, 'w'=>$pw, 'h'=>$ph, 'pgh'=>$this->h, 'image_id'=>$cell['background-image']['image_id'], 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$cell['background-image']['x_pos'] , 'y_pos'=>$cell['background-image']['y_pos'] , 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat);
27125 if ($cell['background-image']['opacity']>0 && $cell['background-image']['opacity']<1) { $opac = $this->SetAlpha($cell['background-image']['opacity'],'Normal',true); }
27126 else { $opac = ''; }
27127 $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));
27128 }
27129 else {
27130 $image_id = $cell['background-image']['image_id'];
27131 $orig_w = $cell['background-image']['orig_w'];
27132 $orig_h = $cell['background-image']['orig_h'];
27133 $x_pos = $cell['background-image']['x_pos'];
27134 $y_pos = $cell['background-image']['y_pos'];
27135 $x_repeat = $cell['background-image']['x_repeat'];
27136 $y_repeat = $cell['background-image']['y_repeat'];
27137 $resize = $cell['background-image']['resize'];
27138 $opacity = $cell['background-image']['opacity'];
27139 $itype = $cell['background-image']['itype'];
27140 $this->tableBackgrounds[$level*9+8][] = array('x'=>$px, 'y'=>$py, 'w'=>$pw, 'h'=>$ph, '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);
27141 }
27142 }
27143 }
27144 /*-- END BACKGROUNDS --*/
27145
27146 if (isset($cell['colspan']) && $cell['colspan']>1) { $ccolsp = $cell['colspan']; }
27147 else { $ccolsp = 1; }
27148 if (isset($cell['rowspan']) && $cell['rowspan']>1) { $crowsp = $cell['rowspan']; }
27149 else { $crowsp = 1; }
27150
27151
27152 // but still need to do this for repeated headers...
27153 if (!$table['borders_separate'] && $this->tabletheadjustfinished && !$this->simpleTables){
27154 if (isset($table['topntail']) && $table['topntail']) {
27155 $bord_det['T'] = $this->border_details($table['topntail']);
27156 $bord_det['T']['w'] /= $this->shrin_k;
27157 $this->setBorder($bord, _BORDER_TOP);
27158 }
27159 if (isset($table['thead-underline']) && $table['thead-underline']) {
27160 $bord_det['T'] = $this->border_details($table['thead-underline']);
27161 $bord_det['T']['w'] /= $this->shrin_k;
27162 $this->setBorder($bord, _BORDER_TOP);
27163 }
27164 }
27165
27166
27167 //Get info of first row ==>> table header
27168 //Use > 1 row if THEAD
27169 if (isset($table['is_thead'][$i]) && $table['is_thead'][$i] && $level==1) {
27170 if ($j==0) $tableheaderrowheight += $table['hr'][$i];
27171 $tableheader[$i][0]['trbackground-images'] = (isset($table['trbackground-images'][$i]) ? $table['trbackground-images'][$i] : null);
27172 $tableheader[$i][0]['trgradients'] = (isset($table['trgradients'][$i]) ? $table['trgradients'][$i] : null);
27173 $tableheader[$i][0]['trbgcolor'] = (isset($table['bgcolor'][$i]) ? $table['bgcolor'][$i] : null);
27174 $tableheader[$i][$j]['x'] = $x;
27175 $tableheader[$i][$j]['y'] = $y;
27176 $tableheader[$i][$j]['h'] = $h;
27177 $tableheader[$i][$j]['w'] = $w;
27178 if (isset($cell['textbuffer'])) { $tableheader[$i][$j]['textbuffer'] = $cell['textbuffer']; }
27179 else { $tableheader[$i][$j]['textbuffer'] = ''; }
27180 $tableheader[$i][$j]['a'] = $cell['a'];
27181 $tableheader[$i][$j]['R'] = $cell['R'];
27182
27183 $tableheader[$i][$j]['va'] = $cell['va'];
27184 $tableheader[$i][$j]['mih'] = $cell['mih'];
27185 $tableheader[$i][$j]['gradient'] = (isset($cell['gradient']) ? $cell['gradient'] : null); // *BACKGROUNDS*
27186 $tableheader[$i][$j]['background-image'] = (isset($cell['background-image']) ? $cell['background-image'] : null); // *BACKGROUNDS*
27187 $tableheader[$i][$j]['rowspan'] = (isset($cell['rowspan']) ? $cell['rowspan'] : null);
27188 $tableheader[$i][$j]['colspan'] = (isset($cell['colspan']) ? $cell['colspan'] : null);
27189 $tableheader[$i][$j]['bgcolor'] = $cell['bgcolor'];
27190
27191 if (!$this->simpleTables){
27192 $tableheader[$i][$j]['border'] = $bord;
27193 $tableheader[$i][$j]['border_details'] = $bord_det;
27194 }
27195 else if ($this->simpleTables){
27196 $tableheader[$i][$j]['border'] = $table['simple']['border'];
27197 $tableheader[$i][$j]['border_details'] = $table['simple']['border_details'];
27198 }
27199 $tableheader[$i][$j]['padding'] = $cell['padding'];
27200 if (isset($cell['direction'])) $tableheader[$i][$j]['direction'] = $cell['direction'];
27201 if (isset($cell['cellLineHeight'])) $tableheader[$i][$j]['cellLineHeight'] = $cell['cellLineHeight'];
27202 if (isset($cell['cellLineStackingStrategy'])) $tableheader[$i][$j]['cellLineStackingStrategy'] = $cell['cellLineStackingStrategy'];
27203 if (isset($cell['cellLineStackingShift'])) $tableheader[$i][$j]['cellLineStackingShift'] = $cell['cellLineStackingShift'];
27204 }
27205
27206 // CELL BORDER
27207 if ($bord) {
27208 if ($table['borders_separate'] && $paintcell) {
27209 $this->_tableRect($x + ($table['border_spacing_H']/2)+($bord_det['L']['w'] /2), $y+ ($table['border_spacing_V']/2)+($bord_det['T']['w'] /2), $w-$table['border_spacing_H']-($bord_det['L']['w'] /2)-($bord_det['R']['w'] /2), $h- $table['border_spacing_V']-($bord_det['T']['w'] /2)-($bord_det['B']['w']/2), $bord, $bord_det, false, $table['borders_separate']);
27210 }
27211 else if (!$table['borders_separate']) {
27212 $this->_tableRect($x, $y, $w, $h, $bord, $bord_det, true, $table['borders_separate']); // true causes buffer
27213 }
27214
27215 }
27216
27217 //VERTICAL ALIGN
27218 if ($cell['R'] && INTVAL($cell['R']) > 0 && INTVAL($cell['R']) < 90 && isset($cell['va']) && $cell['va']!='B') { $cell['va']='B';}
27219 if (!isset($cell['va']) || $cell['va']=='M') $this->y += ($h-$cell['mih'])/2;
27220 elseif (isset($cell['va']) && $cell['va']=='B') $this->y += $h-$cell['mih'];
27221
27222 // NESTED CONTENT
27223
27224 // TEXT (and nested tables)
27225
27226 $this->divwidth=$w;
27227 if (!empty($cell['textbuffer'])) {
27228 $this->cellTextAlign=$align;
27229 $this->cellLineHeight = $cell['cellLineHeight'];
27230 $this->cellLineStackingStrategy = $cell['cellLineStackingStrategy'];
27231 $this->cellLineStackingShift = $cell['cellLineStackingShift'];
27232 if ($level==1) {
27233 if (isset($table['is_tfoot'][$i]) && $table['is_tfoot'][$i]) {
27234 if (preg_match('/{colsum([0-9]*)[_]*}/', $cell['textbuffer'][0][0], $m)) {
27235 $rep = sprintf("%01.".intval($m[1])."f", $this->colsums[$j]);
27236 $cell['textbuffer'][0][0] = preg_replace('/{colsum[0-9_]*}/', $rep ,$cell['textbuffer'][0][0]);
27237 }
27238 }
27239 else if (!isset($table['is_thead'][$i])) {
27240 if (isset($this->colsums[$j])) { $this->colsums[$j] += floatval(preg_replace('/^[^0-9\.\,]*/','',$cell['textbuffer'][0][0])); }
27241 else { $this->colsums[$j] = floatval(preg_replace('/^[^0-9\.\,]*/','',$cell['textbuffer'][0][0])); }
27242 }
27243 }
27244 $opy = $this->y;
27245 // mPDF ITERATION
27246 if ($this->iterationCounter) {
27247 foreach($cell['textbuffer'] AS $k=>$t) {
27248 if (preg_match('/{iteration ([a-zA-Z0-9_]+)}/',$t[0], $m)) {
27249 $vname = '__'.$m[1].'_';
27250 if (!isset($this->$vname)) { $this->$vname = 1; }
27251 else { $this->$vname++; }
27252 $cell['textbuffer'][$k][0] = preg_replace('/{iteration '.$m[1].'}/', $this->$vname, $cell['textbuffer'][$k][0]);
27253 }
27254 }
27255 }
27256
27257
27258 if ($cell['R']) {
27259 $cellPtSize = $cell['textbuffer'][0][11] / $this->shrin_k;
27260 if (!$cellPtSize) { $cellPtSize = $this->default_font_size; }
27261 $cellFontHeight = ($cellPtSize/_MPDFK);
27262 $opx = $this->x;
27263 $angle = INTVAL($cell['R']);
27264 // Only allow 45 to 89 degrees (when bottom-aligned) or exactly 90 or -90
27265 if ($angle > 90) { $angle = 90; }
27266 else if ($angle > 0 && $angle <45) { $angle = 45; }
27267 else if ($angle < 0) { $angle = -90; }
27268 $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight);
27269 if (isset($cell['a']) && $cell['a']=='R') {
27270 $this->x += ($w) + ($offset) - ($cellFontHeight/3) - ($cell['padding']['R'] + ($table['border_spacing_H']/2));
27271 }
27272 else if (!isset($cell['a']) || $cell['a']=='C') {
27273 $this->x += ($w/2) + ($offset);
27274 }
27275 else {
27276 $this->x += ($offset) + ($cellFontHeight/3)+($cell['padding']['L'] +($table['border_spacing_H']/2));
27277 }
27278 $str = '';
27279 foreach($cell['textbuffer'] AS $t) { $str .= $t[0].' '; }
27280 $str = rtrim($str);
27281 if (!isset($cell['va']) || $cell['va']=='M') {
27282 $this->y -= ($h-$cell['mih'])/2; //Undo what was added earlier VERTICAL ALIGN
27283 if ($angle > 0) { $this->y += (($h-$cell['mih'])/2) + $cell['padding']['T'] + ($cell['mih']-($cell['padding']['T'] + $cell['padding']['B'])); }
27284 else if ($angle < 0) { $this->y += (($h-$cell['mih'])/2)+ ($cell['padding']['T'] + ($table['border_spacing_V']/2)); }
27285 }
27286 elseif (isset($cell['va']) && $cell['va']=='B') {
27287 $this->y -= $h-$cell['mih']; //Undo what was added earlier VERTICAL ALIGN
27288 if ($angle > 0) { $this->y += $h-($cell['padding']['B'] + ($table['border_spacing_V']/2)); }
27289 else if ($angle < 0) { $this->y += $h-$cell['mih'] + ($cell['padding']['T'] + ($table['border_spacing_V']/2)); }
27290 }
27291 elseif (isset($cell['va']) && $cell['va']=='T') {
27292 if ($angle > 0) { $this->y += $cell['mih']-($cell['padding']['B'] + ($table['border_spacing_V']/2)); }
27293 else if ($angle < 0) { $this->y += ($cell['padding']['T'] + ($table['border_spacing_V']/2)); }
27294 }
27295 $this->Rotate($angle,$this->x,$this->y);
27296 $s_fs = $this->FontSizePt;
27297 $s_f = $this->FontFamily;
27298 $s_st = $this->FontStyle;
27299 if (!empty($cell['textbuffer'][0][3])) { //Font Color
27300 $cor = $cell['textbuffer'][0][3];
27301 $this->SetTColor($cor);
27302 }
27303 $this->SetFont($cell['textbuffer'][0][4],$cell['textbuffer'][0][2],$cellPtSize,true,true);
27304
27305 $this->magic_reverse_dir($str, $this->directionality, $cell['textbuffer'][0][18]);
27306 $this->Text($this->x,$this->y,$str,$cell['textbuffer'][0][18],$cell['textbuffer'][0][8]); // textvar
27307 $this->Rotate(0);
27308 $this->SetFont($s_f,$s_st,$s_fs,true,true);
27309 $this->SetTColor(0);
27310 $this->x = $opx;
27311 }
27312 else {
27313
27314 if (!$this->simpleTables){
27315 if ($bord_det) {
27316 $btlw = $bord_det['L']['w'];
27317 $btrw = $bord_det['R']['w'];
27318 $bttw = $bord_det['T']['w'];
27319 }
27320 else {
27321 $btlw = 0;
27322 $btrw = 0;
27323 $bttw = 0;
27324 }
27325 if ($table['borders_separate']) {
27326 $xadj = $btlw + $cell['padding']['L'] +($table['border_spacing_H']/2);
27327 $wadj = $btlw + $btrw + $cell['padding']['L'] +$cell['padding']['R'] + $table['border_spacing_H'];
27328 $yadj = $bttw + $cell['padding']['T'] + ($table['border_spacing_H']/2);
27329 }
27330 else {
27331 $xadj = $btlw/2 + $cell['padding']['L'];
27332 $wadj = ($btlw + $btrw)/2 + $cell['padding']['L'] + $cell['padding']['R'];
27333 $yadj = $bttw/2 + $cell['padding']['T'];
27334 }
27335 }
27336 else if ($this->simpleTables){
27337 if ($table['borders_separate']) { // NB twice border width
27338 $xadj = $table['simple']['border_details']['L']['w'] + $cell['padding']['L'] +($table['border_spacing_H']/2);
27339 $wadj = $table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w'] + $cell['padding']['L'] +$cell['padding']['R'] + $table['border_spacing_H'];
27340 $yadj = $table['simple']['border_details']['T']['w'] + $cell['padding']['T'] + ($table['border_spacing_H']/2);
27341 }
27342 else {
27343 $xadj = $table['simple']['border_details']['L']['w']/2 + $cell['padding']['L'];
27344 $wadj = ($table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w'])/2 + $cell['padding']['L'] + $cell['padding']['R'];
27345 $yadj = $table['simple']['border_details']['T']['w']/2 + $cell['padding']['T'];
27346 }
27347 }
27348 $this->decimal_offset = 0;
27349 if(substr($cell['a'],0,1) == 'D') {
27350 if (isset($cell['colspan']) && $cell['colspan'] > 1) { $this->cellTextAlign = $c['a'] = substr($cell['a'],2,1); }
27351 else {
27352 $smax = $table['decimal_align'][$j]['maxs0'];
27353 $d_content = $table['decimal_align'][$j]['maxs0'] + $table['decimal_align'][$j]['maxs1'];
27354 $this->decimal_offset = $smax;
27355 $extra = ($w - $d_content - $wadj);
27356 if ($extra > 0) {
27357 if(substr($cell['a'],2,1) == 'R') { $this->decimal_offset += $extra; }
27358 else if(substr($cell['a'],2,1) == 'C') { $this->decimal_offset += ($extra)/2; }
27359 }
27360 }
27361 }
27362 $this->divwidth=$w-$wadj;
27363 if ($this->divwidth == 0) { $this->divwidth = 0.0001; }
27364 $this->x += $xadj;
27365 $this->y += $yadj;
27366 $this->printbuffer($cell['textbuffer'],'',true, false, $cell['direction']);
27367 }
27368 $this->y = $opy;
27369 }
27370
27371 /*-- BACKGROUNDS --*/
27372 if (!$this->ColActive) {
27373 if (isset($table['trgradients'][$i]) && ($j==0 || $table['borders_separate'])) {
27374 $g = $this->grad->parseBackgroundGradient($table['trgradients'][$i]);
27375 if ($g) {
27376 $gx = $x0;
27377 $gy = $y;
27378 $gh = $h;
27379 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
27380 if ($table['borders_separate']) {
27381 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
27382 $clx = $x+ ($table['border_spacing_H']/2);
27383 $cly = $y+ ($table['border_spacing_V']/2);
27384 $clw = $w- $table['border_spacing_H'];
27385 $clh = $h- $table['border_spacing_V'];
27386 // Set clipping path
27387 $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
27388 $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);
27389 }
27390 else {
27391 $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'=>'');
27392 }
27393 }
27394 }
27395 if (isset($table['trbackground-images'][$i]) && ($j==0 || $table['borders_separate'])) {
27396 if (isset($table['trbackground-images'][$i]['gradient']) && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['trbackground-images'][$i]['gradient'] )) {
27397 $g = $this->grad->parseMozGradient( $table['trbackground-images'][$i]['gradient'] );
27398 if ($g) {
27399 $gx = $x0;
27400 $gy = $y;
27401 $gh = $h;
27402 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
27403 if ($table['borders_separate']) {
27404 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
27405 $clx = $x+ ($table['border_spacing_H']/2);
27406 $cly = $y+ ($table['border_spacing_V']/2);
27407 $clw = $w- $table['border_spacing_H'];
27408 $clh = $h- $table['border_spacing_V'];
27409 // Set clipping path
27410 $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
27411 $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);
27412 }
27413 else {
27414 $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'=>'');
27415 }
27416 }
27417 }
27418 else {
27419 $image_id = $table['trbackground-images'][$i]['image_id'];
27420 $orig_w = $table['trbackground-images'][$i]['orig_w'];
27421 $orig_h = $table['trbackground-images'][$i]['orig_h'];
27422 $x_pos = $table['trbackground-images'][$i]['x_pos'];
27423 $y_pos = $table['trbackground-images'][$i]['y_pos'];
27424 $x_repeat = $table['trbackground-images'][$i]['x_repeat'];
27425 $y_repeat = $table['trbackground-images'][$i]['y_repeat'];
27426 $resize = $table['trbackground-images'][$i]['resize'];
27427 $opacity = $table['trbackground-images'][$i]['opacity'];
27428 $itype = $table['trbackground-images'][$i]['itype'];
27429 $clippath = '';
27430 $gx = $x0;
27431 $gy = $y;
27432 $gh = $h;
27433 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
27434 if ($table['borders_separate']) {
27435 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
27436 $clx = $x + ($table['border_spacing_H']/2);
27437 $cly = $y + ($table['border_spacing_V']/2);
27438 $clw = $w - $table['border_spacing_H'];
27439 $clh = $h - $table['border_spacing_V'];
27440 // Set clipping path
27441 $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
27442 $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);
27443 }
27444 else {
27445 $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);
27446 }
27447 }
27448 }
27449 }
27450
27451 /*-- END BACKGROUNDS --*/
27452
27453 // TABLE BORDER - if separate
27454 if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) {
27455 $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H']/2);
27456 $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H']/2);
27457 $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V']/2);
27458 $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V']/2);
27459 $tbx = $x;
27460 $tby = $y;
27461 $tbw = $w;
27462 $tbh = $h;
27463 $tab_bord = 0;
27464
27465 $corner = '';
27466 if ($i == 0) { // Top
27467 $tby -= $halfspaceT + ($table['border_details']['T']['w']/2);
27468 $tbh += $halfspaceT + ($table['border_details']['T']['w']/2);
27469 $this->setBorder($tab_bord , _BORDER_TOP);
27470 $corner .= 'T';
27471 }
27472 if ($i == ($numrows-1) || (isset($cell['rowspan']) && ($i+$cell['rowspan']) == $numrows)) { // Bottom
27473 $tbh += $halfspaceB + ($table['border_details']['B']['w']/2);
27474 $this->setBorder($tab_bord , _BORDER_BOTTOM);
27475 $corner .= 'B';
27476 }
27477 if ($j == 0) { // Left
27478 $tbx -= $halfspaceL + ($table['border_details']['L']['w']/2);
27479 $tbw += $halfspaceL + ($table['border_details']['L']['w']/2);
27480 $this->setBorder($tab_bord , _BORDER_LEFT);
27481 $corner .= 'L';
27482 }
27483 if ($j == ($numcols-1) || (isset($cell['colspan']) && ($j+$cell['colspan']) == $numcols)) { // Right
27484 $tbw += $halfspaceR + ($table['border_details']['R']['w']/2);
27485 $this->setBorder($tab_bord , _BORDER_RIGHT);
27486 $corner .= 'R';
27487 }
27488 $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'] );
27489 }
27490
27491 unset($cell );
27492 //Reset values
27493 $this->Reset();
27494
27495 }//end of (if isset(cells)...)
27496 }// end of columns
27497
27498 $newpagestarted = false;
27499 $this->tabletheadjustfinished = false;
27500
27501 /*-- COLUMNS --*/
27502 if ($this->ColActive) {
27503 if (!$this->table_keep_together && $i < $numrows-1 && $level==1) { $this->breakpoints[$this->CurrCol][] = $y + $h; } // mPDF 6
27504 if (count($this->cellBorderBuffer)) { $this->printcellbuffer(); }
27505 }
27506 /*-- END COLUMNS --*/
27507
27508 if ($i == $numrows-1) { $this->y = $y + $h; } //last row jump (update this->y position)
27509 if ($this->table_rotate && $level==1) {
27510 $this->tbrot_h += $h;
27511 }
27512
27513
27514
27515 }// end of rows
27516
27517 if ($this->progressBar) { $this->UpdateProgressBar(7,70,' '); } // *PROGRESS-BAR*
27518
27519 if (count($this->cellBorderBuffer)) { $this->printcellbuffer(); }
27520
27521
27522 if ($this->tableClipPath ) { $this->_out("Q"); }
27523 $this->tableClipPath = '';
27524
27525 // Advance down page by half width of bottom border
27526 if ($table['borders_separate']) { $this->y += $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2; }
27527 else { $this->y += $table['max_cell_border_width']['B']/2; }
27528
27529 if ($table['borders_separate'] && $level==1) { $this->tbrot_h += $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2; }
27530 else if ($level==1) { $this->tbrot_h += $table['margin']['B'] + $table['max_cell_border_width']['B']/2; }
27531
27532 $bx = $x0;
27533 $by = $y0;
27534 if ($table['borders_separate']) {
27535 $bx -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['border_spacing_H']/2);
27536 if ($tablestartpageno != $this->page) { // IF broken across page
27537 $by += $table['max_cell_border_width']['T']/2;
27538 if (empty($tableheader)) { $by -= ($table['border_spacing_V']/2); }
27539 }
27540 else if ($split && $startrow > 0 && empty($tableheader)) {
27541 $by -= ($table['border_spacing_V']/2);
27542 }
27543 else {
27544 $by -= ($table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V']/2);
27545 }
27546 }
27547 else if ($tablestartpageno != $this->page && !empty($tableheader)) { $by += $maxbwtop /2; }
27548 $by -= $tableheaderadj;
27549 $bh = $this->y - $by;
27550 if (!$table['borders_separate']) { $bh -= $table['max_cell_border_width']['B']/2; }
27551
27552 if ($split) {
27553 $bw = 0;
27554 $finalSpread = true;
27555 for($t=$startcol; $t<$numcols; $t++) {
27556 if ($table['colPg'][$t] == $splitpg) { $bw += $table['wc'][$t]; }
27557 if ($table['colPg'][$t] > $splitpg) { $finalSpread = false; break; }
27558 }
27559 if ($startcol==0) { $firstSpread = true; }
27560 else { $firstSpread = false; }
27561 if ($table['borders_separate']) {
27562 $bw += $table['border_spacing_H'];
27563 if ($firstSpread) {
27564 $bw += $table['padding']['L'] + $table['border_details']['L']['w'];
27565 }
27566 else {
27567 $bx += ($table['padding']['L'] + $table['border_details']['L']['w']);
27568 }
27569 if ($finalSpread) {
27570 $bw += $table['padding']['R'] + $table['border_details']['R']['w'];
27571 }
27572 }
27573 }
27574 else {
27575 $bw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
27576 }
27577
27578 if (!$this->ColActive) {
27579 if (isset($table['bgcolor'][-1])) {
27580 $color = $this->ConvertColor($table['bgcolor'][-1]);
27581 if ($color) {
27582 $this->tableBackgrounds[$level*9][] = array('gradient'=>false, 'x'=>$bx, 'y'=>$by, 'w'=>$bw, 'h'=>$bh, 'col'=>$color);
27583 }
27584 }
27585
27586 /*-- BACKGROUNDS --*/
27587 if (isset($table['gradient'])) {
27588 $g = $this->grad->parseBackgroundGradient($table['gradient']);
27589 if ($g) {
27590 $this->tableBackgrounds[$level*9+1][] = array('gradient'=>true, 'x'=>$bx, 'y'=>$by, 'w'=>$bw, 'h'=>$bh, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
27591 }
27592 }
27593
27594 if (isset($table['background-image'])) {
27595 if (isset($table['background-image']['gradient']) && $table['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['background-image']['gradient'] )) {
27596 $g = $this->grad->parseMozGradient( $table['background-image']['gradient'] );
27597 if ($g) {
27598 $this->tableBackgrounds[$level*9+1][] = array('gradient'=>true, 'x'=>$bx, 'y'=>$by, 'w'=>$bw, 'h'=>$bh, 'gradtype'=>$g['type'], 'stops'=>$g['stops'], 'colorspace'=>$g['colorspace'], 'coords'=>$g['coords'], 'extend'=>$g['extend'], 'clippath'=>'');
27599 }
27600 }
27601 else {
27602 $image_id = $table['background-image']['image_id'];
27603 $orig_w = $table['background-image']['orig_w'];
27604 $orig_h = $table['background-image']['orig_h'];
27605 $x_pos = $table['background-image']['x_pos'];
27606 $y_pos = $table['background-image']['y_pos'];
27607 $x_repeat = $table['background-image']['x_repeat'];
27608 $y_repeat = $table['background-image']['y_repeat'];
27609 $resize = $table['background-image']['resize'];
27610 $opacity = $table['background-image']['opacity'];
27611 $itype = $table['background-image']['itype'];
27612 $this->tableBackgrounds[$level*9+2][] = array('x'=>$bx, 'y'=>$by, 'w'=>$bw, 'h'=>$bh, '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);
27613 }
27614 }
27615 /*-- END BACKGROUNDS --*/
27616 }
27617
27618 if ($this->tableBackgrounds && $level == 1) {
27619 $s = $this->PrintTableBackgrounds();
27620 if ($this->table_rotate && !$this->processingHeader && !$this->processingFooter) {
27621 $this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS'.$this->uniqstr.')/', '\\1'."\n".$s."\n", $this->tablebuffer);
27622 if ($level == 1) { $this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS'.$this->uniqstr.')/', " ", $this->tablebuffer); }
27623 }
27624 else if ($this->bufferoutput) {
27625 $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS'.$this->uniqstr.')/', '\\1'."\n".$s."\n", $this->headerbuffer);
27626 if ($level == 1) { $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS'.$this->uniqstr.')/', " ", $this->headerbuffer ); }
27627 }
27628 else {
27629 $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS'.$this->uniqstr.')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
27630 if ($level == 1) { $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS'.$this->uniqstr.')/', " ", $this->pages[$this->page]); }
27631 }
27632 $this->tableBackgrounds = array();
27633 }
27634
27635
27636 // TABLE BOTTOM MARGIN
27637 if ($table['margin']['B']) {
27638 if (!$this->table_rotate && $level==1) {
27639 $this->DivLn($table['margin']['B'],$this->blklvl,true); // collapsible
27640 }
27641 else {
27642 $this->y += ($table['margin']['B']);
27643 }
27644 }
27645
27646 if ($this->ColActive && $level==1) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
27647
27648 if ($split) {
27649 // Are there more columns to print on a next page?
27650 if ($lastCol < $numcols-1) {
27651 $splitpg++;
27652 $startcol = $lastCol + 1;
27653 return array(false, $startrow, $startcol, $splitpg, $returny, $y0);
27654 }
27655 else {
27656 return array(true,0,0,0,false,false);
27657 }
27658 }
27659
27660 }//END OF FUNCTION _tableWrite()
27661
27662
27663 /////////////////////////END OF TABLE CODE//////////////////////////////////
27664 /*-- END TABLES --*/
27665
27666 function _putextgstates() {
27667 for ($i = 1; $i <= count($this->extgstates); $i++) {
27668 $this->_newobj();
27669 $this->extgstates[$i]['n'] = $this->n;
27670 $this->_out('<</Type /ExtGState');
27671 foreach ($this->extgstates[$i]['parms'] as $k=>$v)
27672 $this->_out('/'.$k.' '.$v);
27673 $this->_out('>>');
27674 $this->_out('endobj');
27675 }
27676 }
27677
27678 function _putocg() {
27679 if ($this->hasOC) {
27680 $this->_newobj();
27681 $this->n_ocg_print=$this->n;
27682 $this->_out('<</Type /OCG /Name '.$this->_textstring('Print only'));
27683 $this->_out('/Usage <</Print <</PrintState /ON>> /View <</ViewState /OFF>>>>>>');
27684 $this->_out('endobj');
27685 $this->_newobj();
27686 $this->n_ocg_view=$this->n;
27687 $this->_out('<</Type /OCG /Name '.$this->_textstring('Screen only'));
27688 $this->_out('/Usage <</Print <</PrintState /OFF>> /View <</ViewState /ON>>>>>>');
27689 $this->_out('endobj');
27690 $this->_newobj();
27691 $this->n_ocg_hidden=$this->n;
27692 $this->_out('<</Type /OCG /Name '.$this->_textstring('Hidden'));
27693 $this->_out('/Usage <</Print <</PrintState /OFF>> /View <</ViewState /OFF>>>>>>');
27694 $this->_out('endobj');
27695 }
27696 if (count($this->layers)) {
27697 ksort($this->layers);
27698 foreach($this->layers as $id=>$layer) {
27699 $this->_newobj();
27700 $this->layers[$id]['n'] = $this->n;
27701 if (isset($this->layerDetails[$id]['name']) && $this->layerDetails[$id]['name']) {
27702 $name = $this->layerDetails[$id]['name'];
27703 }
27704 else { $name = $layer['name']; }
27705 $this->_out('<</Type /OCG /Name '.$this->_UTF16BEtextstring($name).'>>');
27706 $this->_out('endobj');
27707 }
27708 }
27709 }
27710
27711
27712 /*-- IMPORTS --*/
27713
27714 // from mPDFI
27715 function _putimportedobjects() {
27716 if (is_array($this->parsers) && count($this->parsers) > 0) {
27717 foreach($this->parsers AS $filename => $p) {
27718 $this->current_parser =& $this->parsers[$filename];
27719 if (is_array($this->_obj_stack[$filename])) {
27720 while($n = key($this->_obj_stack[$filename])) {
27721 $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c,$this->_obj_stack[$filename][$n][1]);
27722 $this->_newobj($this->_obj_stack[$filename][$n][0]);
27723 if ($nObj[0] == PDF_TYPE_STREAM) {
27724 $this->pdf_write_value($nObj);
27725 }
27726 else {
27727 $this->pdf_write_value($nObj[1]);
27728 }
27729 $this->_out('endobj');
27730 $this->_obj_stack[$filename][$n] = null; // free memory
27731 unset($this->_obj_stack[$filename][$n]);
27732 reset($this->_obj_stack[$filename]);
27733 }
27734 }
27735 }
27736 }
27737 }
27738
27739
27740 function _putformxobjects() {
27741 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
27742 reset($this->tpls);
27743 foreach($this->tpls AS $tplidx => $tpl) {
27744 $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
27745 $this->_newobj();
27746 $this->tpls[$tplidx]['n'] = $this->n;
27747 $this->_out('<<'.$filter.'/Type /XObject');
27748 $this->_out('/Subtype /Form');
27749 $this->_out('/FormType 1');
27750 // Left/Bottom/Right/Top
27751 $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
27752 $tpl['box']['x']*_MPDFK,
27753 $tpl['box']['y']*_MPDFK,
27754 ($tpl['box']['x'] + $tpl['box']['w'])*_MPDFK,
27755 ($tpl['box']['y'] + $tpl['box']['h'])*_MPDFK )
27756 );
27757
27758
27759 if (isset($tpl['box']))
27760 $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]',-$tpl['box']['x']*_MPDFK, -$tpl['box']['y']*_MPDFK));
27761 $this->_out('/Resources ');
27762
27763 if (isset($tpl['resources'])) {
27764 $this->current_parser =& $tpl['parser'];
27765 $this->pdf_write_value($tpl['resources']);
27766 } else {
27767 $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
27768 if (isset($this->_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) {
27769 $this->_out('/Font <<');
27770 foreach($this->_res['tpl'][$tplidx]['fonts'] as $font)
27771 $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
27772 $this->_out('>>');
27773 }
27774 if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) ||
27775 isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls']))
27776 {
27777 $this->_out('/XObject <<');
27778 if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) {
27779 foreach($this->_res['tpl'][$tplidx]['images'] as $image)
27780 $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
27781 }
27782 if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) {
27783 foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $itpl)
27784 $this->_out($this->tplprefix.$i.' '.$itpl['n'].' 0 R');
27785 }
27786 $this->_out('>>');
27787 }
27788 $this->_out('>>');
27789 }
27790
27791 $this->_out('/Length '.strlen($p).' >>');
27792 $this->_putstream($p);
27793 $this->_out('endobj');
27794 }
27795 }
27796
27797 /*-- END IMPORTS --*/
27798
27799
27800 function _putpatterns() {
27801 for ($i = 1; $i <= count($this->patterns); $i++) {
27802 $x = $this->patterns[$i]['x'];
27803 $y = $this->patterns[$i]['y'];
27804 $w = $this->patterns[$i]['w'];
27805 $h = $this->patterns[$i]['h'];
27806 $pgh = $this->patterns[$i]['pgh'];
27807 $orig_w = $this->patterns[$i]['orig_w'];
27808 $orig_h = $this->patterns[$i]['orig_h'];
27809 $image_id = $this->patterns[$i]['image_id'];
27810 $itype = $this->patterns[$i]['itype'];
27811 if (isset($this->patterns[$i]['bpa'])) { $bpa = $this->patterns[$i]['bpa']; } // background positioning area
27812 else { $bpa = array(); }
27813
27814 if ($this->patterns[$i]['x_repeat']) { $x_repeat = true; }
27815 else { $x_repeat = false; }
27816 if ($this->patterns[$i]['y_repeat']) { $y_repeat = true; }
27817 else { $y_repeat = false; }
27818 $x_pos = $this->patterns[$i]['x_pos'];
27819 if (stristr($x_pos ,'%') ) {
27820 $x_pos += 0;
27821 $x_pos /= 100;
27822 if (isset($bpa['w']) && $bpa['w']) $x_pos = ($bpa['w'] * $x_pos) - ($orig_w/_MPDFK * $x_pos);
27823 else $x_pos = ($w * $x_pos) - ($orig_w/_MPDFK * $x_pos);
27824 }
27825 $y_pos = $this->patterns[$i]['y_pos'];
27826 if (stristr($y_pos ,'%') ) {
27827 $y_pos += 0;
27828 $y_pos /= 100;
27829 if (isset($bpa['h']) && $bpa['h']) $y_pos = ($bpa['h'] * $y_pos) - ($orig_h/_MPDFK * $y_pos);
27830 else $y_pos = ($h * $y_pos) - ($orig_h/_MPDFK * $y_pos);
27831 }
27832 if (isset($bpa['x']) && $bpa['x']) $adj_x = ($x_pos + $bpa['x']) *_MPDFK;
27833 else $adj_x = ($x_pos + $x) *_MPDFK;
27834 if (isset($bpa['y']) && $bpa['y']) $adj_y = (($pgh - $y_pos - $bpa['y'])*_MPDFK) - $orig_h ;
27835 else $adj_y = (($pgh - $y_pos - $y)*_MPDFK) - $orig_h ;
27836 $img_obj = false;
27837 if ($itype == 'svg' || $itype == 'wmf') {
27838 foreach($this->formobjects AS $fo) {
27839 if ($fo['i'] == $image_id) {
27840 $img_obj = $fo['n'];
27841 $fo_w = $fo['w'];
27842 $fo_h = -$fo['h'];
27843 $wmf_x = $fo['x'];
27844 $wmf_y = $fo['y'];
27845 break;
27846 }
27847 }
27848 }
27849 else {
27850 foreach($this->images AS $img) {
27851 if ($img['i'] == $image_id) { $img_obj = $img['n']; break; }
27852 }
27853 }
27854 if (!$img_obj ) { echo "Problem: Image object not found for background pattern ".$img['i']; exit; }
27855
27856 $this->_newobj();
27857 $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
27858 if ($itype == 'svg' || $itype == 'wmf') {
27859 $this->_out('/XObject <</FO'.$image_id.' '.$img_obj.' 0 R >>');
27860 // ******* ADD ANY ExtGStates, Shading AND Fonts needed for the FormObject
27861 // Set in classes/svg array['fo'] = true
27862 // Required that _putshaders comes before _putpatterns in _putresources
27863 // This adds any resources associated with any FormObject to every Formobject - overkill but works!
27864 if (count($this->extgstates)) {
27865 $this->_out('/ExtGState <<');
27866 foreach($this->extgstates as $k=>$extgstate)
27867 if (isset($extgstate['fo']) && $extgstate['fo']) {
27868 if (isset($extgstate['trans'])) $this->_out('/'.$extgstate['trans'].' '.$extgstate['n'].' 0 R');
27869 else $this->_out('/GS'.$k.' '.$extgstate['n'].' 0 R');
27870 }
27871 $this->_out('>>');
27872 }
27873 /*-- BACKGROUNDS --*/
27874 if (isset($this->gradients) AND (count($this->gradients) > 0)) {
27875 $this->_out('/Shading <<');
27876 foreach ($this->gradients as $id => $grad) {
27877 if (isset($grad['fo']) && $grad['fo']) {
27878 $this->_out('/Sh'.$id.' '.$grad['id'].' 0 R');
27879 }
27880 }
27881 $this->_out('>>');
27882 }
27883 /*-- END BACKGROUNDS --*/
27884 $this->_out('/Font <<');
27885 foreach($this->fonts as $font) {
27886 if (!$font['used'] && $font['type']=='TTF') { continue; }
27887 if (isset($font['fo']) && $font['fo']) {
27888 if ($font['type']=='TTF' && ($font['sip'] || $font['smp'])) {
27889 foreach($font['n'] AS $k => $fid) {
27890 $this->_out('/F'.$font['subsetfontids'][$k].' '.$font['n'][$k].' 0 R');
27891 }
27892 }
27893 else {
27894 $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
27895 }
27896 }
27897 }
27898 $this->_out('>>');
27899 }
27900 else {
27901 $this->_out('/XObject <</I'.$image_id.' '.$img_obj.' 0 R >>');
27902 }
27903 $this->_out('>>');
27904 $this->_out('endobj');
27905
27906 $this->_newobj();
27907 $this->patterns[$i]['n'] = $this->n;
27908 $this->_out('<< /Type /Pattern /PatternType 1 /PaintType 1 /TilingType 2');
27909 $this->_out('/Resources '. ($this->n-1) .' 0 R');
27910
27911 $this->_out(sprintf('/BBox [0 0 %.3F %.3F]',$orig_w,$orig_h));
27912 if ($x_repeat) { $this->_out(sprintf('/XStep %.3F',$orig_w)); }
27913 else { $this->_out(sprintf('/XStep %d',99999)); }
27914 if ($y_repeat) { $this->_out(sprintf('/YStep %.3F',$orig_h)); }
27915 else { $this->_out(sprintf('/YStep %d',99999)); }
27916
27917 if ($itype == 'svg' || $itype == 'wmf') {
27918 $this->_out(sprintf('/Matrix [1 0 0 -1 %.3F %.3F]', $adj_x, ($adj_y+$orig_h)));
27919 $s = sprintf("q %.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q",($orig_w/$fo_w), (-$orig_h/$fo_h), -($orig_w/$fo_w)*$wmf_x, ($orig_w/$fo_w)*$wmf_y, $image_id);
27920 }
27921 else {
27922 $this->_out(sprintf('/Matrix [1 0 0 1 %.3F %.3F]',$adj_x,$adj_y));
27923 $s = sprintf("q %.3F 0 0 %.3F 0 0 cm /I%d Do Q",$orig_w,$orig_h,$image_id);
27924 }
27925
27926 if ($this->compress) {
27927 $this->_out('/Filter /FlateDecode');
27928 $s = gzcompress($s);
27929 }
27930 $this->_out('/Length '.strlen($s).'>>');
27931 $this->_putstream($s);
27932 $this->_out('endobj');
27933 }
27934 }
27935
27936 /*-- BACKGROUNDS --*/
27937 function _putshaders() {
27938 $maxid = count($this->gradients); //index for transparency gradients
27939 foreach ($this->gradients as $id => $grad) {
27940 if (($grad['type'] == 2 || $grad['type'] == 3) && empty($grad['is_mask'])) {
27941 $this->_newobj();
27942 $this->_out('<<');
27943 $this->_out('/FunctionType 3');
27944 $this->_out('/Domain [0 1]');
27945 $fn = array();
27946 $bd = array();
27947 $en = array();
27948 for($i=0; $i<(count($grad['stops'])-1); $i++) {
27949 $fn[] = ($this->n+1+$i).' 0 R';
27950 $en[] = '0 1';
27951 if ($i>0) { $bd[] = sprintf('%.3F', $grad['stops'][$i]['offset']); }
27952 }
27953 $this->_out('/Functions ['.implode(' ',$fn).']');
27954 $this->_out('/Bounds ['.implode(' ',$bd).']');
27955 $this->_out('/Encode ['.implode(' ',$en).']');
27956 $this->_out('>>');
27957 $this->_out('endobj');
27958 $f1 = $this->n;
27959 for($i=0; $i<(count($grad['stops'])-1); $i++) {
27960 $this->_newobj();
27961 $this->_out('<<');
27962 $this->_out('/FunctionType 2');
27963 $this->_out('/Domain [0 1]');
27964 $this->_out('/C0 ['.$grad['stops'][$i]['col'].']');
27965 $this->_out('/C1 ['.$grad['stops'][$i+1]['col'].']');
27966 $this->_out('/N 1');
27967 $this->_out('>>');
27968 $this->_out('endobj');
27969 }
27970 }
27971 if ($grad['type'] == 2 || $grad['type'] == 3) {
27972 if (isset($grad['trans']) && $grad['trans']) {
27973 $this->_newobj();
27974 $this->_out('<<');
27975 $this->_out('/FunctionType 3');
27976 $this->_out('/Domain [0 1]');
27977 $fn = array();
27978 $bd = array();
27979 $en = array();
27980 for($i=0; $i<(count($grad['stops'])-1); $i++) {
27981 $fn[] = ($this->n+1+$i).' 0 R';
27982 $en[] = '0 1';
27983 if ($i>0) { $bd[] = sprintf('%.3F', $grad['stops'][$i]['offset']); }
27984 }
27985 $this->_out('/Functions ['.implode(' ',$fn).']');
27986 $this->_out('/Bounds ['.implode(' ',$bd).']');
27987 $this->_out('/Encode ['.implode(' ',$en).']');
27988 $this->_out('>>');
27989 $this->_out('endobj');
27990 $f2 = $this->n;
27991 for($i=0; $i<(count($grad['stops'])-1); $i++) {
27992 $this->_newobj();
27993 $this->_out('<<');
27994 $this->_out('/FunctionType 2');
27995 $this->_out('/Domain [0 1]');
27996 $this->_out(sprintf('/C0 [%.3F]', $grad['stops'][$i]['opacity']));
27997 $this->_out(sprintf('/C1 [%.3F]', $grad['stops'][$i+1]['opacity']));
27998 $this->_out('/N 1');
27999 $this->_out('>>');
28000 $this->_out('endobj');
28001 }
28002 }
28003 }
28004
28005 if (empty($grad['is_mask'])) {
28006 $this->_newobj();
28007 $this->_out('<<');
28008 $this->_out('/ShadingType '.$grad['type']);
28009 if (isset($grad['colorspace'])) {
28010 $this->_out('/ColorSpace /Device'.$grad['colorspace']); // Can use CMYK if all C0 and C1 above have 4 values
28011 } else {
28012 $this->_out('/ColorSpace /DeviceRGB');
28013 }
28014 if ($grad['type'] == 2) {
28015 $this->_out(sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]));
28016 $this->_out('/Function '.$f1.' 0 R');
28017 $this->_out('/Extend ['.$grad['extend'][0].' '.$grad['extend'][1].'] ');
28018 $this->_out('>>');
28019 }
28020 else if ($grad['type'] == 3) {
28021 //x0, y0, r0, x1, y1, r1
28022 //at this this time radius of inner circle is 0
28023 $ir = 0;
28024 if (isset($grad['coords'][5]) && $grad['coords'][5]) { $ir = $grad['coords'][5]; }
28025 $this->_out(sprintf('/Coords [%.3F %.3F %.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $ir, $grad['coords'][2], $grad['coords'][3], $grad['coords'][4]));
28026 $this->_out('/Function '.$f1.' 0 R');
28027 $this->_out('/Extend ['.$grad['extend'][0].' '.$grad['extend'][1].'] ');
28028 $this->_out('>>');
28029 }
28030 else if ($grad['type']==6) {
28031 $this->_out('/BitsPerCoordinate 16');
28032 $this->_out('/BitsPerComponent 8');
28033 if ($grad['colorspace'] == 'CMYK') { $this->_out('/Decode[0 1 0 1 0 1 0 1 0 1 0 1]'); }
28034 else if ($grad['colorspace'] == 'Gray') { $this->_out('/Decode[0 1 0 1 0 1]'); }
28035 else { $this->_out('/Decode[0 1 0 1 0 1 0 1 0 1]'); }
28036 $this->_out('/BitsPerFlag 8');
28037 $this->_out('/Length '.strlen($grad['stream']));
28038 $this->_out('>>');
28039 $this->_putstream($grad['stream']);
28040 }
28041 $this->_out('endobj');
28042 }
28043
28044 $this->gradients[$id]['id'] = $this->n;
28045
28046 // set pattern object
28047 $this->_newobj();
28048 $out = '<< /Type /Pattern /PatternType 2';
28049 $out .= ' /Shading '.$this->gradients[$id]['id'].' 0 R';
28050 $out .= ' >>';
28051 $out .= "\n".'endobj';
28052 $this->_out($out);
28053
28054
28055 $this->gradients[$id]['pattern'] = $this->n;
28056
28057 if (isset($grad['trans']) && $grad['trans']) {
28058 // luminosity pattern
28059 $transid = $id + $maxid;
28060 $this->_newobj();
28061 $this->_out('<<');
28062 $this->_out('/ShadingType '.$grad['type']);
28063 $this->_out('/ColorSpace /DeviceGray');
28064 if ($grad['type'] == 2) {
28065 $this->_out(sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]));
28066 $this->_out('/Function '.$f2.' 0 R');
28067 $this->_out('/Extend ['.$grad['extend'][0].' '.$grad['extend'][1].'] ');
28068 $this->_out('>>');
28069 }
28070 else if ($grad['type'] == 3) {
28071 //x0, y0, r0, x1, y1, r1
28072 //at this this time radius of inner circle is 0
28073 $ir = 0;
28074 if (isset($grad['coords'][5]) && $grad['coords'][5]) { $ir = $grad['coords'][5]; }
28075 $this->_out(sprintf('/Coords [%.3F %.3F %.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $ir, $grad['coords'][2], $grad['coords'][3], $grad['coords'][4]));
28076 $this->_out('/Function '.$f2.' 0 R');
28077 $this->_out('/Extend ['.$grad['extend'][0].' '.$grad['extend'][1].'] ');
28078 $this->_out('>>');
28079 }
28080 else if ($grad['type']==6) {
28081 $this->_out('/BitsPerCoordinate 16');
28082 $this->_out('/BitsPerComponent 8');
28083 $this->_out('/Decode[0 1 0 1 0 1]');
28084 $this->_out('/BitsPerFlag 8');
28085 $this->_out('/Length '.strlen($grad['stream_trans']));
28086 $this->_out('>>');
28087 $this->_putstream($grad['stream_trans']);
28088 }
28089 $this->_out('endobj');
28090
28091 $this->gradients[$transid]['id'] = $this->n;
28092 $this->_newobj();
28093 $this->_out('<< /Type /Pattern /PatternType 2');
28094 $this->_out('/Shading '.$this->gradients[$transid]['id'].' 0 R');
28095 $this->_out('>>');
28096 $this->_out('endobj');
28097 $this->gradients[$transid]['pattern'] = $this->n;
28098 $this->_newobj();
28099 // Need to extend size of viewing box in case of transformations
28100 $str = 'q /a0 gs /Pattern cs /p'.$transid.' scn -'.($this->wPt/2).' -'.($this->hPt/2).' '.(2*$this->wPt).' '.(2*$this->hPt).' re f Q';
28101 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
28102 $p=($this->compress) ? gzcompress($str) : $str;
28103 $this->_out('<< /Type /XObject /Subtype /Form /FormType 1 '.$filter);
28104 $this->_out('/Length '.strlen($p));
28105 $this->_out('/BBox [-'.($this->wPt/2).' -'.($this->hPt/2).' '.(2*$this->wPt).' '.(2*$this->hPt).']');
28106 $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceGray >>');
28107 $this->_out('/Resources <<');
28108 $this->_out('/ExtGState << /a0 << /ca 1 /CA 1 >> >>');
28109 $this->_out('/Pattern << /p'.$transid.' '.$this->gradients[$transid]['pattern'].' 0 R >>');
28110 $this->_out('>>');
28111 $this->_out('>>');
28112 $this->_putstream($p);
28113 $this->_out('endobj');
28114 $this->_newobj();
28115 $this->_out('<< /Type /Mask /S /Luminosity /G '.($this->n - 1).' 0 R >>'."\n".'endobj');
28116 $this->_newobj();
28117 $this->_out('<< /Type /ExtGState /SMask '.($this->n - 1).' 0 R /AIS false >>'."\n".'endobj');
28118 if (isset($grad['fo']) && $grad['fo']) { $this->extgstates[] = array('n' => $this->n, 'trans' => 'TGS'.$id, 'fo'=>true); }
28119 else { $this->extgstates[] = array('n' => $this->n, 'trans' => 'TGS'.$id); }
28120 }
28121 }
28122 }
28123 /*-- END BACKGROUNDS --*/
28124
28125 function _putspotcolors() {
28126 foreach($this->spotColors as $name=>$color) {
28127 $this->_newobj();
28128 $this->_out('[/Separation /'.str_replace(' ','#20',$name));
28129 $this->_out('/DeviceCMYK <<');
28130 $this->_out('/Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0] ');
28131 $this->_out(sprintf('/C1 [%.3F %.3F %.3F %.3F] ',$color['c']/100,$color['m']/100,$color['y']/100,$color['k']/100));
28132 $this->_out('/FunctionType 2 /Domain [0 1] /N 1>>]');
28133 $this->_out('endobj');
28134 $this->spotColors[$name]['n']=$this->n;
28135 }
28136 }
28137
28138
28139 function _putresources() {
28140 if ($this->hasOC || count($this->layers))
28141 $this->_putocg();
28142 $this->_putextgstates();
28143 $this->_putspotcolors();
28144 if ($this->progressBar) { $this->UpdateProgressBar(2,'40','Compiling Fonts'); } // *PROGRESS-BAR*
28145 $this->_putfonts();
28146 if ($this->progressBar) { $this->UpdateProgressBar(2,'50','Compiling Images'); } // *PROGRESS-BAR*
28147 $this->_putimages();
28148 $this->_putformobjects(); // *IMAGES-CORE*
28149
28150 /*-- IMPORTS --*/
28151 if ($this->enableImports) {
28152 $this->_putformxobjects();
28153 $this->_putimportedobjects();
28154 }
28155 /*-- END IMPORTS --*/
28156
28157 /*-- BACKGROUNDS --*/
28158 $this->_putshaders();
28159 $this->_putpatterns();
28160 /*-- END BACKGROUNDS --*/
28161
28162
28163 //Resource dictionary
28164 $this->offsets[2]=strlen($this->buffer);
28165 $this->_out('2 0 obj');
28166 $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
28167
28168 $this->_out('/Font <<');
28169 foreach($this->fonts as $font) {
28170 if (isset($font['type']) && $font['type']=='TTF' && !$font['used']) { continue; }
28171 if (isset($font['type']) && $font['type']=='TTF' && ($font['sip'] || $font['smp'])) {
28172 foreach($font['n'] AS $k => $fid) {
28173 $this->_out('/F'.$font['subsetfontids'][$k].' '.$font['n'][$k].' 0 R');
28174 }
28175 }
28176 else {
28177 $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
28178 }
28179 }
28180 $this->_out('>>');
28181
28182 if (count($this->spotColors)) {
28183 $this->_out('/ColorSpace <<');
28184 foreach($this->spotColors as $color)
28185 $this->_out('/CS'.$color['i'].' '.$color['n'].' 0 R');
28186 $this->_out('>>');
28187 }
28188
28189 if (count($this->extgstates)) {
28190 $this->_out('/ExtGState <<');
28191 foreach($this->extgstates as $k=>$extgstate)
28192 if (isset($extgstate['trans'])) $this->_out('/'.$extgstate['trans'].' '.$extgstate['n'].' 0 R');
28193 else $this->_out('/GS'.$k.' '.$extgstate['n'].' 0 R');
28194 $this->_out('>>');
28195 }
28196
28197 /*-- BACKGROUNDS --*/
28198 if ((isset($this->gradients) AND (count($this->gradients) > 0)) || ($this->enableImports && count($this->tpls))) { // mPDF 5.7.3
28199 $this->_out('/Shading <<');
28200 foreach ($this->gradients as $id => $grad) {
28201 $this->_out('/Sh'.$id.' '.$grad['id'].' 0 R');
28202 }
28203 // mPDF 5.7.3
28204 // If a shading dictionary is in an object (tpl) imported from another PDF, it needs to be included
28205 // in the document resources, as well as the object resources
28206 // Otherwise get an error in some PDF viewers
28207 if ($this->enableImports && count($this->tpls)) {
28208 foreach($this->tpls as $tplidx => $tpl) {
28209 if (isset($tpl['resources'])) {
28210 $this->current_parser =& $tpl['parser'];
28211 reset ($tpl['resources'][1]);
28212 while (list($k, $v) = each($tpl['resources'][1])) {
28213 if ($k == '/Shading') {
28214 while (list($k2, $v2) = each($v[1])) {
28215 $this->_out($k2 . " ",false);
28216 $this->pdf_write_value($v2);
28217 }
28218 }
28219 }
28220
28221
28222 }
28223 }
28224 }
28225
28226 $this->_out('>>');
28227 /*
28228 // ??? Not needed !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
28229 $this->_out('/Pattern <<');
28230 foreach ($this->gradients as $id => $grad) {
28231 $this->_out('/P'.$id.' '.$grad['pattern'].' 0 R');
28232 }
28233 $this->_out('>>');
28234 */
28235 }
28236 /*-- END BACKGROUNDS --*/
28237
28238
28239 if(count($this->images) || count($this->formobjects) || ($this->enableImports && count($this->tpls))) {
28240 $this->_out('/XObject <<');
28241 foreach($this->images as $image)
28242 $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
28243 foreach($this->formobjects as $formobject)
28244 $this->_out('/FO'.$formobject['i'].' '.$formobject['n'].' 0 R');
28245 /*-- IMPORTS --*/
28246 if ($this->enableImports && count($this->tpls)) {
28247 foreach($this->tpls as $tplidx => $tpl) {
28248 $this->_out($this->tplprefix.$tplidx.' '.$tpl['n'].' 0 R');
28249 }
28250 }
28251 /*-- END IMPORTS --*/
28252 $this->_out('>>');
28253 }
28254
28255 /*-- BACKGROUNDS --*/
28256
28257 if (count($this->patterns)) {
28258 $this->_out('/Pattern <<');
28259 foreach($this->patterns as $k=>$patterns)
28260 $this->_out('/P'.$k.' '.$patterns['n'].' 0 R');
28261 $this->_out('>>');
28262 }
28263 /*-- END BACKGROUNDS --*/
28264
28265 if ($this->hasOC || count($this->layers)) {
28266 $this->_out('/Properties <<');
28267 if ($this->hasOC) {
28268 $this->_out('/OC1 '.$this->n_ocg_print.' 0 R /OC2 '.$this->n_ocg_view.' 0 R /OC3 '.$this->n_ocg_hidden.' 0 R ');
28269 }
28270 if (count($this->layers)) {
28271 foreach($this->layers as $id=>$layer)
28272 $this->_out('/ZI'.$id.' '.$layer['n'].' 0 R');
28273 }
28274 $this->_out('>>');
28275 }
28276
28277 $this->_out('>>');
28278 $this->_out('endobj'); // end resource dictionary
28279
28280 $this->_putbookmarks(); // *BOOKMARKS*
28281
28282 if (isset($this->js) && $this->js) {
28283 $this->_putjavascript();
28284 }
28285
28286 /*-- ENCRYPTION --*/
28287 if ($this->encrypted) {
28288 $this->_newobj();
28289 $this->enc_obj_id = $this->n;
28290 $this->_out('<<');
28291 $this->_putencryption();
28292 $this->_out('>>');
28293 $this->_out('endobj');
28294 }
28295 /*-- END ENCRYPTION --*/
28296 }
28297
28298
28299 function _putjavascript() {
28300 $this->_newobj();
28301 $this->n_js = $this->n;
28302 $this->_out('<<');
28303 $this->_out('/Names [(EmbeddedJS) '.(1 + $this->n).' 0 R ]');
28304 $this->_out('>>');
28305 $this->_out('endobj');
28306
28307 $this->_newobj();
28308 $this->_out('<<');
28309 $this->_out('/S /JavaScript');
28310 $this->_out('/JS '.$this->_textstring($this->js));
28311 $this->_out('>>');
28312 $this->_out('endobj');
28313 }
28314
28315
28316
28317
28318 /*-- ENCRYPTION --*/
28319 function _putencryption() {
28320 $this->_out('/Filter /Standard');
28321 if ($this->useRC128encryption) {
28322 $this->_out('/V 2');
28323 $this->_out('/R 3');
28324 $this->_out('/Length 128');
28325 }
28326 else {
28327 $this->_out('/V 1');
28328 $this->_out('/R 2');
28329 }
28330 $this->_out('/O ('.$this->_escape($this->Ovalue).')');
28331 $this->_out('/U ('.$this->_escape($this->Uvalue).')');
28332 $this->_out('/P '.$this->Pvalue);
28333 }
28334 /*-- END ENCRYPTION --*/
28335
28336 function _puttrailer() {
28337 $this->_out('/Size '.($this->n+1));
28338 $this->_out('/Root '.$this->n.' 0 R');
28339 $this->_out('/Info '.$this->InfoRoot.' 0 R');
28340 /*-- ENCRYPTION --*/
28341 if ($this->encrypted) {
28342 $this->_out('/Encrypt '.$this->enc_obj_id.' 0 R');
28343 $this->_out('/ID [<'.$this->uniqid.'> <'.$this->uniqid.'>]');
28344 }
28345 else {
28346 /*-- END ENCRYPTION --*/
28347 $uniqid = md5(time() . $this->buffer);
28348 $this->_out('/ID [<'.$uniqid.'> <'.$uniqid.'>]');
28349 /*-- ENCRYPTION --*/
28350 }
28351 /*-- END ENCRYPTION --*/
28352 }
28353
28354 /*-- ENCRYPTION --*/
28355 function SetProtection($permissions=array(),$user_pass='',$owner_pass=null, $length=40) {
28356 $this->encrypted=false;
28357 if (is_string($permissions) && strlen($permissions)>0) { $permissions = array($permissions); }
28358 else if (!is_array($permissions)) { return 0; }
28359 $this->last_rc4_key='';
28360 $this->padding="\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08".
28361 "\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
28362
28363 $options = array(
28364 'print' => 4, // bit 3
28365 'modify' => 8, // bit 4
28366 'copy' => 16, // bit 5
28367 'annot-forms' => 32, // bit 6
28368 'fill-forms' => 256, // bit 9
28369 'extract' => 512, // bit 10
28370 'assemble' => 1024,// bit 11
28371 'print-highres' => 2048 // bit 12
28372 );
28373 // bit 31 = 1073741824
28374 // bit 32 = 2147483648
28375 // bits 13-31 = 2147479552
28376 // bits 13-32 = 4294963200 + 192 = 4294963392
28377 $protection = 4294963392; // bits 7,8,13-32
28378 foreach ($permissions as $permission) {
28379 if (!isset($options[$permission]))
28380 $this->Error('Incorrect permission: '.$permission);
28381 if ($options[$permission] > 32) { $this->useRC128encryption = true; }
28382 if (isset($options[$permission])) $protection += $options[$permission];
28383 }
28384 if ($length==128) { $this->useRC128encryption = true; }
28385 if ($owner_pass === null)
28386 $owner_pass = uniqid(rand());
28387 $this->encrypted = true;
28388 $this->_generateencryptionkey($user_pass, $owner_pass, $protection);
28389 }
28390
28391
28392 // Compute key depending on object number where the encrypted data is stored
28393 function _objectkey($n) {
28394 if ($this->useRC128encryption)
28395 $len = 16;
28396 else
28397 $len = 10;
28398 return substr($this->_md5_16($this->encryption_key.pack('VXxx',$n)),0,$len);
28399 }
28400
28401 // RC4 is the standard encryption algorithm used in PDF format
28402 function _RC4($key, $text) {
28403 if ($this->last_rc4_key != $key) {
28404 $k = str_repeat($key, 256/strlen($key)+1);
28405 $rc4 = range(0,255);
28406 $j = 0;
28407 for ($i=0; $i<256; $i++){
28408 $t = $rc4[$i];
28409 $j = ($j + $t + ord($k[$i])) % 256;
28410 $rc4[$i] = $rc4[$j];
28411 $rc4[$j] = $t;
28412 }
28413 $this->last_rc4_key = $key;
28414 $this->last_rc4_key_c = $rc4;
28415 } else {
28416 $rc4 = $this->last_rc4_key_c;
28417 }
28418
28419 $len = strlen($text);
28420 $a = 0;
28421 $b = 0;
28422 $out = '';
28423 for ($i=0; $i<$len; $i++){
28424 $a = ($a+1)%256;
28425 $t= $rc4[$a];
28426 $b = ($b+$t)%256;
28427 $rc4[$a] = $rc4[$b];
28428 $rc4[$b] = $t;
28429 $k = $rc4[($rc4[$a]+$rc4[$b])%256];
28430 $out.= chr(ord($text[$i]) ^ $k);
28431 }
28432 return $out;
28433 }
28434
28435 // Get MD5 as binary string
28436 function _md5_16($string) {
28437 return pack('H*',md5($string));
28438 }
28439
28440 // Compute O value
28441 function _Ovalue($user_pass, $owner_pass) {
28442 $tmp = $this->_md5_16($owner_pass);
28443 if ($this->useRC128encryption) {
28444 for ($i = 0; $i < 50; ++$i) {
28445 $tmp = $this->_md5_16($tmp);
28446 }
28447 }
28448 if ($this->useRC128encryption)
28449 $keybytelen = (128 / 8);
28450 else
28451 $keybytelen = (40 / 8);
28452 $owner_RC4_key = substr($tmp,0,$keybytelen);
28453 $enc = $this->_RC4($owner_RC4_key, $user_pass);
28454 if ($this->useRC128encryption) {
28455 $len = strlen($owner_RC4_key);
28456 for ($i = 1; $i <= 19; ++$i) {
28457 $key = '';
28458 for ($j = 0; $j < $len; ++$j) {
28459 $key .= chr(ord($owner_RC4_key{$j}) ^ $i);
28460 }
28461 $enc = $this->_RC4($key, $enc);
28462 }
28463 }
28464 return $enc;
28465 }
28466
28467 // Compute U value
28468 function _Uvalue() {
28469 if ($this->useRC128encryption) {
28470 $tmp = $this->_md5_16($this->padding.$this->_hexToString($this->uniqid));
28471 $enc = $this->_RC4($this->encryption_key, $tmp);
28472 $len = strlen($tmp);
28473 for ($i=1; $i<=19; ++$i) {
28474 $key = '';
28475 for ($j=0; $j<$len; ++$j) {
28476 $key .= chr(ord($this->encryption_key{$j}) ^ $i);
28477 }
28478 $enc = $this->_RC4($key, $enc);
28479 }
28480 $enc .= str_repeat("\x00", 16);
28481 return substr($enc, 0, 32);
28482 }
28483 else {
28484 return $this->_RC4($this->encryption_key, $this->padding);
28485 }
28486 }
28487
28488 // Compute encryption key
28489 function _generateencryptionkey($user_pass, $owner_pass, $protection) {
28490 // Pad passwords
28491 $user_pass = substr($user_pass.$this->padding,0,32);
28492 $owner_pass = substr($owner_pass.$this->padding,0,32);
28493 $chars = 'ABCDEF1234567890';
28494 $id = '';
28495 for ($i=0; $i<32; $i++) { $id .= $chars{rand(0, 15)}; }
28496 $this->uniqid = md5($id);
28497 // Compute O value
28498 $this->Ovalue = $this->_Ovalue($user_pass,$owner_pass);
28499 // Compute encyption key
28500 if ($this->useRC128encryption)
28501 $keybytelen = (128/8);
28502 else
28503 $keybytelen = (40/8);
28504 $prot = sprintf('%032b', $protection);
28505 $perms = chr(bindec(substr($prot,24,8)));
28506 $perms .= chr(bindec(substr($prot,16,8)));
28507 $perms .= chr(bindec(substr($prot,8,8)));
28508 $perms .= chr(bindec(substr($prot,0,8)));
28509 $tmp = $this->_md5_16($user_pass.$this->Ovalue.$perms.$this->_hexToString($this->uniqid));
28510 if ($this->useRC128encryption) {
28511 for ($i=0; $i<50; ++$i) {
28512 $tmp = $this->_md5_16(substr($tmp, 0, $keybytelen));
28513 }
28514 }
28515 $this->encryption_key = substr($tmp,0,$keybytelen);
28516 // Compute U value
28517 $this->Uvalue = $this->_Uvalue();
28518 // Compute P value
28519 $this->Pvalue = $protection;
28520 }
28521
28522
28523 function _hexToString($hs) {
28524 $s = '';
28525 $len = strlen($hs);
28526 if (($len % 2) != 0) {
28527 $hs .= '0';
28528 ++$len;
28529 }
28530 for ($i = 0; $i < $len; $i += 2) {
28531 $s .= chr(hexdec($hs{$i}.$hs{($i + 1)}));
28532 }
28533 return $s;
28534 }
28535
28536 /*-- END ENCRYPTION --*/
28537
28538 //=========================================
28539 /*-- BOOKMARKS --*/
28540 // FROM class PDF_Bookmark
28541
28542 function Bookmark($txt,$level=0,$y=0) {
28543 $txt = $this->purify_utf8_text($txt);
28544 if ($this->text_input_as_HTML) {
28545 $txt = $this->all_entities_to_utf8($txt);
28546 }
28547 if($y==-1) {
28548 if (!$this->ColActive){ $y=$this->y; }
28549 else { $y = $this->y0; } // If columns are on - mark top of columns
28550 }
28551 // else y is used as set, or =0 i.e. top of page
28552 // DIRECTIONALITY RTL
28553 $bmo = array('t'=>$txt,'l'=>$level,'y'=>$y,'p'=>$this->page);
28554 if ($this->keep_block_together) {
28555 // do nothing
28556 }
28557 /*-- TABLES --*/
28558 else if ($this->table_rotate) {
28559 $this->tbrot_BMoutlines[]= $bmo;
28560 }
28561 else if ($this->kwt) {
28562 $this->kwt_BMoutlines[]= $bmo;
28563 }
28564 /*-- END TABLES --*/
28565 else if ($this->ColActive) { // *COLUMNS*
28566 $this->col_BMoutlines[]= $bmo; // *COLUMNS*
28567 } // *COLUMNS*
28568 else {
28569 $this->BMoutlines[]= $bmo;
28570 }
28571 }
28572
28573
28574 function _putbookmarks()
28575 {
28576 $nb=count($this->BMoutlines);
28577 if($nb==0)
28578 return;
28579
28580 $bmo = $this->BMoutlines;
28581 $this->BMoutlines = array();
28582 $lastlevel = -1;
28583 for($i=0;$i<count($bmo);$i++) {
28584 if ($bmo[$i]['l']>0) {
28585 while($bmo[$i]['l']-$lastlevel > 1) { // If jump down more than one level, insert a new entry
28586 $new = $bmo[$i];
28587 $new['t']="[".$new['t']."]"; // Put [] around text/title to highlight
28588 $new['l']=$lastlevel+1;
28589 $lastlevel++;
28590 $this->BMoutlines[] = $new;
28591 }
28592 }
28593 $this->BMoutlines[] = $bmo[$i];
28594 $lastlevel = $bmo[$i]['l'];
28595 }
28596 $nb=count($this->BMoutlines);
28597
28598 $lru=array();
28599 $level=0;
28600 foreach($this->BMoutlines as $i=>$o) {
28601 if($o['l']>0) {
28602 $parent=$lru[$o['l']-1];
28603 //Set parent and last pointers
28604 $this->BMoutlines[$i]['parent']=$parent;
28605 $this->BMoutlines[$parent]['last']=$i;
28606 if($o['l']>$level) {
28607 //Level increasing: set first pointer
28608 $this->BMoutlines[$parent]['first']=$i;
28609 }
28610 }
28611 else {
28612 $this->BMoutlines[$i]['parent']=$nb;
28613 }
28614 if($o['l']<=$level and $i>0) {
28615 //Set prev and next pointers
28616 $prev=$lru[$o['l']];
28617 $this->BMoutlines[$prev]['next']=$i;
28618 $this->BMoutlines[$i]['prev']=$prev;
28619 }
28620 $lru[$o['l']]=$i;
28621 $level=$o['l'];
28622 }
28623
28624
28625 //Outline items
28626 $n=$this->n+1;
28627 foreach($this->BMoutlines as $i=>$o) {
28628 $this->_newobj();
28629 $this->_out('<</Title '.$this->_UTF16BEtextstring($o['t']));
28630 $this->_out('/Parent '.($n+$o['parent']).' 0 R');
28631 if(isset($o['prev']))
28632 $this->_out('/Prev '.($n+$o['prev']).' 0 R');
28633 if(isset($o['next']))
28634 $this->_out('/Next '.($n+$o['next']).' 0 R');
28635 if(isset($o['first']))
28636 $this->_out('/First '.($n+$o['first']).' 0 R');
28637 if(isset($o['last']))
28638 $this->_out('/Last '.($n+$o['last']).' 0 R');
28639
28640
28641 if (isset($this->pageDim[$o['p']]['h'])) { $h=$this->pageDim[$o['p']]['h']; }
28642 else { $h = 0; }
28643
28644 $this->_out(sprintf('/Dest [%d 0 R /XYZ 0 %.3F null]',1+2*($o['p']),($h-$o['y'])*_MPDFK));
28645 if (isset($this->bookmarkStyles) && isset($this->bookmarkStyles[$o['l']])) {
28646 // font style
28647 $bms = $this->bookmarkStyles[$o['l']]['style'];
28648 $style = 0;
28649 if (strpos($bms,'B') !== false) { $style += 2; }
28650 if (strpos($bms,'I') !== false) { $style += 1; }
28651 $this->_out(sprintf('/F %d', $style));
28652 // Colour
28653 $col = $this->bookmarkStyles[$o['l']]['color'];
28654 if (isset($col) && is_array($col) && count($col)==3) {
28655 $this->_out(sprintf('/C [%.3F %.3F %.3F]', ($col[0]/255), ($col[1]/255), ($col[2]/255)));
28656 }
28657 }
28658
28659 $this->_out('/Count 0>>');
28660 $this->_out('endobj');
28661 }
28662 //Outline root
28663 $this->_newobj();
28664 $this->OutlineRoot=$this->n;
28665 $this->_out('<</Type /BMoutlines /First '.$n.' 0 R');
28666 $this->_out('/Last '.($n+$lru[0]).' 0 R>>');
28667 $this->_out('endobj');
28668 }
28669 /*-- END BOOKMARKS --*/
28670
28671
28672
28673
28674 //======================================================
28675 /*-- TOC --*/
28676 // ToC TABLE OF CONTENTS
28677
28678 // Initiate, and Mark a place for the Table of Contents to be inserted
28679 function TOC($tocfont='', $tocfontsize=0, $tocindent=0, $resetpagenum='', $pagenumstyle='', $suppress='', $toc_orientation='', $TOCusePaging=true, $TOCuseLinking=false, $toc_id=0, $tocoutdent='') {
28680 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
28681 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
28682 $this->tocontents->TOC($tocfont, $tocfontsize, $tocindent, $resetpagenum, $pagenumstyle, $suppress, $toc_orientation, $TOCusePaging, $TOCuseLinking, $toc_id, $tocoutdent);
28683 }
28684
28685
28686 function TOCpagebreakByArray($a) {
28687 if (!is_array($a)) { $a = array(); }
28688 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
28689 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
28690 $tocoutdent = (isset($a['tocoutdent']) ? $a['tocoutdent'] : (isset($a['outdent']) ? $a['outdent'] : ''));
28691 $TOCusePaging = (isset($a['TOCusePaging']) ? $a['TOCusePaging'] : (isset($a['paging']) ? $a['paging'] : true));
28692 $TOCuseLinking = (isset($a['TOCuseLinking']) ? $a['TOCuseLinking'] : (isset($a['links']) ? $a['links'] : ''));
28693 $toc_orientation = (isset($a['toc_orientation']) ? $a['toc_orientation'] : (isset($a['toc-orientation']) ? $a['toc-orientation'] : ''));
28694 $toc_mgl = (isset($a['toc_mgl']) ? $a['toc_mgl'] : (isset($a['toc-margin-left']) ? $a['toc-margin-left'] : ''));
28695 $toc_mgr = (isset($a['toc_mgr']) ? $a['toc_mgr'] : (isset($a['toc-margin-right']) ? $a['toc-margin-right'] : ''));
28696 $toc_mgt = (isset($a['toc_mgt']) ? $a['toc_mgt'] : (isset($a['toc-margin-top']) ? $a['toc-margin-top'] : ''));
28697 $toc_mgb = (isset($a['toc_mgb']) ? $a['toc_mgb'] : (isset($a['toc-margin-bottom']) ? $a['toc-margin-bottom'] : ''));
28698 $toc_mgh = (isset($a['toc_mgh']) ? $a['toc_mgh'] : (isset($a['toc-margin-header']) ? $a['toc-margin-header'] : ''));
28699 $toc_mgf = (isset($a['toc_mgf']) ? $a['toc_mgf'] : (isset($a['toc-margin-footer']) ? $a['toc-margin-footer'] : ''));
28700 $toc_ohname = (isset($a['toc_ohname']) ? $a['toc_ohname'] : (isset($a['toc-odd-header-name']) ? $a['toc-odd-header-name'] : ''));
28701 $toc_ehname = (isset($a['toc_ehname']) ? $a['toc_ehname'] : (isset($a['toc-even-header-name']) ? $a['toc-even-header-name'] : ''));
28702 $toc_ofname = (isset($a['toc_ofname']) ? $a['toc_ofname'] : (isset($a['toc-odd-footer-name']) ? $a['toc-odd-footer-name'] : ''));
28703 $toc_efname = (isset($a['toc_efname']) ? $a['toc_efname'] : (isset($a['toc-even-footer-name']) ? $a['toc-even-footer-name'] : ''));
28704 $toc_ohvalue = (isset($a['toc_ohvalue']) ? $a['toc_ohvalue'] : (isset($a['toc-odd-header-value']) ? $a['toc-odd-header-value'] : 0));
28705 $toc_ehvalue = (isset($a['toc_ehvalue']) ? $a['toc_ehvalue'] : (isset($a['toc-even-header-value']) ? $a['toc-even-header-value'] : 0));
28706 $toc_ofvalue = (isset($a['toc_ofvalue']) ? $a['toc_ofvalue'] : (isset($a['toc-odd-footer-value']) ? $a['toc-odd-footer-value'] : 0));
28707 $toc_efvalue = (isset($a['toc_efvalue']) ? $a['toc_efvalue'] : (isset($a['toc-even-footer-value']) ? $a['toc-even-footer-value'] : 0));
28708 $toc_preHTML = (isset($a['toc_preHTML']) ? $a['toc_preHTML'] : (isset($a['toc-preHTML']) ? $a['toc-preHTML'] : ''));
28709 $toc_postHTML = (isset($a['toc_postHTML']) ? $a['toc_postHTML'] : (isset($a['toc-postHTML']) ? $a['toc-postHTML'] : ''));
28710 $toc_bookmarkText = (isset($a['toc_bookmarkText']) ? $a['toc_bookmarkText'] : (isset($a['toc-bookmarkText']) ? $a['toc-bookmarkText'] : ''));
28711 $resetpagenum = (isset($a['resetpagenum']) ? $a['resetpagenum'] : '');
28712 $pagenumstyle = (isset($a['pagenumstyle']) ? $a['pagenumstyle'] : '');
28713 $suppress = (isset($a['suppress']) ? $a['suppress'] : '');
28714 $orientation = (isset($a['orientation']) ? $a['orientation'] : '');
28715 $mgl = (isset($a['mgl']) ? $a['mgl'] : (isset($a['margin-left']) ? $a['margin-left'] : ''));
28716 $mgr = (isset($a['mgr']) ? $a['mgr'] : (isset($a['margin-right']) ? $a['margin-right'] : ''));
28717 $mgt = (isset($a['mgt']) ? $a['mgt'] : (isset($a['margin-top']) ? $a['margin-top'] : ''));
28718 $mgb = (isset($a['mgb']) ? $a['mgb'] : (isset($a['margin-bottom']) ? $a['margin-bottom'] : ''));
28719 $mgh = (isset($a['mgh']) ? $a['mgh'] : (isset($a['margin-header']) ? $a['margin-header'] : ''));
28720 $mgf = (isset($a['mgf']) ? $a['mgf'] : (isset($a['margin-footer']) ? $a['margin-footer'] : ''));
28721 $ohname = (isset($a['ohname']) ? $a['ohname'] : (isset($a['odd-header-name']) ? $a['odd-header-name'] : ''));
28722 $ehname = (isset($a['ehname']) ? $a['ehname'] : (isset($a['even-header-name']) ? $a['even-header-name'] : ''));
28723 $ofname = (isset($a['ofname']) ? $a['ofname'] : (isset($a['odd-footer-name']) ? $a['odd-footer-name'] : ''));
28724 $efname = (isset($a['efname']) ? $a['efname'] : (isset($a['even-footer-name']) ? $a['even-footer-name'] : ''));
28725 $ohvalue = (isset($a['ohvalue']) ? $a['ohvalue'] : (isset($a['odd-header-value']) ? $a['odd-header-value'] : 0));
28726 $ehvalue = (isset($a['ehvalue']) ? $a['ehvalue'] : (isset($a['even-header-value']) ? $a['even-header-value'] : 0));
28727 $ofvalue = (isset($a['ofvalue']) ? $a['ofvalue'] : (isset($a['odd-footer-value']) ? $a['odd-footer-value'] : 0));
28728 $efvalue = (isset($a['efvalue']) ? $a['efvalue'] : (isset($a['even-footer-value']) ? $a['even-footer-value'] : 0));
28729 $toc_id = (isset($a['toc_id']) ? $a['toc_id'] : (isset($a['name']) ? $a['name'] : 0));
28730 $pagesel = (isset($a['pagesel']) ? $a['pagesel'] : (isset($a['pageselector']) ? $a['pageselector'] : ''));
28731 $toc_pagesel = (isset($a['toc_pagesel']) ? $a['toc_pagesel'] : (isset($a['toc-pageselector']) ? $a['toc-pageselector'] : ''));
28732 $sheetsize = (isset($a['sheetsize']) ? $a['sheetsize'] : (isset($a['sheet-size']) ? $a['sheet-size'] : ''));
28733 $toc_sheetsize = (isset($a['toc_sheetsize']) ? $a['toc_sheetsize'] : (isset($a['toc-sheet-size']) ? $a['toc-sheet-size'] : ''));
28734
28735 $this->TOCpagebreak($tocfont, $tocfontsize, $tocindent, $TOCusePaging, $TOCuseLinking, $toc_orientation, $toc_mgl, $toc_mgr, $toc_mgt, $toc_mgb, $toc_mgh, $toc_mgf, $toc_ohname, $toc_ehname, $toc_ofname, $toc_efname, $toc_ohvalue, $toc_ehvalue, $toc_ofvalue, $toc_efvalue, $toc_preHTML, $toc_postHTML, $toc_bookmarkText, $resetpagenum, $pagenumstyle, $suppress, $orientation, $mgl, $mgr, $mgt, $mgb, $mgh, $mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue, $toc_id, $pagesel, $toc_pagesel, $sheetsize, $toc_sheetsize, $tocoutdent);
28736
28737 }
28738
28739 function TOCpagebreak($tocfont='', $tocfontsize='', $tocindent='', $TOCusePaging=true, $TOCuseLinking='', $toc_orientation='', $toc_mgl='',$toc_mgr='',$toc_mgt='',$toc_mgb='',$toc_mgh='',$toc_mgf='',$toc_ohname='',$toc_ehname='',$toc_ofname='',$toc_efname='',$toc_ohvalue=0,$toc_ehvalue=0,$toc_ofvalue=0, $toc_efvalue=0, $toc_preHTML='', $toc_postHTML='', $toc_bookmarkText='', $resetpagenum='', $pagenumstyle='', $suppress='', $orientation='', $mgl='',$mgr='',$mgt='',$mgb='',$mgh='',$mgf='',$ohname='',$ehname='',$ofname='',$efname='',$ohvalue=0,$ehvalue=0,$ofvalue=0,$efvalue=0, $toc_id=0, $pagesel='', $toc_pagesel='', $sheetsize='', $toc_sheetsize='', $tocoutdent='') {
28740 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
28741 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
28742 if (!$resetpagenum) { $resetpagenum= 1; } // mPDF 6
28743 //Start a new page
28744 if($this->state==0) $this->AddPage();
28745 if ($this->y == $this->tMargin && (!$this->mirrorMargins ||($this->mirrorMargins && $this->page % 2==1))) {
28746 // Don't add a page
28747 if ($this->page==1 && count($this->PageNumSubstitutions)==0) {
28748 if (!$suppress) { $suppress = 'off'; }
28749 //$this->PageNumSubstitutions[] = array('from'=>1, 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=> $suppress);
28750 }
28751 $this->PageNumSubstitutions[] = array('from'=>$this->page, 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=> $suppress);
28752 }
28753 else {
28754 $this->AddPage($orientation,'NEXT-ODD', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$sheetsize);
28755 }
28756 $this->tocontents->TOCpagebreak($tocfont, $tocfontsize, $tocindent, $TOCusePaging, $TOCuseLinking, $toc_orientation, $toc_mgl, $toc_mgr, $toc_mgt, $toc_mgb, $toc_mgh, $toc_mgf, $toc_ohname, $toc_ehname, $toc_ofname, $toc_efname, $toc_ohvalue, $toc_ehvalue, $toc_ofvalue, $toc_efvalue, $toc_preHTML, $toc_postHTML, $toc_bookmarkText, $resetpagenum, $pagenumstyle, $suppress, $orientation, $mgl, $mgr, $mgt, $mgb, $mgh, $mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue, $toc_id, $pagesel, $toc_pagesel, $sheetsize, $toc_sheetsize, $tocoutdent);
28757 }
28758
28759 function TOC_Entry($txt, $level=0, $toc_id=0) {
28760 if ($this->ColActive) { $ily = $this->y0; } else { $ily = $this->y; } // use top of columns
28761
28762 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
28763 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
28764 $linkn = $this->AddLink();
28765 $uid = '__mpdfinternallink_' . $linkn ;
28766 if ($this->table_rotate) { $this->internallink[$uid] = array("Y"=>$ily,"PAGE"=>$this->page, "tbrot"=>true ); }
28767 else if ($this->kwt) { $this->internallink[$uid] = array("Y"=>$ily,"PAGE"=>$this->page, "kwt"=>true ); }
28768 else if ($this->ColActive) { $this->internallink[$uid] = array("Y"=>$ily,"PAGE"=>$this->page, "col"=>$this->CurrCol ); }
28769 else if (!$this->keep_block_together) { $this->internallink[$uid] = array("Y"=>$ily,"PAGE"=>$this->page ); }
28770 $this->internallink['#'.$uid] = $linkn;
28771 $this->SetLink($linkn,$ily,$this->page);
28772
28773 if (strtoupper($toc_id)=='ALL') { $toc_id = '_mpdf_all'; }
28774 else if (!$toc_id) { $toc_id = 0; }
28775 else { $toc_id = strtolower($toc_id); }
28776 $btoc = array('t'=>$txt,'l'=>$level,'p'=>$this->page, 'link'=>$linkn, 'toc_id'=>$toc_id);
28777 if ($this->keep_block_together) {
28778 // do nothing
28779 }
28780 /*-- TABLES --*/
28781 else if ($this->table_rotate) {
28782 $this->tbrot_toc[]= $btoc;
28783 }
28784 else if ($this->kwt) {
28785 $this->kwt_toc[]= $btoc;
28786 }
28787 /*-- END TABLES --*/
28788 else if ($this->ColActive) { // *COLUMNS*
28789 $this->col_toc[]= $btoc; // *COLUMNS*
28790 } // *COLUMNS*
28791 else {
28792 $this->tocontents->_toc[]= $btoc;
28793 }
28794 }
28795
28796 /*-- END TOC --*/
28797
28798 //======================================================
28799 function MovePages($target_page, $start_page, $end_page=-1) {
28800 // move a page/pages EARLIER in the document
28801 if ($end_page<1) { $end_page = $start_page; }
28802 $n_toc = $end_page - $start_page + 1;
28803
28804 // Set/Update PageNumSubstitutions changes before moving anything
28805 if (count($this->PageNumSubstitutions)) {
28806 $tp_present = false;
28807 $sp_present = false;
28808 $ep_present = false;
28809 foreach($this->PageNumSubstitutions AS $k=>$v) {
28810 if ($this->PageNumSubstitutions[$k]['from']==$target_page) {
28811 $tp_present = true;
28812 if ($this->PageNumSubstitutions[$k]['suppress']!='on' && $this->PageNumSubstitutions[$k]['suppress']!=1) {
28813 $this->PageNumSubstitutions[$k]['suppress']='off';
28814 }
28815 }
28816 if ($this->PageNumSubstitutions[$k]['from']==$start_page) {
28817 $sp_present = true;
28818 if ($this->PageNumSubstitutions[$k]['suppress']!='on' && $this->PageNumSubstitutions[$k]['suppress']!=1) {
28819 $this->PageNumSubstitutions[$k]['suppress']='off';
28820 }
28821 }
28822 if ($this->PageNumSubstitutions[$k]['from']==($end_page+1)) {
28823 $ep_present = true;
28824 if ($this->PageNumSubstitutions[$k]['suppress']!='on' && $this->PageNumSubstitutions[$k]['suppress']!=1) {
28825 $this->PageNumSubstitutions[$k]['suppress']='off';
28826 }
28827 }
28828 }
28829
28830 if (!$tp_present) {
28831 list($tp_type, $tp_suppress, $tp_reset) = $this->docPageSettings($target_page);
28832 }
28833 if (!$sp_present) {
28834 list($sp_type, $sp_suppress, $sp_reset) = $this->docPageSettings($start_page);
28835 }
28836 if (!$ep_present) {
28837 list($ep_type, $ep_suppress, $ep_reset) = $this->docPageSettings($start_page-1);
28838 }
28839
28840 }
28841
28842 $last = array();
28843 //store pages
28844 for($i = $start_page;$i <= $end_page ;$i++)
28845 $last[]=$this->pages[$i];
28846 //move pages
28847 for($i=$start_page - 1;$i>=($target_page);$i--) {
28848 $this->pages[$i+$n_toc]=$this->pages[$i];
28849 }
28850 //Put toc pages at insert point
28851 for($i = 0;$i < $n_toc;$i++) {
28852 $this->pages[$target_page + $i]=$last[$i];
28853 }
28854
28855 /*-- BOOKMARKS --*/
28856 // Update Bookmarks
28857 foreach($this->BMoutlines as $i=>$o) {
28858 if($o['p']>=$target_page) {
28859 $this->BMoutlines[$i]['p'] += $n_toc;
28860 }
28861 }
28862 /*-- END BOOKMARKS --*/
28863
28864 // Update Page Links
28865 if (count($this->PageLinks)) {
28866 $newarr = array();
28867 foreach($this->PageLinks as $i=>$o) {
28868 foreach($this->PageLinks[$i] as $key => $pl) {
28869 if (strpos($pl[4],'@')===0) {
28870 $p=substr($pl[4],1);
28871 if($p>=$start_page && $p<=$end_page) {
28872 $this->PageLinks[$i][$key][4] = '@'.($p + ($target_page - $start_page));
28873 }
28874 else if($p>=$target_page && $p<$start_page) {
28875 $this->PageLinks[$i][$key][4] = '@'.($p+$n_toc);
28876 }
28877 }
28878 }
28879 if($i>=$start_page && $i<=$end_page) {
28880 $newarr[($i + ($target_page - $start_page))] = $this->PageLinks[$i];
28881 }
28882 else if($i>=$target_page && $i<$start_page) {
28883 $newarr[($i + $n_toc)] = $this->PageLinks[$i];
28884 }
28885 else {
28886 $newarr[$i] = $this->PageLinks[$i];
28887 }
28888 }
28889 $this->PageLinks = $newarr;
28890 }
28891
28892 // OrientationChanges
28893 if (count($this->OrientationChanges)) {
28894 $newarr = array();
28895 foreach($this->OrientationChanges AS $p=>$v) {
28896 if($p>=$start_page && $p<=$end_page) { $newarr[($p + ($target_page - $start_page))] = $this->OrientationChanges[$p]; }
28897 else if($p>=$target_page && $p<$start_page) { $newarr[$p+$n_toc] = $this->OrientationChanges[$p]; }
28898 else { $newarr[$p] = $this->OrientationChanges[$p]; }
28899 }
28900 ksort($newarr);
28901 $this->OrientationChanges = $newarr;
28902 }
28903
28904 // Page Dimensions
28905 if (count($this->pageDim)) {
28906 $newarr = array();
28907 foreach($this->pageDim AS $p=>$v) {
28908 if($p>=$start_page && $p<=$end_page) { $newarr[($p + ($target_page - $start_page))] = $this->pageDim[$p]; }
28909 else if($p>=$target_page && $p<$start_page) { $newarr[$p+$n_toc] = $this->pageDim[$p]; }
28910 else { $newarr[$p] = $this->pageDim[$p]; }
28911 }
28912 ksort($newarr);
28913 $this->pageDim = $newarr;
28914 }
28915
28916 // HTML Headers & Footers
28917 if (count($this->saveHTMLHeader)) {
28918 $newarr = array();
28919 foreach($this->saveHTMLHeader AS $p=>$v) {
28920 if($p>=$start_page && $p<=$end_page) { $newarr[($p + ($target_page - $start_page))] = $this->saveHTMLHeader[$p]; }
28921 else if($p>=$target_page && $p<$start_page) { $newarr[$p+$n_toc] = $this->saveHTMLHeader[$p]; }
28922 else { $newarr[$p] = $this->saveHTMLHeader[$p]; }
28923 }
28924 ksort($newarr);
28925 $this->saveHTMLHeader = $newarr;
28926 }
28927 if (count($this->saveHTMLFooter)) {
28928 $newarr = array();
28929 foreach($this->saveHTMLFooter AS $p=>$v) {
28930 if($p>=$start_page && $p<=$end_page) { $newarr[($p + ($target_page - $start_page))] = $this->saveHTMLFooter[$p]; }
28931 else if($p>=$target_page && $p<$start_page) { $newarr[$p+$n_toc] = $this->saveHTMLFooter[$p]; }
28932 else { $newarr[$p] = $this->saveHTMLFooter[$p]; }
28933 }
28934 ksort($newarr);
28935 $this->saveHTMLFooter = $newarr;
28936 }
28937
28938 // Update Internal Links
28939 if (count($this->internallink)) {
28940 foreach($this->internallink as $key=>$o) {
28941 if($o['PAGE']>=$start_page && $o['PAGE']<=$end_page) {
28942 $this->internallink[$key]['PAGE'] += ($target_page - $start_page);
28943 }
28944 else if($o['PAGE']>=$target_page && $o['PAGE']<$start_page) {
28945 $this->internallink[$key]['PAGE'] += $n_toc;
28946 }
28947 }
28948 }
28949
28950 // Update Links
28951 if (count($this->links)) {
28952 foreach($this->links as $key=>$o) {
28953 if($o[0]>=$start_page && $o[0]<=$end_page) {
28954 $this->links[$key][0] += ($target_page - $start_page);
28955 }
28956 if($o[0]>=$target_page && $o[0]<$start_page) {
28957 $this->links[$key][0] += $n_toc;
28958 }
28959 }
28960 }
28961
28962 // Update Form fields
28963 if (count($this->mpdfform->forms)) {
28964 foreach($this->mpdfform->forms as $key=>$f) {
28965 if($f['page']>=$start_page && $f['page']<=$end_page) {
28966 $this->mpdfform->forms[$key]['page'] += ($target_page - $start_page);
28967 }
28968 if($f['page']>=$target_page && $f['page']<$start_page) {
28969 $this->mpdfform->forms[$key]['page'] += $n_toc;
28970 }
28971 }
28972 }
28973
28974 /*-- ANNOTATIONS --*/
28975 // Update Annotations
28976 if (count($this->PageAnnots)) {
28977 $newarr = array();
28978 foreach($this->PageAnnots as $p=>$anno) {
28979 if($p>=$start_page && $p<=$end_page) {
28980 $np = $p + ($target_page - $start_page);
28981 foreach($anno as $o) {
28982 $newarr[$np][] = $o;
28983 }
28984 }
28985 else if($p>=$target_page && $p<$start_page) {
28986 $np = $p + $n_toc;
28987 foreach($anno as $o) {
28988 $newarr[$np][] = $o;
28989 }
28990 }
28991 else {
28992 $newarr[$p] = $this->PageAnnots[$p];
28993 }
28994 }
28995 $this->PageAnnots = $newarr;
28996 unset($newarr);
28997 }
28998 /*-- END ANNOTATIONS --*/
28999
29000 // Update PageNumSubstitutions
29001 if (count($this->PageNumSubstitutions)) {
29002 $newarr = array();
29003 foreach($this->PageNumSubstitutions AS $k=>$v) {
29004 if($this->PageNumSubstitutions[$k]['from']>=$start_page && $this->PageNumSubstitutions[$k]['from']<=$end_page) {
29005 $this->PageNumSubstitutions[$k]['from'] += ($target_page - $start_page);
29006 $newarr[$this->PageNumSubstitutions[$k]['from']] = $this->PageNumSubstitutions[$k];
29007 }
29008 else if($this->PageNumSubstitutions[$k]['from']>=$target_page && $this->PageNumSubstitutions[$k]['from']<$start_page) {
29009 $this->PageNumSubstitutions[$k]['from'] += $n_toc;
29010 $newarr[$this->PageNumSubstitutions[$k]['from']] = $this->PageNumSubstitutions[$k];
29011 }
29012 else {
29013 $newarr[$this->PageNumSubstitutions[$k]['from']] = $this->PageNumSubstitutions[$k];
29014 }
29015 }
29016
29017 if (!$sp_present) {
29018 $newarr[$target_page] = array('from'=>$target_page, 'suppress'=>$sp_suppress, 'reset'=>$sp_reset, 'type'=>$sp_type);
29019 }
29020 if (!$tp_present) {
29021 $newarr[($target_page + $n_toc)] = array('from'=>($target_page+$n_toc), 'suppress'=>$tp_suppress, 'reset'=>$tp_reset, 'type'=>$tp_type);
29022 }
29023 if (!$ep_present && $end_page>count($this->pages)) {
29024 $newarr[($end_page+1)] = array('from'=>($end_page+1), 'suppress'=>$ep_suppress, 'reset'=>$ep_reset, 'type'=>$ep_type);
29025 }
29026 ksort($newarr);
29027 $this->PageNumSubstitutions = array();
29028 foreach($newarr as $v) {
29029 $this->PageNumSubstitutions[] = $v;
29030 }
29031 }
29032 }
29033
29034 //======================================================
29035 function DeletePages($start_page, $end_page=-1) {
29036 // move a page/pages EARLIER in the document
29037 if ($end_page<1) { $end_page = $start_page; }
29038 $n_tod = $end_page - $start_page + 1;
29039 $last_page = count($this->pages);
29040 $n_atend = $last_page - $end_page + 1;
29041
29042 //move pages
29043 for($i=0;$i<$n_atend;$i++) {
29044 $this->pages[$start_page+$i]=$this->pages[$end_page+1+$i];
29045 }
29046 //delete pages
29047 for($i = 0;$i < $n_tod ;$i++)
29048 unset($this->pages[$last_page-$i]);
29049
29050
29051 /*-- BOOKMARKS --*/
29052 // Update Bookmarks
29053 foreach($this->BMoutlines as $i=>$o) {
29054 if($o['p']>=$end_page) { $this->BMoutlines[$i]['p'] -= $n_tod; }
29055 else if($p<$start_page) { unset($this->BMoutlines[$i]); }
29056 }
29057 /*-- END BOOKMARKS --*/
29058
29059 // Update Page Links
29060 if (count($this->PageLinks)) {
29061 $newarr = array();
29062 foreach($this->PageLinks as $i=>$o) {
29063 foreach($this->PageLinks[$i] as $key => $pl) {
29064 if (strpos($pl[4],'@')===0) {
29065 $p=substr($pl[4],1);
29066 if($p>$end_page) { $this->PageLinks[$i][$key][4] = '@'.($p - $n_tod); }
29067 else if($p<$start_page) { unset($this->PageLinks[$i][$key]); }
29068 }
29069 }
29070 if($i>$end_page) { $newarr[($i - $n_tod)] = $this->PageLinks[$i]; }
29071 else if($p<$start_page) { $newarr[$i] = $this->PageLinks[$i]; }
29072 }
29073 $this->PageLinks = $newarr;
29074 }
29075
29076 // OrientationChanges
29077 if (count($this->OrientationChanges)) {
29078 $newarr = array();
29079 foreach($this->OrientationChanges AS $p=>$v) {
29080 if($p>$end_page) { $newarr[($p - $t_tod)] = $this->OrientationChanges[$p]; }
29081 else if($p<$start_page) { $newarr[$p] = $this->OrientationChanges[$p]; }
29082 }
29083 ksort($newarr);
29084 $this->OrientationChanges = $newarr;
29085 }
29086
29087 // Page Dimensions
29088 if (count($this->pageDim)) {
29089 $newarr = array();
29090 foreach($this->pageDim AS $p=>$v) {
29091 if($p>$end_page) { $newarr[($p - $n_tod)] = $this->pageDim[$p]; }
29092 else if($p<$start_page) { $newarr[$p] = $this->pageDim[$p]; }
29093 }
29094 ksort($newarr);
29095 $this->pageDim = $newarr;
29096 }
29097
29098 // HTML Headers & Footers
29099 if (count($this->saveHTMLHeader)) {
29100 foreach($this->saveHTMLHeader AS $p=>$v) {
29101 if($p>$end_page) { $newarr[($p - $n_tod)] = $this->saveHTMLHeader[$p]; } // mPDF 5.7.3
29102 else if($p<$start_page) { $newarr[$p] = $this->saveHTMLHeader[$p]; }
29103 }
29104 ksort($newarr);
29105 $this->saveHTMLHeader = $newarr;
29106 }
29107 if (count($this->saveHTMLFooter)) {
29108 $newarr = array();
29109 foreach($this->saveHTMLFooter AS $p=>$v) {
29110 if($p>$end_page) { $newarr[($p - $n_tod)] = $this->saveHTMLFooter[$p]; }
29111 else if($p<$start_page) { $newarr[$p] = $this->saveHTMLFooter[$p]; }
29112 }
29113 ksort($newarr);
29114 $this->saveHTMLFooter = $newarr;
29115 }
29116
29117 // Update Internal Links
29118 foreach($this->internallink as $key=>$o) {
29119 if($o['PAGE']>$end_page) { $this->internallink[$key]['PAGE'] -= $n_tod; }
29120 else if($o['PAGE']<$start_page) { unset($this->internallink[$key]); }
29121 }
29122
29123 // Update Links
29124 foreach($this->links as $key=>$o) {
29125 if($o[0]>$end_page) { $this->links[$key][0] -= $n_tod; }
29126 else if($o[0]<$start_page) { unset($this->links[$key]); }
29127 }
29128
29129 // Update Form fields
29130 foreach($this->mpdfform->forms as $key=>$f) {
29131 if($f['page']>$end_page) { $this->mpdfform->forms[$key]['page'] -= $n_tod; }
29132 else if($f['page']<$start_page) { unset($this->mpdfform->forms[$key]); }
29133 }
29134
29135 /*-- ANNOTATIONS --*/
29136 // Update Annotations
29137 if (count($this->PageAnnots)) {
29138 $newarr = array();
29139 foreach($this->PageAnnots as $p=>$anno) {
29140 if($p>$end_page) { foreach($anno as $o) { $newarr[($p - $n_tod)][] = $o; } }
29141 else if($p<$start_page) { $newarr[$p] = $this->PageAnnots[$p]; }
29142 }
29143 ksort($newarr);
29144 $this->PageAnnots = $newarr;
29145 }
29146 /*-- END ANNOTATIONS --*/
29147
29148 // Update PageNumSubstitutions
29149 foreach($this->PageNumSubstitutions AS $k=>$v) {
29150 if($this->PageNumSubstitutions[$k]['from']>$end_page) { $this->PageNumSubstitutions[$k]['from'] -= $n_tod; }
29151 else if($this->PageNumSubstitutions[$k]['from']<$start_page) { unset($this->PageNumSubstitutions[$k]); }
29152 }
29153
29154 unset($newarr);
29155 $this->page = count($this->pages);
29156 }
29157
29158
29159 //======================================================
29160 /*-- INDEX --*/
29161 // FROM class PDF_Ref == INDEX
29162
29163
29164 function IndexEntry($txt, $xref='') {
29165 if ($xref) {
29166 $this->IndexEntrySee($txt,$xref);
29167 return;
29168 }
29169
29170 //Search the reference (AND Ref/PageNo) in the array
29171 $Present = false;
29172 if ($this->keep_block_together) {
29173 // do nothing
29174 }
29175 /*-- TABLES --*/
29176 else if ($this->kwt) {
29177 $size=count($this->kwt_Reference);
29178 for ($i=0;$i<$size;$i++){
29179 if (isset($this->kwt_Reference[$i]['t']) && $this->kwt_Reference[$i]['t']==$txt){
29180 $Present = true;
29181 if ($this->page != $this->kwt_Reference[$i]['op']) {
29182 $this->kwt_Reference[$i]['op'] = $this->page;
29183 }
29184 }
29185 }
29186 if (!$Present) { //If not found, add it
29187 $this->kwt_Reference[] = array('t'=>$txt, 'op'=>$this->page);
29188 }
29189 }
29190 /*-- END TABLES --*/
29191 else {
29192 $size=count($this->Reference);
29193 for ($i=0;$i<$size;$i++){
29194 if (isset($this->Reference[$i]['t']) && $this->Reference[$i]['t']==$txt){
29195 $Present = true;
29196 if (!in_array($this->page,$this->Reference[$i]['p'])) {
29197 $this->Reference[$i]['p'][] = $this->page;
29198 }
29199 }
29200 }
29201 if (!$Present) { //If not found, add it
29202 $this->Reference[] = array('t'=>$txt,'p'=>array($this->page));
29203 }
29204 }
29205 }
29206
29207
29208 // Added function to add a reference "Elephants. See Chickens"
29209 function IndexEntrySee($txta,$txtb) {
29210 if ($this->directionality == 'rtl') { // *OTL*
29211 // ONLY DO THIS IF NOT IN TAGS
29212 if ($txta == strip_tags($txta)) $txta = str_replace(':',' - ',$txta); // *OTL*
29213 if ($txtb == strip_tags($txtb)) $txtb = str_replace(':',' - ',$txtb); // *OTL*
29214 } // *OTL*
29215 else { // *OTL*
29216 if ($txta == strip_tags($txta)) $txta = str_replace(':',', ',$txta);
29217 if ($txtb == strip_tags($txtb)) $txtb = str_replace(':',', ',$txtb);
29218 } // *OTL*
29219 $this->Reference[]=array('t'=>$txta.' - see '.$txtb,'p'=>array());
29220 }
29221
29222
29223 function InsertIndex($usedivletters=1, $useLinking=false, $indexCollationLocale='', $indexCollationGroup='') {
29224 $size=count($this->Reference);
29225 if ($size == 0) { return false; }
29226
29227 // $spacer used after named entry
29228 // $sep separates number [groups], $joiner joins numbers in range
29229 // e.g. "elephant 73, 97-99" = elephant[$spacer]73[$sep]97[$joiner]99
29230
29231 // $subEntrySeparator separates main and subentry (if $this->indexUseSubentries == false;) e.g.
29232 // Mammal:elephant => Mammal[$subEntrySeparator]elephant
29233 // $subEntryInset specifies what precedes a subentry (if $this->indexUseSubentries == true;) e.g.
29234 // Mammal:elephant => [$subEntryInset]elephant
29235 $spacer = "\xc2\xa0 ";
29236 if ($this->directionality == 'rtl') { $sep = '&#x060c; '; $joiner = '-'; $subEntrySeparator = '&#x060c; '; $subEntryInset = ' - '; }
29237 else { $sep = ', '; $joiner = '-'; $subEntrySeparator = ', '; $subEntryInset = ' - '; }
29238
29239 for ($i=0;$i<$size;$i++){
29240 $txt = $this->Reference[$i]['t'];
29241 $txt = strip_tags($txt); // mPDF 6
29242 $txt = $this->purify_utf8($txt);
29243 $this->Reference[$i]['uf'] = $txt; // Unformatted e.g. pure utf-8 encoded characters, no mark-up/tags
29244 // Used for ordering and collation
29245 }
29246
29247 if ($usedivletters) {
29248 if ($indexCollationGroup) {
29249 require_once(_MPDF_PATH.'collations/'.$indexCollationGroup.'.php');
29250 }
29251 else { $collation = array(); }
29252 for ($i=0;$i<$size;$i++){
29253 if ($this->Reference[$i]['uf']) {
29254 $l = mb_substr($this->Reference[$i]['uf'],0,1,'UTF-8');
29255 if (isset($this->indexCollationGroup) && $this->indexCollationGroup) {
29256 $uni = $this->UTF8StringToArray($l);
29257 $ucode = $uni[0];
29258 if (isset($collation[$ucode])) { $this->Reference[$i]['d'] = code2utf($collation[$ucode]); }
29259 else { $this->Reference[$i]['d'] = mb_strtolower($l,'UTF-8'); }
29260 }
29261 else { $this->Reference[$i]['d'] = mb_strtolower($l,'UTF-8'); }
29262 }
29263 }
29264 }
29265
29266 if (!function_exists('cmp')) {
29267 function cmp ($a, $b) {
29268 return strcoll(strtolower($a['uf']), strtolower($b['uf']));
29269 }
29270 }
29271 //Alphabetic sort of the references
29272 $originalLocale = setlocale(LC_COLLATE, 0);
29273 if ($indexCollationLocale) { setlocale(LC_COLLATE, $indexCollationLocale); }
29274 usort($this->Reference, 'cmp');
29275 if ($indexCollationLocale) { setlocale(LC_COLLATE, $originalLocale); }
29276
29277 $html = '<div class="mpdf_index_main">';
29278
29279 $lett = '';
29280 $last_lett = '';
29281 $mainentry = '';
29282 for ($i=0;$i<$size;$i++){
29283 if ($this->Reference[$i]['t']) {
29284 if ($usedivletters) {
29285 $lett = $this->Reference[$i]['d'];
29286 if ($lett != $last_lett) { $html .= '<div class="mpdf_index_letter">'.$lett.'</div>'; }
29287 }
29288 $txt = $this->Reference[$i]['t'];
29289
29290 // Sub-entries e.g. Mammals:elephant
29291 // But allow for tags e.g. <b>Mammal</b>:elephants
29292 $a=preg_split('/(<.*?>)/',$txt,-1,PREG_SPLIT_DELIM_CAPTURE);
29293 $txt = '';
29294 $marker = false;
29295 foreach($a as $k => $e) {
29296 if($k%2==0 && !$marker) {
29297 if (strpos($e, ':')!==false) { // == SubEntry
29298 if ($this->indexUseSubentries) {
29299
29300 // If the Main entry does not have any page numbers associated with it
29301 // create and insert an entry
29302 list($txtmain,$sub) = preg_split('/[:]/', $e, 2);
29303 if (strip_tags($txt.$txtmain) != $mainentry) {
29304 $html .= '<div class="mpdf_index_entry">'.$txt.$txtmain.'</div>';
29305 $mainentry = strip_tags($txt.$txtmain);
29306 }
29307
29308 $txt = $subEntryInset;
29309 $e = $sub; // Only replace first one
29310 }
29311 else {
29312 $e = preg_replace('/[:]/', $subEntrySeparator, $e, 1); // Only replace first one
29313 }
29314 $marker = true; // Don't replace any more once the subentry marker has been found
29315 }
29316 }
29317 $txt .= $e;
29318 }
29319
29320 if (!$marker) { $mainentry = strip_tags($txt); }
29321
29322 $html .= '<div class="mpdf_index_entry">';
29323 $html .= $txt;
29324 $ppp = $this->Reference[$i]['p']; // = array of page numbers to point to
29325 if (count($ppp)) {
29326 sort($ppp);
29327 $newarr = array();
29328 $range_start = $ppp[0];
29329 $range_end = 0;
29330
29331 $html .= $spacer;
29332
29333 for ($zi=1;$zi<count($ppp);$zi++) {
29334 if ($ppp[$zi] == ($ppp[($zi-1)]+1)) {
29335 $range_end = $ppp[$zi];
29336 }
29337 else {
29338 if ($range_end) {
29339 if ($range_end == $range_start+1) {
29340 if ($useLinking) { $html .= '<a class="mpdf_index_link" href="@'.$range_start.'">'; }
29341 $html .= $this->docPageNum($range_start);
29342 if ($useLinking) { $html .= '</a>'; }
29343 $html .= $sep;
29344
29345 if ($useLinking) { $html .= '<a class="mpdf_index_link" href="@'.$ppp[$zi-1].'">'; }
29346 $html .= $this->docPageNum($ppp[$zi-1]);
29347 if ($useLinking) { $html .= '</a>'; }
29348 $html .= $sep;
29349 }
29350 }
29351 else {
29352 if ($useLinking) { $html .= '<a class="mpdf_index_link" href="@'.$ppp[$zi-1].'">'; }
29353 $html .= $this->docPageNum($ppp[$zi-1]);
29354 if ($useLinking) { $html .= '</a>'; }
29355 $html .= $sep;
29356 }
29357 $range_start = $ppp[$zi];
29358 $range_end = 0;
29359 }
29360 }
29361
29362 if ($range_end) {
29363 if ($useLinking) { $html .= '<a class="mpdf_index_link" href="@'.$range_start.'">'; }
29364 $html .= $this->docPageNum($range_start);
29365 if ($range_end == $range_start+1) {
29366 if ($useLinking) { $html .= '</a>'; }
29367 $html .= $sep;
29368 if ($useLinking) { $html .= '<a class="mpdf_index_link" href="@'.$range_end.'">'; }
29369 $html .= $this->docPageNum($range_end);
29370 if ($useLinking) { $html .= '</a>'; }
29371 }
29372 else {
29373 $html .= $joiner;
29374 $html .= $this->docPageNum($range_end);
29375 if ($useLinking) { $html .= '</a>'; }
29376 }
29377
29378 }
29379 else {
29380 if ($useLinking) { $html .= '<a class="mpdf_index_link" href="@'.$ppp[(count($ppp)-1)].'">'; }
29381 $html .= $this->docPageNum($ppp[(count($ppp)-1)]);
29382 if ($useLinking) { $html .= '</a>'; }
29383 }
29384 }
29385 }
29386 $html .= '</div>';
29387 $last_lett = $lett;
29388 }
29389 $html .= '</div>';
29390 $save_fpb = $this->fixedPosBlockSave;
29391 $this->WriteHTML($html);
29392 $this->fixedPosBlockSave = $save_fpb;
29393
29394 $this->breakpoints[$this->CurrCol][] = $this->y; // *COLUMNS*
29395 }
29396 /*-- END INDEX --*/
29397
29398
29399 function AcceptPageBreak() {
29400 if (count($this->cellBorderBuffer)) { $this->printcellbuffer(); } // *TABLES*
29401 /*-- COLUMNS --*/
29402 if ($this->ColActive==1) {
29403 if($this->CurrCol<$this->NbCol-1) {
29404 //Go to the next column
29405 $this->CurrCol++;
29406 $this->SetCol($this->CurrCol);
29407 $this->y=$this->y0;
29408 $this->ChangeColumn=1; // Number (and direction) of columns changed +1, +2, -2 etc.
29409 // DIRECTIONALITY RTL
29410 if ($this->directionality == 'rtl') { $this->ChangeColumn = -($this->ChangeColumn); } // *OTL*
29411
29412 //Stay on the page
29413 return false;
29414 }
29415 else {
29416 //Go back to the first column - NEW PAGE
29417 if (count($this->columnbuffer)) { $this->printcolumnbuffer(); }
29418 $this->SetCol(0);
29419 $this->y0 = $this->tMargin;
29420 $this->ChangeColumn= -($this->NbCol-1);
29421 // DIRECTIONALITY RTL
29422 if ($this->directionality == 'rtl') { $this->ChangeColumn = -($this->ChangeColumn); } // *OTL*
29423 //Page break
29424 return true;
29425 }
29426 }
29427 /*-- END COLUMNS --*/
29428 /*-- TABLES --*/
29429 else if ($this->table_rotate) {
29430 if ($this->tablebuffer) { $this->printtablebuffer(); }
29431 return true;
29432 }
29433 /*-- END TABLES --*/
29434 else { // *COLUMNS*
29435 $this->ChangeColumn=0;
29436 return $this->autoPageBreak;
29437 } // *COLUMNS*
29438 return $this->autoPageBreak;
29439 }
29440
29441
29442 //----------- COLUMNS ---------------------
29443 /*-- COLUMNS --*/
29444
29445 function SetColumns($NbCol,$vAlign='',$gap=5) {
29446 // NbCol = number of columns
29447 // Anything less than 2 turns columns off
29448 if ($NbCol<2) { // SET COLUMNS OFF
29449 if ($this->ColActive) {
29450 $this->ColActive=0;
29451 if (count($this->columnbuffer)) { $this->printcolumnbuffer(); }
29452 $this->NbCol=1;
29453 $this->ResetMargins();
29454 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
29455 $this->divwidth = 0;
29456 $this->Ln();
29457 }
29458 $this->ColActive=0;
29459 $this->columnbuffer = array();
29460 $this->ColDetails = array();
29461 $this->columnLinks = array();
29462 $this->columnAnnots = array();
29463 $this->columnForms = array();
29464 $this->col_BMoutlines = array();
29465 $this->col_toc = array();
29466 $this->breakpoints = array();
29467 }
29468 else { // SET COLUMNS ON
29469 if ($this->ColActive) {
29470 $this->ColActive=0;
29471 if (count($this->columnbuffer)) { $this->printcolumnbuffer(); }
29472 $this->ResetMargins();
29473 }
29474 if (isset($this->y) && $this->y>$this->tMargin) $this->Ln();
29475 $this->NbCol=$NbCol;
29476 $this->ColGap = $gap;
29477 $this->divwidth = 0;
29478 $this->ColActive=1;
29479 $this->ColumnAdjust = true; // enables column height adjustment for the page
29480 $this->columnbuffer = array();
29481 $this->ColDetails = array();
29482 $this->columnLinks = array();
29483 $this->columnAnnots = array();
29484 $this->columnForms = array();
29485 $this->col_BMoutlines = array();
29486 $this->col_toc = array();
29487 $this->breakpoints = array();
29488 if ((strtoupper($vAlign) == 'J') || (strtoupper($vAlign) == 'JUSTIFY')) { $vAlign = 'J'; }
29489 else { $vAlign = ''; }
29490 $this->colvAlign = $vAlign;
29491 //Save the ordinate
29492 $absL = $this->DeflMargin-($gap/2);
29493 $absR = $this->DefrMargin-($gap/2);
29494 $PageWidth = $this->w-$absL-$absR; // virtual pagewidth for calculation only
29495 $ColWidth = (($PageWidth - ($gap * ($NbCol)))/$NbCol);
29496 $this->ColWidth = $ColWidth;
29497 /*-- OTL --*/
29498
29499 if ($this->directionality == 'rtl') {
29500 for ($i=0;$i<$this->NbCol;$i++) {
29501 $this->ColL[$i] = $absL + ($gap/2) + (($NbCol - ($i+1))*($PageWidth/$NbCol)) ;
29502 $this->ColR[$i] = $this->ColL[$i] + $ColWidth; // NB This is not R margin -> R pos
29503 }
29504 }
29505 else {
29506 /*-- END OTL --*/
29507 for ($i=0;$i<$this->NbCol;$i++) {
29508 $this->ColL[$i] = $absL + ($gap/2) + ($i* ($PageWidth/$NbCol) );
29509 $this->ColR[$i] = $this->ColL[$i] + $ColWidth; // NB This is not R margin -> R pos
29510 }
29511 } // *OTL*
29512 $this->pgwidth = $ColWidth;
29513 $this->SetCol(0);
29514 $this->y0=$this->y;
29515 }
29516 $this->x = $this->lMargin;
29517 }
29518
29519 function SetCol($CurrCol) {
29520 // Used internally to set column by number: 0 is 1st column
29521 //Set position on a column
29522 $this->CurrCol=$CurrCol;
29523 $x = $this->ColL[$CurrCol];
29524 $xR = $this->ColR[$CurrCol]; // NB This is not R margin -> R pos
29525 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
29526 $x += $this->MarginCorrection ;
29527 $xR += $this->MarginCorrection ;
29528 }
29529 $this->SetMargins($x,($this->w - $xR),$this->tMargin);
29530 }
29531
29532 function AddColumn() {
29533 $this->NewColumn();
29534 $this->ColumnAdjust = false; // disables all column height adjustment for the page.
29535 }
29536 function NewColumn() {
29537 if ($this->ColActive==1) {
29538 if($this->CurrCol<$this->NbCol-1) {
29539 //Go to the next column
29540 $this->CurrCol++;
29541 $this->SetCol($this->CurrCol);
29542 $this->y = $this->y0;
29543 $this->ChangeColumn=1;
29544 // DIRECTIONALITY RTL
29545 if ($this->directionality == 'rtl') { $this->ChangeColumn = -($this->ChangeColumn); } // *OTL*
29546 //Stay on the page
29547 }
29548 else {
29549 //Go back to the first column
29550 //Page break
29551 if (count($this->columnbuffer)) { $this->printcolumnbuffer(); }
29552 $this->AddPage($this->CurOrientation);
29553 $this->SetCol(0);
29554 $this->y0 = $this->tMargin;
29555 $this->ChangeColumn= -($this->NbCol-1);
29556 // DIRECTIONALITY RTL
29557 if ($this->directionality == 'rtl') { $this->ChangeColumn = -($this->ChangeColumn); } // *OTL*
29558 }
29559 $this->x = $this->lMargin;
29560 }
29561 else {
29562 $this->AddPage($this->CurOrientation);
29563 }
29564 }
29565
29566 function printcolumnbuffer() {
29567 // Columns ended (but page not ended) -> try to match all columns - unless disabled by using a custom column-break
29568 if (!$this->ColActive && $this->ColumnAdjust && !$this->keepColumns) {
29569 // Calculate adjustment to add to each column to calculate rel_y value
29570 $this->ColDetails[0]['add_y'] = 0;
29571 $last_col = 0;
29572 // Recursively add previous column's height
29573 for($i=1;$i<$this->NbCol;$i++) {
29574 if (isset($this->ColDetails[$i]['bottom_margin']) && $this->ColDetails[$i]['bottom_margin']) { // If any entries in the column
29575 $this->ColDetails[$i]['add_y'] = ($this->ColDetails[$i-1]['bottom_margin'] - $this->y0) + $this->ColDetails[$i-1]['add_y'];
29576 $last_col = $i; // Last column actually printed
29577 }
29578 }
29579
29580 // Calculate value for each position sensitive entry as though for one column
29581 foreach($this->columnbuffer AS $key=>$s) {
29582 $t = $s['s'];
29583 if ($t == 'ACROFORM') {
29584 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29585 $this->columnbuffer[$key]['s'] = '';
29586 }
29587 else if (preg_match('/BT \d+\.\d\d+ (\d+\.\d\d+) Td/',$t)) {
29588 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29589 }
29590 else if (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ [\-]{0,1}\d+\.\d\d+ re/',$t)) {
29591 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29592 }
29593 else if (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) m/',$t)) {
29594 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29595 }
29596 else if (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) l/',$t)) {
29597 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29598 }
29599 else if (preg_match('/q \d+\.\d\d+ 0 0 \d+\.\d\d+ \d+\.\d\d+ (\d+\.\d\d+) cm \/(I|FO)\d+ Do Q/',$t)) {
29600 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29601 }
29602 else if (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ c/',$t)) {
29603 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29604 }
29605 }
29606 foreach($this->internallink AS $key => $f) {
29607 if (is_array($f) && isset($f['col'])) {
29608 $this->internallink[$key]['rel_y'] = $f['Y'] + $this->ColDetails[$f['col']]['add_y'] - $this->y0;
29609 }
29610 }
29611
29612 $breaks = array();
29613 foreach($this->breakpoints AS $c => $bpa) {
29614 foreach($bpa AS $rely) {
29615 $breaks[] = $rely + $this->ColDetails[$c]['add_y'] - $this->y0;
29616 }
29617 }
29618
29619
29620 if (isset($this->ColDetails[$last_col]['bottom_margin'])) { $lcbm = $this->ColDetails[$last_col]['bottom_margin']; }
29621 else { $lcbm = 0; }
29622 $sum_h = $this->ColDetails[$last_col]['add_y'] + $lcbm - $this->y0;
29623 //$sum_h = max($this->ColDetails[$last_col]['add_y'] + $this->ColDetails[$last_col]['bottom_margin'] - $this->y0, end($breaks));
29624 $target_h = ($sum_h / $this->NbCol);
29625
29626 $cbr = array();
29627 for($i=1;$i<$this->NbCol;$i++) {
29628 $th = ($sum_h * $i / $this->NbCol);
29629 foreach($breaks AS $bk=>$val) {
29630 if ($val > $th) {
29631 if (($val-$th) < ($th-$breaks[$bk-1])) { $cbr[$i-1] = $val; }
29632 else { $cbr[$i-1] = $breaks[$bk-1]; }
29633 break;
29634 }
29635 }
29636 }
29637 $cbr[($this->NbCol-1)] = $sum_h;
29638
29639 // mPDF 6
29640 // Avoid outputing with 1st column empty
29641 if (isset($cbr[0]) && $cbr[0]==0) {
29642 for ($i=0;$i<$this->NbCol-1;$i++) { $cbr[$i] = $cbr[$i+1]; }
29643 }
29644
29645 // Now update the columns - divide into columns of approximately equal value
29646 $last_new_col = 0;
29647 $yadj = 0; // mm
29648 $xadj = 0;
29649 $last_col_bottom = 0;
29650 $lowest_bottom_y = 0;
29651 $block_bottom = 0;
29652 $newcolumn = 0;
29653 foreach($this->columnbuffer AS $key=>$s) {
29654 if (isset($s['rel_y'])) { // only process position sensitive data
29655 if ($s['rel_y'] >= $cbr[$newcolumn]) {
29656 $newcolumn++;
29657 }
29658 else {
29659 $newcolumn = $last_new_col ;
29660 }
29661
29662
29663 $block_bottom = max($block_bottom,($s['rel_y']+$s['h']));
29664
29665 if ($this->directionality == 'rtl') { // *OTL*
29666 $xadj = -(($newcolumn - $s['col']) * ($this->ColWidth + $this->ColGap)); // *OTL*
29667 } // *OTL*
29668 else { // *OTL*
29669 $xadj = ($newcolumn - $s['col']) * ($this->ColWidth + $this->ColGap);
29670 } // *OTL*
29671
29672 if ($last_new_col != $newcolumn) { // Added new column
29673 $last_col_bottom = $this->columnbuffer[$key]['rel_y'];
29674 $block_bottom = 0;
29675 }
29676 $yadj = ($s['rel_y'] - $s['y']) - ($last_col_bottom)+$this->y0;
29677 // callback function
29678 $t = $s['s'];
29679
29680 // mPDF 5.7+
29681 $t = $this->columnAdjustPregReplace('Td', $xadj, $yadj, '/BT (\d+\.\d\d+) (\d+\.\d\d+) Td/', $t);
29682 $t = $this->columnAdjustPregReplace('re', $xadj, $yadj, '/(\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) ([\-]{0,1}\d+\.\d\d+) re/', $t);
29683 $t = $this->columnAdjustPregReplace('l', $xadj, $yadj, '/(\d+\.\d\d+) (\d+\.\d\d+) l/', $t);
29684 $t = $this->columnAdjustPregReplace('img', $xadj, $yadj, '/q (\d+\.\d\d+) 0 0 (\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) cm \/(I|FO)/', $t);
29685 $t = $this->columnAdjustPregReplace('draw', $xadj, $yadj, '/(\d+\.\d\d+) (\d+\.\d\d+) m/', $t);
29686 $t = $this->columnAdjustPregReplace('bezier',$xadj, $yadj, '/(\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) c/', $t);
29687
29688 $this->columnbuffer[$key]['s'] = $t;
29689 $this->columnbuffer[$key]['newcol'] = $newcolumn;
29690 $this->columnbuffer[$key]['newy'] = $s['y'] + $yadj;
29691 $last_new_col = $newcolumn;
29692 $clb = $s['y'] + $yadj + $s['h'] ; // bottom_margin of current
29693 if ((isset($this->ColDetails[$newcolumn]['max_bottom']) && $clb > $this->ColDetails[$newcolumn]['max_bottom']) || (!isset($this->ColDetails[$newcolumn]['max_bottom']) && $clb)) { $this->ColDetails[$newcolumn]['max_bottom'] = $clb; }
29694 if ($clb > $lowest_bottom_y) { $lowest_bottom_y = $clb; }
29695 // Adjust LINKS
29696 if (isset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29697 $ref = $this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29698 $this->PageLinks[$this->page][$ref][0] += ($xadj*_MPDFK);
29699 $this->PageLinks[$this->page][$ref][1] -= ($yadj*_MPDFK);
29700 unset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29701 }
29702 // Adjust FORM FIELDS
29703 if (isset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29704 $ref = $this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29705 $this->mpdfform->forms[$ref]['x'] += ($xadj);
29706 $this->mpdfform->forms[$ref]['y'] += ($yadj);
29707 unset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29708 }
29709 /*-- ANNOTATIONS --*/
29710 if (isset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29711 $ref = $this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29712 if ($this->PageAnnots[$this->page][$ref]['x'] < 0) {
29713 $this->PageAnnots[$this->page][$ref]['x'] -= ($xadj);
29714 }
29715 else {
29716 $this->PageAnnots[$this->page][$ref]['x'] += ($xadj);
29717 }
29718 $this->PageAnnots[$this->page][$ref]['y'] += ($yadj); // unlike PageLinks, Page annots has y values from top in mm
29719 unset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29720 }
29721 /*-- END ANNOTATIONS --*/
29722 }
29723 }
29724
29725 /*-- BOOKMARKS --*/
29726 // Adjust Bookmarks
29727 foreach($this->col_BMoutlines AS $v) {
29728 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$this->y0,'p'=>$v['p']);
29729 }
29730 /*-- END BOOKMARKS --*/
29731
29732 /*-- TOC --*/
29733
29734 // Adjust ToC
29735 foreach($this->col_toc AS $v) {
29736 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$v['p'],'link'=>$v['link'],'toc_id'=>$v['toc_id']);
29737 $this->links[$v['link']][1] = $this->y0;
29738 }
29739 /*-- END TOC --*/
29740
29741 // Adjust column length to be equal
29742 if ($this->colvAlign == 'J') {
29743 foreach($this->columnbuffer AS $key=>$s) {
29744 if (isset($s['rel_y'])) { // only process position sensitive data
29745 // Set ratio to expand y values or heights
29746 if (isset($this->ColDetails[$s['newcol']]['max_bottom']) && $this->ColDetails[$s['newcol']]['max_bottom'] && $this->ColDetails[$s['newcol']]['max_bottom']!=$this->y0) {
29747 $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['newcol']]['max_bottom'] - ($this->y0));
29748 }
29749 else { $ratio = 1; }
29750 if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) {
29751 $yadj = ($s['newy'] - $this->y0) * ($ratio - 1);
29752
29753 // Adjust LINKS
29754 if (isset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29755 $ref = $this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29756 $this->PageLinks[$this->page][$ref][1] -= ($yadj*_MPDFK); // y value
29757 $this->PageLinks[$this->page][$ref][3] *= $ratio; // height
29758 unset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29759 }
29760 // Adjust FORM FIELDS
29761 if (isset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29762 $ref = $this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29763 $this->mpdfform->forms[$ref]['x'] += ($xadj);
29764 $this->mpdfform->forms[$ref]['y'] += ($yadj);
29765 unset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29766 }
29767 /*-- ANNOTATIONS --*/
29768 if (isset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29769 $ref = $this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29770 $this->PageAnnots[$this->page][$ref]['y'] += ($yadj);
29771 unset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29772 }
29773 /*-- END ANNOTATIONS --*/
29774 }
29775 }
29776 }
29777 foreach($this->internallink AS $key => $f) {
29778 if (is_array($f) && isset($f['col'])) {
29779 $last_col_bottom = 0;
29780 for ($nbc=0; $nbc<$this->NbCol; $nbc++) {
29781 if ($f['rel_y'] >= $cbr[$nbc]) { $last_col_bottom = $cbr[$nbc]; }
29782 }
29783 $yadj = ($f['rel_y'] - $f['Y']) - $last_col_bottom + $this->y0;
29784 $f['Y'] += $yadj;
29785 unset($f['col']);
29786 unset($f['rel_y']);
29787 $this->internallink[$key] = $f;
29788 }
29789 }
29790
29791 $last_col = -1;
29792 $trans_on = false;
29793 foreach($this->columnbuffer AS $key=>$s) {
29794 if (isset($s['rel_y'])) { // only process position sensitive data
29795 // Set ratio to expand y values or heights
29796 if (isset($this->ColDetails[$s['newcol']]['max_bottom']) && $this->ColDetails[$s['newcol']]['max_bottom'] && $this->ColDetails[$s['newcol']]['max_bottom']!=$this->y0) {
29797 $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['newcol']]['max_bottom'] - ($this->y0));
29798 }
29799 else { $ratio = 1; }
29800 if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) {
29801 //Start Transformation
29802 $this->pages[$this->page] .= $this->StartTransform(true)."\n";
29803 $this->pages[$this->page] .= $this->transformScale(100, $ratio*100, $x='', $this->y0, true)."\n";
29804 $trans_on = true;
29805 }
29806 }
29807 // Now output the adjusted values
29808 $this->pages[$this->page] .= $s['s']."\n";
29809 if (isset($s['rel_y']) && ($ratio > 1) && ($ratio <= $this->max_colH_correction)) { // only process position sensitive data
29810 //Stop Transformation
29811 $this->pages[$this->page] .= $this->StopTransform(true)."\n";
29812 $trans_on = false;
29813 }
29814 }
29815 if ($trans_on) { $this->pages[$this->page] .= $this->StopTransform(true)."\n"; }
29816 }
29817 else { // if NOT $this->colvAlign == 'J'
29818 // Now output the adjusted values
29819 foreach($this->columnbuffer AS $s) {
29820 $this->pages[$this->page] .= $s['s']."\n";
29821 }
29822 }
29823 if ($lowest_bottom_y > 0) { $this->y = $lowest_bottom_y ; }
29824 }
29825
29826 // Columns not ended but new page -> align columns (can leave the columns alone - just tidy up the height)
29827 else if ($this->colvAlign == 'J' && $this->ColumnAdjust && !$this->keepColumns) {
29828 // calculate the lowest bottom margin
29829 $lowest_bottom_y = 0;
29830 foreach($this->columnbuffer AS $key=>$s) {
29831 // Only process output data
29832 $t = $s['s'];
29833 if ($t == 'ACROFORM' || (preg_match('/BT \d+\.\d\d+ (\d+\.\d\d+) Td/',$t)) || (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ [\-]{0,1}\d+\.\d\d+ re/',$t)) ||
29834 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) l/',$t)) ||
29835 (preg_match('/q \d+\.\d\d+ 0 0 \d+\.\d\d+ \d+\.\d\d+ (\d+\.\d\d+) cm \/(I|FO)\d+ Do Q/',$t)) ||
29836 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) m/',$t)) ||
29837 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ c/',$t)) ) {
29838
29839 $clb = $s['y'] + $s['h'];
29840 if ((isset($this->ColDetails[$s['col']]['max_bottom']) && $clb > $this->ColDetails[$s['col']]['max_bottom']) || !isset($this->ColDetails[$s['col']]['max_bottom'])) { $this->ColDetails[$s['col']]['max_bottom'] = $clb; }
29841 if ($clb > $lowest_bottom_y) { $lowest_bottom_y = $clb; }
29842 $this->columnbuffer[$key]['rel_y'] = $s['y']; // Marks position sensitive data to process later
29843 if ($t == 'ACROFORM') { $this->columnbuffer[$key]['s'] = ''; }
29844 }
29845 }
29846 // Adjust column length equal
29847 foreach($this->columnbuffer AS $key=>$s) {
29848 // Set ratio to expand y values or heights
29849 if (isset($this->ColDetails[$s['col']]['max_bottom']) && $this->ColDetails[$s['col']]['max_bottom']) {
29850 $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['col']]['max_bottom'] - ($this->y0));
29851 }
29852 else { $ratio = 1; }
29853 if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) {
29854 $yadj = ($s['y'] - $this->y0) * ($ratio - 1);
29855
29856 // Adjust LINKS
29857 if (isset($s['rel_y'])) { // only process position sensitive data
29858 // otherwise triggers for all entries in column buffer (.e.g. formatting) and makes below adjustments more than once
29859 if (isset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29860 $ref = $this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29861 $this->PageLinks[$this->page][$ref][1] -= ($yadj*_MPDFK); // y value
29862 $this->PageLinks[$this->page][$ref][3] *= $ratio; // height
29863 unset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29864 }
29865 // Adjust FORM FIELDS
29866 if (isset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29867 $ref = $this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29868 $this->mpdfform->forms[$ref]['x'] += ($xadj);
29869 $this->mpdfform->forms[$ref]['y'] += ($yadj);
29870 unset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29871 }
29872 /*-- ANNOTATIONS --*/
29873 if (isset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29874 $ref = $this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29875 $this->PageAnnots[$this->page][$ref]['y'] += ($yadj);
29876 unset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29877 }
29878 /*-- END ANNOTATIONS --*/
29879 }
29880 }
29881 }
29882
29883 /*-- BOOKMARKS --*/
29884
29885 // Adjust Bookmarks
29886 foreach($this->col_BMoutlines AS $v) {
29887 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$this->y0,'p'=>$v['p']);
29888 }
29889 /*-- END BOOKMARKS --*/
29890
29891 /*-- TOC --*/
29892
29893 // Adjust ToC
29894 foreach($this->col_toc AS $v) {
29895 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$v['p'],'link'=>$v['link'],'toc_id'=>$v['toc_id']);
29896 $this->links[$v['link']][1] = $this->y0;
29897 }
29898 /*-- END TOC --*/
29899 $trans_on = false;
29900 foreach($this->columnbuffer AS $key=>$s) {
29901 if (isset($s['rel_y'])) { // only process position sensitive data
29902 // Set ratio to expand y values or heights
29903 if ($this->ColDetails[$s['col']]['max_bottom']) {
29904 $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['col']]['max_bottom'] - ($this->y0));
29905 }
29906 else { $ratio = 1; }
29907 if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) {
29908 //Start Transformation
29909 $this->pages[$this->page] .= $this->StartTransform(true)."\n";
29910 $this->pages[$this->page] .= $this->transformScale(100, $ratio*100, $x='', $this->y0, true)."\n";
29911 $trans_on = true;
29912 }
29913 }
29914 // Now output the adjusted values
29915 $this->pages[$this->page] .= $s['s']."\n";
29916 if (isset($s['rel_y']) && ($ratio > 1) && ($ratio <= $this->max_colH_correction)) {
29917 //Stop Transformation
29918 $this->pages[$this->page] .= $this->StopTransform(true)."\n";
29919 $trans_on = false;
29920 }
29921 }
29922 if ($trans_on) { $this->pages[$this->page] .= $this->StopTransform(true)."\n"; }
29923
29924 if ($lowest_bottom_y > 0) { $this->y = $lowest_bottom_y ; }
29925 }
29926
29927
29928 // Just reproduce the page as it was
29929 else {
29930 // If page has not ended but height adjustment was disabled by custom column-break - adjust y
29931 $lowest_bottom_y = 0;
29932 if (!$this->ColActive && (!$this->ColumnAdjust || $this->keepColumns)) {
29933 // calculate the lowest bottom margin
29934 foreach($this->columnbuffer AS $key=>$s) {
29935 // Only process output data
29936 $t = $s['s'];
29937 if ($t == 'ACROFORM' || (preg_match('/BT \d+\.\d\d+ (\d+\.\d\d+) Td/',$t)) || (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ [\-]{0,1}\d+\.\d\d+ re/',$t)) ||
29938 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) l/',$t)) ||
29939 (preg_match('/q \d+\.\d\d+ 0 0 \d+\.\d\d+ \d+\.\d\d+ (\d+\.\d\d+) cm \/(I|FO)\d+ Do Q/',$t)) ||
29940 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) m/',$t)) ||
29941 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ c/',$t)) ) {
29942
29943 $clb = $s['y'] + $s['h'];
29944 if ($clb > $this->ColDetails[$s['col']]['max_bottom']) { $this->ColDetails[$s['col']]['max_bottom'] = $clb; }
29945 if ($clb > $lowest_bottom_y) { $lowest_bottom_y = $clb; }
29946 }
29947 }
29948 }
29949 foreach($this->columnbuffer AS $key=>$s) {
29950 if ($s['s'] != 'ACROFORM')
29951 $this->pages[$this->page] .= $s['s']."\n";
29952 }
29953 if ($lowest_bottom_y > 0) { $this->y = $lowest_bottom_y ; }
29954 /*-- BOOKMARKS --*/
29955 // Output Bookmarks
29956 foreach($this->col_BMoutlines AS $v) {
29957 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$v['p']);
29958 }
29959 /*-- END BOOKMARKS --*/
29960 /*-- TOC --*/
29961 // Output ToC
29962 foreach($this->col_toc AS $v) {
29963 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$v['p'],'link'=>$v['link'],'toc_id'=>$v['toc_id']);
29964 }
29965 /*-- END TOC --*/
29966 }
29967 foreach($this->internallink AS $key => $f) {
29968 if (isset($this->internallink[$key]['col'])) unset($this->internallink[$key]['col']);
29969 if (isset($this->internallink[$key]['rel_y'])) unset($this->internallink[$key]['rel_y']);
29970 }
29971
29972 $this->columnbuffer = array();
29973 $this->ColDetails = array();
29974 $this->columnLinks = array();
29975 $this->columnAnnots = array();
29976 $this->columnForms = array();
29977
29978 $this->col_BMoutlines = array();
29979 $this->col_toc = array();
29980 $this->breakpoints = array();
29981 }
29982
29983 // mPDF 5.7+
29984 function columnAdjustPregReplace($type, $xadj, $yadj, $pattern, $subject) {
29985 preg_match($pattern, $subject, $matches);
29986 if (!count($matches)) { return $subject; }
29987 if (!isset($matches[3])) { $matches[3] = 0; }
29988 if (!isset($matches[4])) { $matches[4] = 0; }
29989 if (!isset($matches[5])) { $matches[5] = 0; }
29990 if (!isset($matches[6])) { $matches[6] = 0; }
29991 return str_replace($matches[0], $this->columnAdjustAdd($type, _MPDFK, $xadj, $yadj, $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]), $subject);
29992 }
29993
29994 /*-- END COLUMNS --*/
29995
29996
29997 //==================================================================
29998 /*-- TABLES --*/
29999 function printcellbuffer() {
30000 if (count($this->cellBorderBuffer )) {
30001 sort($this->cellBorderBuffer);
30002 foreach($this->cellBorderBuffer AS $cbb) {
30003 $cba = unpack("A16dom/nbord/A1side/ns/dbw/a6ca/A10style/dx/dy/dw/dh/dmbl/dmbr/dmrt/dmrb/dmtl/dmtr/dmlt/dmlb/dcpd/dover/", $cbb);
30004 $side = $cba['side'];
30005 $color = str_pad($cba['ca'], 6, "\x00");
30006 $details = array();
30007 $details[$side]['dom'] = (float) $cba['dom'];
30008 $details[$side]['s'] = $cba['s'];
30009 $details[$side]['w'] = $cba['bw'];
30010 $details[$side]['c'] = $color;
30011 $details[$side]['style'] = trim($cba['style']);
30012 $details['mbw']['BL'] = $cba['mbl'];
30013 $details['mbw']['BR'] = $cba['mbr'];
30014 $details['mbw']['RT'] = $cba['mrt'];
30015 $details['mbw']['RB'] = $cba['mrb'];
30016 $details['mbw']['TL'] = $cba['mtl'];
30017 $details['mbw']['TR'] = $cba['mtr'];
30018 $details['mbw']['LT'] = $cba['mlt'];
30019 $details['mbw']['LB'] = $cba['mlb'];
30020 $details['cellposdom'] = $cba['cpd'];
30021 $details['p'] = $side;
30022 if ($cba['over']==1) { $details[$side]['overlay'] = true; }
30023 else { $details[$side]['overlay'] = false; }
30024 $this->_tableRect($cba['x'],$cba['y'],$cba['w'],$cba['h'],$cba['bord'],$details, false, false);
30025
30026 }
30027 $this->cellBorderBuffer = array();
30028 }
30029 }
30030 //==================================================================
30031 function printtablebuffer() {
30032
30033 if (!$this->table_rotate) {
30034 $this->pages[$this->page] .= $this->tablebuffer;
30035 foreach($this->tbrot_Links AS $p => $l) {
30036 foreach($l AS $v) {
30037 $this->PageLinks[$p][] = $v;
30038 }
30039 }
30040 $this->tbrot_Links = array();
30041 /*-- ANNOTATIONS --*/
30042 foreach($this->tbrot_Annots AS $p => $l) {
30043 foreach($l AS $v) {
30044 $this->PageAnnots[$p][] = $v;
30045 }
30046 }
30047 $this->tbrot_Annots = array();
30048 /*-- END ANNOTATIONS --*/
30049
30050 /*-- BOOKMARKS --*/
30051 // Output Bookmarks
30052 foreach($this->tbrot_BMoutlines AS $v) {
30053 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$v['p']);
30054 }
30055 $this->tbrot_BMoutlines = array();
30056 /*-- END BOOKMARKS --*/
30057
30058 /*-- TOC --*/
30059 // Output ToC
30060 foreach($this->tbrot_toc AS $v) {
30061 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$v['p'],'link'=>$v['link'],'toc_id'=>$v['toc_id']);
30062 }
30063 $this->tbrot_toc = array();
30064 /*-- END TOC --*/
30065
30066 return;
30067 }
30068 // else if rotated
30069 $lm = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_left'];
30070 $pw = $this->blk[$this->blklvl]['inner_width'];
30071 //Start Transformation
30072 $this->pages[$this->page] .= $this->StartTransform(true)."\n";
30073
30074 if ($this->table_rotate > 1) { // clockwise
30075 if ($this->tbrot_align == 'L') {
30076 $xadj = $this->tbrot_h ; // align L (as is)
30077 }
30078 else if ($this->tbrot_align == 'R') {
30079 $xadj = $lm-$this->tbrot_x0+($pw) ; // align R
30080 }
30081 else {
30082 $xadj = $lm-$this->tbrot_x0+(($pw + $this->tbrot_h)/2) ; // align C
30083 }
30084 $yadj = 0;
30085 }
30086 else { // anti-clockwise
30087 if ($this->tbrot_align == 'L') {
30088 $xadj = 0 ; // align L (as is)
30089 }
30090 else if ($this->tbrot_align == 'R') {
30091 $xadj = $lm-$this->tbrot_x0+($pw - $this->tbrot_h) ; // align R
30092 }
30093 else {
30094 $xadj = $lm-$this->tbrot_x0+(($pw - $this->tbrot_h)/2) ; // align C
30095 }
30096 $yadj = $this->tbrot_w;
30097 }
30098
30099
30100 $this->pages[$this->page] .= $this->transformTranslate($xadj, $yadj , true)."\n";
30101 $this->pages[$this->page] .= $this->transformRotate($this->table_rotate, $this->tbrot_x0 , $this->tbrot_y0 , true)."\n";
30102
30103 // Now output the adjusted values
30104 $this->pages[$this->page] .= $this->tablebuffer;
30105
30106
30107 foreach($this->tbrot_Links AS $p => $l) {
30108 foreach($l AS $v) {
30109 $w = $v[2]/_MPDFK;
30110 $h = $v[3]/_MPDFK;
30111 $ax = ($v[0]/_MPDFK) - $this->tbrot_x0;
30112 $ay = (($this->hPt-$v[1])/_MPDFK) - $this->tbrot_y0;
30113 if ($this->table_rotate > 1) { // clockwise
30114 $bx = $this->tbrot_x0+$xadj-$ay-$h;
30115 $by = $this->tbrot_y0+$yadj+$ax;
30116 }
30117 else {
30118 $bx = $this->tbrot_x0+$xadj+$ay;
30119 $by = $this->tbrot_y0+$yadj-$ax-$w;
30120 }
30121 $v[0] = $bx*_MPDFK;
30122 $v[1] = ($this->h-$by)*_MPDFK;
30123 $v[2] = $h*_MPDFK; // swap width and height
30124 $v[3] = $w*_MPDFK;
30125 $this->PageLinks[$p][] = $v;
30126 }
30127 }
30128 $this->tbrot_Links = array();
30129 foreach($this->internallink AS $key => $f) {
30130 if (is_array($f) && isset($f['tbrot'])) {
30131 $f['Y'] = $this->tbrot_y0;
30132 $f['PAGE'] = $this->page;
30133 unset($f['tbrot']);
30134 $this->internallink[$key] = $f;
30135 }
30136 }
30137 /*-- ANNOTATIONS --*/
30138 foreach($this->tbrot_Annots AS $p => $l) {
30139 foreach($l AS $v) {
30140 $ax = abs($v['x']) - $this->tbrot_x0; // abs because -ve values are internally set and held for reference if annotMargin set
30141 $ay = $v['y'] - $this->tbrot_y0;
30142 if ($this->table_rotate > 1) { // clockwise
30143 $bx = $this->tbrot_x0+$xadj-$ay;
30144 $by = $this->tbrot_y0+$yadj+$ax;
30145 }
30146 else {
30147 $bx = $this->tbrot_x0+$xadj+$ay;
30148 $by = $this->tbrot_y0+$yadj-$ax;
30149 }
30150 if ($v['x'] < 0) {
30151 $v['x'] = -$bx;
30152 }
30153 else {
30154 $v['x'] = $bx;
30155 }
30156 $v['y'] = ($by);
30157 $this->PageAnnots[$p][] = $v;
30158 }
30159 }
30160 $this->tbrot_Annots = array();
30161 /*-- END ANNOTATIONS --*/
30162
30163
30164 /*-- BOOKMARKS --*/
30165
30166 // Adjust Bookmarks
30167 foreach($this->tbrot_BMoutlines AS $v) {
30168 $v['y'] = $this->tbrot_y0;
30169 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$this->page);
30170 }
30171 /*-- END BOOKMARKS --*/
30172
30173 /*-- TOC --*/
30174
30175 // Adjust ToC - uses document page number
30176 foreach($this->tbrot_toc AS $v) {
30177 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$this->page,'link'=>$v['link'],'toc_id'=>$v['toc_id']);
30178 $this->links[$v['link']][1] = $this->tbrot_y0;
30179 }
30180 /*-- END TOC --*/
30181
30182
30183
30184 $this->tbrot_BMoutlines = array();
30185 $this->tbrot_toc = array();
30186
30187 //Stop Transformation
30188 $this->pages[$this->page] .= $this->StopTransform(true)."\n";
30189
30190
30191 $this->y = $this->tbrot_y0 + $this->tbrot_w;
30192 $this->x = $this->lMargin;
30193
30194 $this->tablebuffer = '';
30195 }
30196
30197 //==================================================================
30198 // Keep-with-table This buffers contents of h1-6 to keep on page with table
30199 function printkwtbuffer() {
30200 if (!$this->kwt_moved) {
30201 foreach($this->kwt_buffer AS $s) { $this->pages[$this->page] .= $s['s']."\n"; }
30202 foreach($this->kwt_Links AS $p => $l) {
30203 foreach($l AS $v) {
30204 $this->PageLinks[$p][] = $v;
30205 }
30206 }
30207 $this->kwt_Links = array();
30208 /*-- ANNOTATIONS --*/
30209 foreach($this->kwt_Annots AS $p => $l) {
30210 foreach($l AS $v) {
30211 $this->PageAnnots[$p][] = $v;
30212 }
30213 }
30214 $this->kwt_Annots = array();
30215 /*-- END ANNOTATIONS --*/
30216
30217 /*-- INDEX --*/
30218 // Output Reference (index)
30219 foreach($this->kwt_Reference AS $v) {
30220 $Present=0;
30221 for ($i=0;$i<count($this->Reference);$i++){
30222 if ($this->Reference[$i]['t']==$v['t']){
30223 $Present=1;
30224 if (!in_array($v['op'],$this->Reference[$i]['p'])) {
30225 $this->Reference[$i]['p'][] = $v['op'];
30226 }
30227 }
30228 }
30229 if ($Present==0) {
30230 $this->Reference[]=array('t'=>$v['t'],'p'=>array($v['op']));
30231 }
30232 }
30233 $this->kwt_Reference = array();
30234 /*-- END INDEX --*/
30235
30236 /*-- BOOKMARKS --*/
30237 // Output Bookmarks
30238 foreach($this->kwt_BMoutlines AS $v) {
30239 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$v['p']);
30240 }
30241 $this->kwt_BMoutlines = array();
30242 /*-- END BOOKMARKS --*/
30243
30244 /*-- TOC --*/
30245 // Output ToC
30246 foreach($this->kwt_toc AS $v) {
30247 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$v['p'],'link'=>$v['link'],'toc_id'=>$v['toc_id']);
30248 }
30249 $this->kwt_toc = array();
30250 /*-- END TOC --*/
30251
30252 $this->pageoutput[$this->page] = array(); // mPDF 6
30253 return;
30254 }
30255
30256 //Start Transformation
30257 $this->pages[$this->page] .= $this->StartTransform(true)."\n";
30258 $xadj = $this->lMargin - $this->kwt_x0 ;
30259 //$yadj = $this->y - $this->kwt_y0 ;
30260 $yadj = $this->tMargin - $this->kwt_y0 ;
30261
30262 $this->pages[$this->page] .= $this->transformTranslate($xadj, $yadj , true)."\n";
30263
30264 // Now output the adjusted values
30265 foreach($this->kwt_buffer AS $s) { $this->pages[$this->page] .= $s['s']."\n"; }
30266
30267 // Adjust hyperLinks
30268 foreach($this->kwt_Links AS $p => $l) {
30269 foreach($l AS $v) {
30270 $bx = $this->kwt_x0+$xadj;
30271 $by = $this->kwt_y0+$yadj;
30272 $v[0] = $bx*_MPDFK;
30273 $v[1] = ($this->h-$by)*_MPDFK;
30274 $this->PageLinks[$p][] = $v;
30275 }
30276 }
30277 foreach($this->internallink AS $key => $f) {
30278 if (is_array($f) && isset($f['kwt'])) {
30279 $f['Y'] += $yadj;
30280 $f['PAGE'] = $this->page;
30281 unset($f['kwt']);
30282 $this->internallink[$key] = $f;
30283 }
30284 }
30285 /*-- ANNOTATIONS --*/
30286 foreach($this->kwt_Annots AS $p => $l) {
30287 foreach($l AS $v) {
30288 $bx = $this->kwt_x0+$xadj;
30289 $by = $this->kwt_y0+$yadj;
30290 if ($v['x'] < 0) {
30291 $v['x'] = -$bx;
30292 }
30293 else {
30294 $v['x'] = $bx;
30295 }
30296 $v['y'] = $by;
30297 $this->PageAnnots[$p][] = $v;
30298 }
30299 }
30300 /*-- END ANNOTATIONS --*/
30301
30302 /*-- BOOKMARKS --*/
30303
30304 // Adjust Bookmarks
30305 foreach($this->kwt_BMoutlines AS $v) {
30306 if ($v['y'] != 0) { $v['y'] += $yadj; }
30307 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$this->page);
30308 }
30309 /*-- END BOOKMARKS --*/
30310
30311 /*-- INDEX --*/
30312
30313 // Adjust Reference (index)
30314 foreach($this->kwt_Reference AS $v) {
30315 $Present=0;
30316 //Search the reference (AND Ref/PageNo) in the array
30317 for ($i=0;$i<count($this->Reference);$i++){
30318 if ($this->Reference[$i]['t']==$v['t']){
30319 $Present=1;
30320 if (!in_array($this->page,$this->Reference[$i]['p'])) {
30321 $this->Reference[$i]['p'][] = $this->page;
30322 }
30323 }
30324 }
30325 if ($Present==0) {
30326 $this->Reference[]=array('t'=>$v['t'],'p'=>array($this->page));
30327 }
30328 }
30329 /*-- END INDEX --*/
30330
30331 /*-- TOC --*/
30332
30333 // Adjust ToC
30334 foreach($this->kwt_toc AS $v) {
30335 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$this->page,'link'=>$v['link'],'toc_id'=>$v['toc_id']);
30336 $this->links[$v['link']][0] = $this->page;
30337 $this->links[$v['link']][1] += $yadj;
30338 }
30339 /*-- END TOC --*/
30340
30341
30342 $this->kwt_Links = array();
30343 $this->kwt_Annots = array();
30344
30345 $this->kwt_Reference = array();
30346 $this->kwt_BMoutlines = array();
30347 $this->kwt_toc = array();
30348 //Stop Transformation
30349 $this->pages[$this->page] .= $this->StopTransform(true)."\n";
30350
30351 $this->kwt_buffer = array();
30352
30353 $this->y += $this->kwt_height;
30354 $this->pageoutput[$this->page] = array(); // mPDF 6
30355 }
30356
30357 /*-- END TABLES --*/
30358
30359
30360 //==================================================================
30361
30362 function printfloatbuffer() {
30363 if (count($this->floatbuffer)) {
30364 $this->objectbuffer = $this->floatbuffer;
30365 $this->printobjectbuffer(false);
30366 $this->objectbuffer = array();
30367 $this->floatbuffer = array();
30368 $this->floatmargins = array();
30369 }
30370 }
30371 //==================================================================
30372
30373
30374
30375 //==================================================================
30376 // Added ELLIPSES and CIRCLES
30377 function Circle($x,$y,$r,$style='S') {
30378 $this->Ellipse($x,$y,$r,$r,$style);
30379 }
30380
30381 function Ellipse($x,$y,$rx,$ry,$style='S') {
30382 if($style=='F') { $op='f'; }
30383 elseif($style=='FD' or $style=='DF') { $op='B'; }
30384 else { $op='S'; }
30385 $lx=4/3*(M_SQRT2-1)*$rx;
30386 $ly=4/3*(M_SQRT2-1)*$ry;
30387 $h=$this->h;
30388 $this->_out(sprintf('%.3F %.3F m %.3F %.3F %.3F %.3F %.3F %.3F c', ($x+$rx)*_MPDFK,($h-$y)*_MPDFK, ($x+$rx)*_MPDFK,($h-($y-$ly))*_MPDFK, ($x+$lx)*_MPDFK,($h-($y-$ry))*_MPDFK, $x*_MPDFK,($h-($y-$ry))*_MPDFK));
30389 $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c', ($x-$lx)*_MPDFK,($h-($y-$ry))*_MPDFK, ($x-$rx)*_MPDFK,($h-($y-$ly))*_MPDFK, ($x-$rx)*_MPDFK,($h-$y)*_MPDFK));
30390 $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c', ($x-$rx)*_MPDFK,($h-($y+$ly))*_MPDFK, ($x-$lx)*_MPDFK,($h-($y+$ry))*_MPDFK, $x*_MPDFK,($h-($y+$ry))*_MPDFK));
30391 $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c %s', ($x+$lx)*_MPDFK,($h-($y+$ry))*_MPDFK, ($x+$rx)*_MPDFK,($h-($y+$ly))*_MPDFK, ($x+$rx)*_MPDFK,($h-$y)*_MPDFK, $op));
30392 }
30393
30394 /*-- DIRECTW --*/
30395 // Added adaptation of shaded_box = AUTOSIZE-TEXT
30396 function AutosizeText($text,$w,$font,$style,$szfont=72) {
30397
30398 $text = ' '.$text.' ';
30399
30400 $this->SetFont($font,$style,$szfont,false);
30401
30402 $text = $this->purify_utf8_text($text);
30403 if ($this->text_input_as_HTML) {
30404 $text = $this->all_entities_to_utf8($text);
30405 }
30406 if ($this->usingCoreFont) { $text = mb_convert_encoding($text,$this->mb_enc,'UTF-8'); }
30407
30408 // DIRECTIONALITY
30409 if (preg_match("/([".$this->pregRTLchars."])/u", $text)) { $this->biDirectional = true; } // *OTL*
30410
30411 $textvar = 0;
30412 $save_OTLtags = $this->OTLtags;
30413 $this->OTLtags = array();
30414 if ($this->useKerning) {
30415 if ($this->CurrentFont['haskernGPOS']) { $this->OTLtags['Plus'] .= ' kern'; }
30416 else { $textvar = ($textvar | FC_KERNING); }
30417 }
30418
30419 /*-- OTL --*/
30420 // Use OTL OpenType Table Layout - GSUB & GPOS
30421 if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
30422 $text = $this->otl->applyOTL($text, $this->CurrentFont['useOTL']);
30423 $OTLdata = $this->otl->OTLdata;
30424 }
30425 /*-- END OTL --*/
30426 $this->OTLtags = $save_OTLtags ;
30427
30428 $this->magic_reverse_dir($text, $this->directionality, $OTLdata);
30429
30430
30431 $width = $this->ConvertSize($w);
30432 $loop = 0;
30433 while ( $loop == 0 ) {
30434 $this->SetFont($font,$style,$szfont,false);
30435 $sz = $this->GetStringWidth( $text, true, $OTLdata, $textvar );
30436 if ( $sz > $w ) { $szfont --; }
30437 else { $loop ++; }
30438 }
30439 $this->SetFont($font,$style,$szfont,true,true);
30440 $this->Cell($w, 0, $text, 0, 0, "C",0,'',0,0,0,'M', 0, false, $OTLdata, $textvar );
30441 }
30442 /*-- END DIRECTW --*/
30443
30444
30445
30446
30447
30448 // ====================================================
30449 // ====================================================
30450
30451 function magic_reverse_dir(&$chunk, $dir, &$chunkOTLdata) {
30452 /*-- OTL --*/
30453 if ($this->usingCoreFont) { return 0; }
30454 if ($chunk=='') { return 0; }
30455
30456 if ($this->biDirectional || $dir=='rtl') {
30457 // check if string contains RTL text
30458 // including any added from OTL tables (in PUA)
30459 $pregRTLchars = $this->pregRTLchars;
30460 if (isset($this->CurrentFont['rtlPUAstr']) && $this->CurrentFont['rtlPUAstr']) { $pregRTLchars .= $this->CurrentFont['rtlPUAstr']; }
30461 if (!preg_match("/[".$pregRTLchars."]/u",$chunk) && $dir!='rtl') { return 0; } // Chunk doesn't contain RTL characters
30462
30463 $unicode = $this->UTF8StringToArray($chunk, false);
30464
30465 $is_strong = false;
30466 if (empty($chunkOTLdata)) { $this->getBasicOTLdata($chunkOTLdata, $unicode, $is_strong); }
30467
30468 if (isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0x80) ) { $useGPOS = true; }
30469 else { $useGPOS = false; }
30470
30471 // NB Returned $chunk may be a shorter string (with adjusted $cOTLdata) by removal of LRE, RLE etc embedding codes.
30472 list($chunk ,$rtl_content) = $this->otl->_bidiSort($unicode, $chunk, $dir, $chunkOTLdata, $useGPOS);
30473
30474 return $rtl_content;
30475 }
30476 /*-- END OTL --*/
30477 return 0;
30478 }
30479
30480
30481 /*-- OTL --*/
30482 function getBasicOTLdata(&$chunkOTLdata, $unicode, &$is_strong) {
30483 if (!class_exists('otl', false)) { include(_MPDF_PATH.'classes/otl.php'); }
30484 if (empty($this->otl)) { $this->otl = new otl($this); }
30485 $chunkOTLdata['group'] = '';
30486 $chunkOTLdata['GPOSinfo'] = array();
30487 $chunkOTLdata['char_data'] = array();
30488 foreach($unicode as $char) {
30489 $ucd_record = UCDN::get_ucd_record($char);
30490 $chunkOTLdata['char_data'][] = array('bidi_class' => $ucd_record[2], 'uni' => $char);
30491 if ($ucd_record[2]==0 || $ucd_record[2]==3 || $ucd_record[2]==4) { $is_strong = true; } // contains strong character
30492 if ($ucd_record[0] == UCDN::UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { $chunkOTLdata['group'] .= 'M'; }
30493 else if ($char == 32 || $char == 12288) { $chunkOTLdata['group'] .= 'S'; }
30494 else { $chunkOTLdata['group'] .= 'C'; }
30495 }
30496 }
30497
30498 function _setBidiCodes($mode='start', $bdf) {
30499 $s = '';
30500 if ($mode=='end') {
30501 // PDF comes before PDI to close isolate-override (e.g. "LRILROPDFPDI")
30502 if (strpos($bdf, 'PDF')!==false) { $s .= code2utf(0x202C); } // POP DIRECTIONAL FORMATTING
30503 if (strpos($bdf, 'PDI')!==false) { $s .= code2utf(0x2069); } // POP DIRECTIONAL ISOLATE
30504 }
30505 else if ($mode=='start') {
30506 // LRI comes before LRO to open isolate-override (e.g. "LRILROPDFPDI")
30507 if (strpos($bdf, 'LRI')!==false) { $s .= code2utf(0x2066); } // U+2066 LRI
30508 else if (strpos($bdf, 'RLI')!==false) { $s .= code2utf(0x2067); } // U+2067 RLI
30509 else if (strpos($bdf, 'FSI')!==false) { $s .= code2utf(0x2068); } // U+2068 FSI
30510 if (strpos($bdf, 'LRO')!==false) { $s .= code2utf(0x202D); } // U+202D LRO
30511 else if (strpos($bdf, 'RLO')!==false) { $s .= code2utf(0x202E); } // U+202E RLO
30512 else if (strpos($bdf, 'LRE')!==false) { $s .= code2utf(0x202A); } // U+202A LRE
30513 else if (strpos($bdf, 'RLE')!==false) { $s .= code2utf(0x202B); } // U+202B RLE
30514 }
30515 return $s;
30516 }
30517
30518 /*-- END OTL --*/
30519
30520 //
30521 // ****************************
30522
30523 // ****************************
30524
30525
30526 function SetSubstitutions() {
30527 $subsarray = array();
30528 @include(_MPDF_PATH.'includes/subs_win-1252.php');
30529 $this->substitute = array();
30530 foreach($subsarray AS $key => $val) {
30531 $this->substitute[code2utf($key)] = $val;
30532 }
30533 }
30534
30535
30536 function SubstituteChars($html) {
30537 // only substitute characters between tags
30538 if (count($this->substitute)) {
30539 $a=preg_split('/(<.*?>)/ms',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
30540 $html = '';
30541 foreach($a as $i => $e) {
30542 if($i%2==0) {
30543 $e = strtr($e, $this->substitute);
30544 }
30545 $html .= $e;
30546 }
30547 }
30548 return $html;
30549 }
30550
30551
30552 function SubstituteCharsSIP(&$writehtml_a, &$writehtml_i, &$writehtml_e) {
30553 if (preg_match("/^(.*?)([\x{20000}-\x{2FFFF}]+)(.*)/u", $writehtml_e, $m)) {
30554 if (isset($this->CurrentFont['sipext']) && $this->CurrentFont['sipext']) {
30555 $font = $this->CurrentFont['sipext'];
30556 if (!in_array($font, $this->available_unifonts)) { return 0; }
30557 $writehtml_a[$writehtml_i] = $writehtml_e = $m[1];
30558 array_splice($writehtml_a, $writehtml_i+1, 0, array('span style="font-family: '.$font.'"', $m[2], '/span', $m[3]));
30559 $this->subPos = $writehtml_i;
30560 return 4;
30561 }
30562 }
30563 return 0;
30564 }
30565
30566 // If core font is selected in document which is not onlyCoreFonts - substitute with non-core font
30567 function SubstituteCharsNonCore(&$writehtml_a, &$writehtml_i, &$writehtml_e) {
30568 // Ignore if in Textarea
30569 if ($writehtml_i > 0 && strtolower(substr($writehtml_a[$writehtml_i-1],0,8)) == 'textarea') { return 0; }
30570 if (mb_convert_encoding(mb_convert_encoding($writehtml_e, $this->mb_enc, "UTF-8"), "UTF-8", $this->mb_enc) == $writehtml_e) {
30571 return 0;
30572 }
30573 $cw = &$this->CurrentFont['cw'];
30574 $unicode = $this->UTF8StringToArray($writehtml_e, false);
30575 $start = -1;
30576 $end = 0;
30577 $flag = 0;
30578 $ftype = '';
30579 $u = array();
30580 if (!$this->subArrMB) {
30581 include(_MPDF_PATH.'includes/subs_core.php');
30582 $this->subArrMB['a'] = $aarr;
30583 $this->subArrMB['s'] = $sarr;
30584 $this->subArrMB['z'] = $zarr;
30585 }
30586 foreach($unicode AS $c => $char) {
30587 if (($char> 127 || ($flag==1 && $char==32)) && $char != 173 && (!isset($this->subArrMB['a'][$char]) || ($flag==1 && $char==32)) && ($char<1536 || ($char>1791 && $char < 2304) || $char>3455)) {
30588 if ($flag==0) { $start=$c; }
30589 $flag=1;
30590 $u[] = $char;
30591 }
30592 else if ($flag>0) { $end=$c-1; break; }
30593 }
30594 if ($flag>0 && !$end) { $end=count($unicode)-1; }
30595 if ($start==-1) { return 0; }
30596 // TRY IN BACKUP SUBS FONT
30597 if (!is_array($this->backupSubsFont)) { $this->backupSubsFont = array("$this->backupSubsFont"); }
30598 foreach($this->backupSubsFont AS $bsfctr=>$bsf) {
30599 if ($this->fonttrans[$bsf] == 'chelvetica' || $this->fonttrans[$bsf] == 'ctimes' || $this->fonttrans[$bsf] == 'ccourier') { continue; }
30600 $font = $bsf;
30601 unset($cw);
30602 $cw = '';
30603 if (isset($this->fonts[$font])) { $cw = &$this->fonts[$font]['cw']; }
30604 else if (file_exists(_MPDF_TTFONTDATAPATH.$font.'.cw.dat')) { $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat'); }
30605 else {
30606
30607 $prevFontFamily = $this->FontFamily;
30608 $prevFontStyle = $this->currentfontstyle;
30609 $prevFontSizePt = $this->FontSizePt;
30610 $this->SetFont($bsf, '', '', false);
30611 $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat');
30612 $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false);
30613 }
30614 if (!$cw) { continue; }
30615 $l = 0;
30616 foreach($u AS $char) {
30617 if ($char == 173 || $this->_charDefined($cw,$char) || ($char>1536 && $char<1791) || ($char>2304 && $char<3455 )) {
30618 $l++;
30619 }
30620 else {
30621 if ($l==0 && $bsfctr == (count($this->backupSubsFont)-1)) { // Not found even in last backup font
30622 $cont = mb_substr($writehtml_e, $start+1);
30623 $writehtml_e = mb_substr($writehtml_e, 0, $start+1, 'UTF-8');
30624 array_splice($writehtml_a, $writehtml_i+1, 0, array('', $cont));
30625 $this->subPos = $writehtml_i+1;
30626 return 2;
30627 }
30628 else { break; }
30629 }
30630 }
30631 if ($l > 0) {
30632 $patt = mb_substr($writehtml_e, $start, $l, 'UTF-8');
30633 if (preg_match("/(.*?)(".preg_quote($patt,'/').")(.*)/u", $writehtml_e, $m)) {
30634 $writehtml_e = $m[1];
30635 array_splice($writehtml_a, $writehtml_i+1, 0, array('span style="font-family: '.$font.'"', $m[2], '/span', $m[3]));
30636 $this->subPos = $writehtml_i+3;
30637 return 4;
30638 }
30639 }
30640 }
30641
30642 unset($cw);
30643 return 0;
30644 }
30645
30646
30647 function SubstituteCharsMB(&$writehtml_a, &$writehtml_i, &$writehtml_e) {
30648 // Ignore if in Textarea
30649 if ($writehtml_i > 0 && strtolower(substr($writehtml_a[$writehtml_i-1],0,8)) == 'textarea') { return 0; }
30650 $cw = &$this->CurrentFont['cw'];
30651 $unicode = $this->UTF8StringToArray($writehtml_e, false);
30652 $start = -1;
30653 $end = 0;
30654 $flag = 0;
30655 $ftype = '';
30656 $u = array();
30657 foreach($unicode AS $c => $char) {
30658 if (($flag == 0 || $flag==2) && (!$this->_charDefined($cw,$char) || ($flag==2 && $char==32)) && $this->checkSIP && $char > 131071) { // Unicode Plane 2 (SIP)
30659 if (in_array($this->FontFamily ,$this->available_CJK_fonts)) { return 0; }
30660 if ($flag==0) { $start=$c; }
30661 $flag=2;
30662 $u[] = $char;
30663 }
30664 //else if (($flag == 0 || $flag==1) && $char != 173 && !$this->_charDefined($cw,$char) && ($char<1423 || ($char>3583 && $char < 11263))) {
30665 else if (($flag == 0 || $flag==1) && $char != 173 && (!$this->_charDefined($cw,$char) || ($flag==1 && $char==32)) && ($char<1536 || ($char>1791 && $char < 2304) || $char>3455)) {
30666 if ($flag==0) { $start=$c; }
30667 $flag=1;
30668 $u[] = $char;
30669 }
30670 else if ($flag>0) { $end=$c-1; break; }
30671 }
30672 if ($flag>0 && !$end) { $end=count($unicode)-1; }
30673 if ($start==-1) { return 0; }
30674 if ($flag == 2) { // SIP
30675 // Check if current CJK font has a ext-B related font
30676 if (isset($this->CurrentFont['sipext']) && $this->CurrentFont['sipext']) {
30677 $font = $this->CurrentFont['sipext'];
30678 unset($cw);
30679 $cw = '';
30680 if (isset($this->fonts[$font])) { $cw = &$this->fonts[$font]['cw']; }
30681 else if (file_exists(_MPDF_TTFONTDATAPATH.$font.'.cw.dat')) { $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat'); }
30682 else {
30683 $prevFontFamily = $this->FontFamily;
30684 $prevFontStyle = $this->currentfontstyle;
30685 $prevFontSizePt = $this->FontSizePt;
30686 $this->SetFont($font, '', '', false);
30687 $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat');
30688 $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false);
30689 }
30690 if (!$cw) { return 0; }
30691 $l = 0;
30692 foreach($u AS $char) {
30693 if ($this->_charDefined($cw,$char) || $char > 131071) {
30694 $l++;
30695 }
30696 else { break; }
30697 }
30698 if ($l > 0) {
30699 $patt = mb_substr($writehtml_e, $start, $l);
30700 if (preg_match("/(.*?)(".preg_quote($patt,'/').")(.*)/u", $writehtml_e, $m)) {
30701 $writehtml_e = $m[1];
30702 array_splice($writehtml_a, $writehtml_i+1, 0, array('span style="font-family: '.$font.'"', $m[2], '/span', $m[3]));
30703 $this->subPos = $writehtml_i+3;
30704 return 4;
30705 }
30706 }
30707 }
30708 // Check Backup SIP font (defined in config_fonts.php)
30709 if (isset($this->backupSIPFont) && $this->backupSIPFont) {
30710 if ($this->currentfontfamily != $this->backupSIPFont) { $font = $this->backupSIPFont; }
30711 else { unset($cw); return 0; }
30712 unset($cw);
30713 $cw = '';
30714 if (isset($this->fonts[$font])) { $cw = &$this->fonts[$font]['cw']; }
30715 else if (file_exists(_MPDF_TTFONTDATAPATH.$font.'.cw.dat')) { $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat'); }
30716 else {
30717 $prevFontFamily = $this->FontFamily;
30718 $prevFontStyle = $this->currentfontstyle;
30719 $prevFontSizePt = $this->FontSizePt;
30720 $this->SetFont($this->backupSIPFont, '', '', false);
30721 $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat');
30722 $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false);
30723 }
30724 if (!$cw) { return 0; }
30725 $l = 0;
30726 foreach($u AS $char) {
30727 if ($this->_charDefined($cw,$char) || $char > 131071) {
30728 $l++;
30729 }
30730 else { break; }
30731 }
30732 if ($l > 0) {
30733 $patt = mb_substr($writehtml_e, $start, $l);
30734 if (preg_match("/(.*?)(".preg_quote($patt,'/').")(.*)/u", $writehtml_e, $m)) {
30735 $writehtml_e = $m[1];
30736 array_splice($writehtml_a, $writehtml_i+1, 0, array('span style="font-family: '.$font.'"', $m[2], '/span', $m[3]));
30737 $this->subPos = $writehtml_i+3;
30738 return 4;
30739 }
30740 }
30741 }
30742 return 0;
30743 }
30744
30745
30746 // FIRST TRY CORE FONTS (when appropriate)
30747 if (!$this->PDFA && !$this->PDFX && !$this->biDirectional) { // mPDF 6
30748 $repl = array();
30749 if (!$this->subArrMB) {
30750 include(_MPDF_PATH.'includes/subs_core.php');
30751 $this->subArrMB['a'] = $aarr;
30752 $this->subArrMB['s'] = $sarr;
30753 $this->subArrMB['z'] = $zarr;
30754 }
30755 if (isset($this->subArrMB['a'][$u[0]])) {
30756 $font = 'tta'; $ftype = 'C';
30757 foreach($u AS $char) {
30758 if (isset($this->subArrMB['a'][$char])) { $repl[] = $this->subArrMB['a'][$char]; }
30759 else { break; }
30760 }
30761 }
30762 else if (isset($this->subArrMB['z'][$u[0]])) {
30763 $font = 'ttz'; $ftype = 'C';
30764 foreach($u AS $char) {
30765 if (isset($this->subArrMB['z'][$char])) { $repl[] = $this->subArrMB['z'][$char]; }
30766 else { break; }
30767 }
30768 }
30769 else if (isset($this->subArrMB['s'][$u[0]])) {
30770 $font = 'tts'; $ftype = 'C';
30771 foreach($u AS $char) {
30772 if (isset($this->subArrMB['s'][$char])) { $repl[] = $this->subArrMB['s'][$char]; }
30773 else { break; }
30774 }
30775 }
30776 if ($ftype=='C') {
30777 $patt = mb_substr($writehtml_e, $start, count($repl));
30778 if (preg_match("/(.*?)(".preg_quote($patt,'/').")(.*)/u", $writehtml_e, $m)) {
30779 $writehtml_e = $m[1];
30780 array_splice($writehtml_a, $writehtml_i+1, 0, array($font, implode('|', $repl), '/'.$font, $m[3])); // e.g. <tts>
30781 $this->subPos = $writehtml_i+3;
30782 return 4;
30783 }
30784 return 0;
30785 }
30786 }
30787
30788 // LASTLY TRY IN BACKUP SUBS FONT
30789 if (!is_array($this->backupSubsFont)) { $this->backupSubsFont = array("$this->backupSubsFont"); }
30790 foreach($this->backupSubsFont AS $bsfctr=>$bsf) {
30791 if ($this->currentfontfamily != $bsf) { $font = $bsf; }
30792 else { continue; }
30793 unset($cw);
30794 $cw = '';
30795 if (isset($this->fonts[$font])) { $cw = &$this->fonts[$font]['cw']; }
30796 else if (file_exists(_MPDF_TTFONTDATAPATH.$font.'.cw.dat')) { $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat'); }
30797 else {
30798 $prevFontFamily = $this->FontFamily;
30799 $prevFontStyle = $this->currentfontstyle;
30800 $prevFontSizePt = $this->FontSizePt;
30801 $this->SetFont($bsf, '', '', false);
30802 $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat');
30803 $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false);
30804 }
30805 if (!$cw) { continue; }
30806 $l = 0;
30807 foreach($u AS $char) {
30808 if ($char == 173 || $this->_charDefined($cw,$char) || ($char>1536 && $char<1791) || ($char>2304 && $char<3455 )) { // Arabic and Indic
30809 $l++;
30810 }
30811 else {
30812 if ($l==0 && $bsfctr == (count($this->backupSubsFont)-1)) { // Not found even in last backup font
30813 $cont = mb_substr($writehtml_e, $start+1);
30814 $writehtml_e = mb_substr($writehtml_e, 0, $start+1);
30815 array_splice($writehtml_a, $writehtml_i+1, 0, array('', $cont));
30816 $this->subPos = $writehtml_i+1;
30817 return 2;
30818 }
30819 else { break; }
30820 }
30821 }
30822 if ($l > 0) {
30823 $patt = mb_substr($writehtml_e, $start, $l);
30824 if (preg_match("/(.*?)(".preg_quote($patt,'/').")(.*)/u", $writehtml_e, $m)) {
30825 $writehtml_e = $m[1];
30826 array_splice($writehtml_a, $writehtml_i+1, 0, array('span style="font-family: '.$font.'"', $m[2], '/span', $m[3]));
30827 $this->subPos = $writehtml_i+3;
30828 return 4;
30829 }
30830 }
30831 }
30832
30833 unset($cw);
30834 return 0;
30835 }
30836
30837
30838 function setHiEntitySubstitutions() {
30839 $entarr = array (
30840 'nbsp' => '160', 'iexcl' => '161', 'cent' => '162', 'pound' => '163', 'curren' => '164', 'yen' => '165', 'brvbar' => '166', 'sect' => '167',
30841 'uml' => '168', 'copy' => '169', 'ordf' => '170', 'laquo' => '171', 'not' => '172', 'shy' => '173', 'reg' => '174', 'macr' => '175',
30842 'deg' => '176', 'plusmn' => '177', 'sup2' => '178', 'sup3' => '179', 'acute' => '180', 'micro' => '181', 'para' => '182', 'middot' => '183',
30843 'cedil' => '184', 'sup1' => '185', 'ordm' => '186', 'raquo' => '187', 'frac14' => '188', 'frac12' => '189', 'frac34' => '190',
30844 'iquest' => '191', 'Agrave' => '192', 'Aacute' => '193', 'Acirc' => '194', 'Atilde' => '195', 'Auml' => '196', 'Aring' => '197',
30845 'AElig' => '198', 'Ccedil' => '199', 'Egrave' => '200', 'Eacute' => '201', 'Ecirc' => '202', 'Euml' => '203', 'Igrave' => '204',
30846 'Iacute' => '205', 'Icirc' => '206', 'Iuml' => '207', 'ETH' => '208', 'Ntilde' => '209', 'Ograve' => '210', 'Oacute' => '211',
30847 'Ocirc' => '212', 'Otilde' => '213', 'Ouml' => '214', 'times' => '215', 'Oslash' => '216', 'Ugrave' => '217', 'Uacute' => '218',
30848 'Ucirc' => '219', 'Uuml' => '220', 'Yacute' => '221', 'THORN' => '222', 'szlig' => '223', 'agrave' => '224', 'aacute' => '225',
30849 'acirc' => '226', 'atilde' => '227', 'auml' => '228', 'aring' => '229', 'aelig' => '230', 'ccedil' => '231', 'egrave' => '232',
30850 'eacute' => '233', 'ecirc' => '234', 'euml' => '235', 'igrave' => '236', 'iacute' => '237', 'icirc' => '238', 'iuml' => '239',
30851 'eth' => '240', 'ntilde' => '241', 'ograve' => '242', 'oacute' => '243', 'ocirc' => '244', 'otilde' => '245', 'ouml' => '246',
30852 'divide' => '247', 'oslash' => '248', 'ugrave' => '249', 'uacute' => '250', 'ucirc' => '251', 'uuml' => '252', 'yacute' => '253',
30853 'thorn' => '254', 'yuml' => '255', 'OElig' => '338', 'oelig' => '339', 'Scaron' => '352', 'scaron' => '353', 'Yuml' => '376',
30854 'fnof' => '402', 'circ' => '710', 'tilde' => '732', 'Alpha' => '913', 'Beta' => '914', 'Gamma' => '915', 'Delta' => '916',
30855 'Epsilon' => '917', 'Zeta' => '918', 'Eta' => '919', 'Theta' => '920', 'Iota' => '921', 'Kappa' => '922', 'Lambda' => '923',
30856 'Mu' => '924', 'Nu' => '925', 'Xi' => '926', 'Omicron' => '927', 'Pi' => '928', 'Rho' => '929', 'Sigma' => '931', 'Tau' => '932',
30857 'Upsilon' => '933', 'Phi' => '934', 'Chi' => '935', 'Psi' => '936', 'Omega' => '937', 'alpha' => '945', 'beta' => '946', 'gamma' => '947',
30858 'delta' => '948', 'epsilon' => '949', 'zeta' => '950', 'eta' => '951', 'theta' => '952', 'iota' => '953', 'kappa' => '954',
30859 'lambda' => '955', 'mu' => '956', 'nu' => '957', 'xi' => '958', 'omicron' => '959', 'pi' => '960', 'rho' => '961', 'sigmaf' => '962',
30860 'sigma' => '963', 'tau' => '964', 'upsilon' => '965', 'phi' => '966', 'chi' => '967', 'psi' => '968', 'omega' => '969',
30861 'thetasym' => '977', 'upsih' => '978', 'piv' => '982', 'ensp' => '8194', 'emsp' => '8195', 'thinsp' => '8201', 'zwnj' => '8204',
30862 'zwj' => '8205', 'lrm' => '8206', 'rlm' => '8207', 'ndash' => '8211', 'mdash' => '8212', 'lsquo' => '8216', 'rsquo' => '8217',
30863 'sbquo' => '8218', 'ldquo' => '8220', 'rdquo' => '8221', 'bdquo' => '8222', 'dagger' => '8224', 'Dagger' => '8225', 'bull' => '8226',
30864 'hellip' => '8230', 'permil' => '8240', 'prime' => '8242', 'Prime' => '8243', 'lsaquo' => '8249', 'rsaquo' => '8250', 'oline' => '8254',
30865 'frasl' => '8260', 'euro' => '8364', 'image' => '8465', 'weierp' => '8472', 'real' => '8476', 'trade' => '8482', 'alefsym' => '8501',
30866 'larr' => '8592', 'uarr' => '8593', 'rarr' => '8594', 'darr' => '8595', 'harr' => '8596', 'crarr' => '8629', 'lArr' => '8656',
30867 'uArr' => '8657', 'rArr' => '8658', 'dArr' => '8659', 'hArr' => '8660', 'forall' => '8704', 'part' => '8706', 'exist' => '8707',
30868 'empty' => '8709', 'nabla' => '8711', 'isin' => '8712', 'notin' => '8713', 'ni' => '8715', 'prod' => '8719', 'sum' => '8721',
30869 'minus' => '8722', 'lowast' => '8727', 'radic' => '8730', 'prop' => '8733', 'infin' => '8734', 'ang' => '8736', 'and' => '8743',
30870 'or' => '8744', 'cap' => '8745', 'cup' => '8746', 'int' => '8747', 'there4' => '8756', 'sim' => '8764', 'cong' => '8773',
30871 'asymp' => '8776', 'ne' => '8800', 'equiv' => '8801', 'le' => '8804', 'ge' => '8805', 'sub' => '8834', 'sup' => '8835', 'nsub' => '8836',
30872 'sube' => '8838', 'supe' => '8839', 'oplus' => '8853', 'otimes' => '8855', 'perp' => '8869', 'sdot' => '8901', 'lceil' => '8968',
30873 'rceil' => '8969', 'lfloor' => '8970', 'rfloor' => '8971', 'lang' => '9001', 'rang' => '9002', 'loz' => '9674', 'spades' => '9824',
30874 'clubs' => '9827', 'hearts' => '9829', 'diams' => '9830',
30875 );
30876 foreach($entarr AS $key => $val) {
30877 $this->entsearch[] = '&'.$key.';';
30878 $this->entsubstitute[] = code2utf($val);
30879 }
30880 }
30881
30882 function SubstituteHiEntities($html) {
30883 // converts html_entities > ASCII 127 to unicode
30884 // Leaves in particular &lt; to distinguish from tag marker
30885 if (count($this->entsearch)) {
30886 $html = str_replace($this->entsearch,$this->entsubstitute,$html);
30887 }
30888 return $html;
30889 }
30890
30891
30892 // Edited v1.2 Pass by reference; option to continue if invalid UTF-8 chars
30893 function is_utf8(&$string) {
30894 if ($string === mb_convert_encoding(mb_convert_encoding($string, "UTF-32", "UTF-8"), "UTF-8", "UTF-32")) {
30895 return true;
30896 }
30897 else {
30898 if ($this->ignore_invalid_utf8) {
30899 $string = mb_convert_encoding(mb_convert_encoding($string, "UTF-32", "UTF-8"), "UTF-8", "UTF-32") ;
30900 return true;
30901 }
30902 else {
30903 return false;
30904 }
30905 }
30906 }
30907
30908
30909 function purify_utf8($html,$lo=true) {
30910 // For HTML
30911 // Checks string is valid UTF-8 encoded
30912 // converts html_entities > ASCII 127 to UTF-8
30913 // Only exception - leaves low ASCII entities e.g. &lt; &amp; etc.
30914 // Leaves in particular &lt; to distinguish from tag marker
30915 if (!$this->is_utf8($html)) {
30916 echo "<p><b>HTML contains invalid UTF-8 character(s)</b></p>";
30917 while (mb_convert_encoding(mb_convert_encoding($html, "UTF-32", "UTF-8"), "UTF-8", "UTF-32") != $html) {
30918 $a = iconv('UTF-8', 'UTF-8', $html);
30919 echo ($a);
30920 $pos = $start = strlen($a);
30921 $err = '';
30922 while ( ord(substr($html,$pos,1)) > 128 ) {
30923 $err .= '[[#'.ord(substr($html,$pos,1)).']]';
30924 $pos++;
30925 }
30926 echo '<span style="color:red; font-weight:bold">'.$err.'</span>';
30927 $html = substr($html, $pos);
30928 }
30929 echo $html;
30930 $this->Error("");
30931 }
30932 $html = preg_replace("/\r/", "", $html );
30933
30934 // converts html_entities > ASCII 127 to UTF-8
30935 // Leaves in particular &lt; to distinguish from tag marker
30936 $html = $this->SubstituteHiEntities($html);
30937
30938 // converts all &#nnn; or &#xHHH; to UTF-8 multibyte
30939 // If $lo==true then includes ASCII < 128
30940 $html = strcode2utf($html,$lo);
30941 return ($html);
30942 }
30943
30944 function purify_utf8_text($txt) {
30945 // For TEXT
30946 // Make sure UTF-8 string of characters
30947 if (!$this->is_utf8($txt)) { $this->Error("Text contains invalid UTF-8 character(s)"); }
30948
30949 $txt = preg_replace("/\r/", "", $txt );
30950
30951 return ($txt);
30952 }
30953 function all_entities_to_utf8($txt) {
30954 // converts txt_entities > ASCII 127 to UTF-8
30955 // Leaves in particular &lt; to distinguish from tag marker
30956 $txt = $this->SubstituteHiEntities($txt);
30957
30958 // converts all &#nnn; or &#xHHH; to UTF-8 multibyte
30959 $txt = strcode2utf($txt);
30960
30961 $txt = $this->lesser_entity_decode($txt);
30962 return ($txt);
30963 }
30964
30965
30966 // ====================================================
30967 /*-- BARCODES --*/
30968 // UPC/EAN barcode
30969 // EAN13, EAN8, UPCA, UPCE, ISBN, ISSN
30970 // Accepts 12 or 13 digits with or without - hyphens
30971 function WriteBarcode($code, $showtext=1, $x='', $y='', $size=1, $border=0, $paddingL=1, $paddingR=1, $paddingT=2, $paddingB=2, $height=1, $bgcol=false, $col=false, $btype='ISBN', $supplement='0', $supplement_code='', $k=1) {
30972 if (empty($code)) {
30973 return;
30974 }
30975 $codestr = $code;
30976 $code = preg_replace('/\-/','',$code);
30977
30978 if (!class_exists('PDFBarcode', false)) {
30979 include(_MPDF_PATH.'classes/barcode.php');
30980 }
30981 $this->barcode = new PDFBarcode();
30982 if ($btype == 'ISSN' || $btype == 'ISBN') {
30983 $arrcode = $this->barcode->getBarcodeArray($code, 'EAN13');
30984 }
30985 else { $arrcode = $this->barcode->getBarcodeArray($code, $btype); }
30986
30987 if ($arrcode === false) { $this->Error('Error in barcode string: '.$codestr); }
30988 if((($btype=='EAN13' || $btype=='ISBN' || $btype=='ISSN') && strlen($code) == 12) || ($btype=='UPCA' && strlen($code) == 11)
30989 || ($btype=='UPCE' && strlen($code) == 11) || ($btype=='EAN8' && strlen($code) == 7)) {
30990 $code .= $arrcode['checkdigit'];
30991 if (stristr($codestr,'-')) { $codestr .= '-' . $arrcode['checkdigit']; }
30992 else { $codestr .= $arrcode['checkdigit']; }
30993 }
30994 if ($btype == 'ISBN') { $codestr = 'ISBN '.$codestr; }
30995 if ($btype == 'ISSN') { $codestr = 'ISSN '.$codestr; }
30996
30997 if (empty($x)) {
30998 $x = $this->x;
30999 }
31000 if (empty($y)) {
31001 $y = $this->y;
31002 }
31003 // set foreground color
31004 $prevDrawColor = $this->DrawColor;
31005 $prevTextColor = $this->TextColor;
31006 $prevFillColor = $this->FillColor;
31007 $lw = $this->LineWidth;
31008 $this->SetLineWidth(0.01);
31009
31010 $size /= $k; // in case resized in a table
31011
31012 $xres = $arrcode['nom-X'] * $size;
31013 $llm = $arrcode['lightmL'] * $arrcode['nom-X'] * $size; // Left Light margin
31014 $rlm = $arrcode['lightmR'] * $arrcode['nom-X'] * $size; // Right Light margin
31015
31016 $bcw = ($arrcode["maxw"] * $xres); // Barcode width = Should always be 31.35mm * $size
31017
31018 $fbw = $bcw + $llm + $rlm; // Full barcode width incl. light margins
31019 $ow = $fbw + $paddingL + $paddingR; // Full overall width incl. user-defined padding
31020
31021 $fbwi = $fbw - 2; // Full barcode width incl. light margins - 2mm - for isbn string
31022
31023 // cf. http://www.gs1uk.org/downloads/bar_code/Bar coding getting it right.pdf
31024 $num_height = 3 * $size; // Height of numerals
31025 $fbh = $arrcode['nom-H'] * $size * $height; // Full barcode height incl. numerals
31026 $bch = $fbh - (1.5 * $size); // Barcode height of bars (3mm for numerals)
31027
31028 if (($btype=='EAN13' && $showtext) || $btype == 'ISSN' || $btype == 'ISBN') { // Add height for ISBN string + margin from top of bars
31029 $tisbnm = 1.5 * $size; // Top margin between isbn (if shown) & bars
31030 $codestr_fontsize = 2.1 * $size;
31031 $paddingT += $codestr_fontsize + $tisbnm ;
31032 }
31033 $oh = $fbh + $paddingT + $paddingB; // Full overall height incl. user-defined padding
31034
31035 // PRINT border background color
31036 $xpos = $x;
31037 $ypos = $y;
31038 if ($col) {
31039 $this->SetDColor($col);
31040 $this->SetTColor($col);
31041 }
31042 else {
31043 $this->SetDColor($this->ConvertColor(0));
31044 $this->SetTColor($this->ConvertColor(0));
31045 }
31046 if ($bgcol) {
31047 $this->SetFColor($bgcol);
31048 }
31049 else { $this->SetFColor($this->ConvertColor(255)); }
31050 if (!$bgcol && !$col) { // fn. called directly - not via HTML
31051 if ($border) { $fillb = 'DF'; } else { $fillb = 'F'; }
31052 $this->Rect($xpos, $ypos, $ow, $oh, $fillb);
31053 }
31054
31055
31056 // PRINT BARS
31057 $xpos = $x + $paddingL + $llm ;
31058 $ypos = $y + $paddingT;
31059 if ($col) { $this->SetFColor($col); }
31060 else { $this->SetFColor($this->ConvertColor(0)); }
31061 if ($arrcode !== false) {
31062 foreach ($arrcode["bcode"] AS $v) {
31063 $bw = ($v["w"] * $xres);
31064 if ($v["t"]) {
31065 // draw a vertical bar
31066 $this->Rect($xpos, $ypos, $bw, $bch, 'F');
31067 }
31068 $xpos += $bw;
31069 }
31070 }
31071
31072
31073 // print text
31074 $prevFontFamily = $this->FontFamily;
31075 $prevFontStyle = $this->FontStyle;
31076 $prevFontSizePt = $this->FontSizePt;
31077
31078 // ISBN string
31079 if (($btype=='EAN13' && $showtext) || $btype=='ISBN' || $btype=='ISSN') {
31080 if ($this->onlyCoreFonts) {
31081 $this->SetFont('chelvetica');
31082 }
31083 else {
31084 $this->SetFont('sans');
31085 }
31086
31087 if ($bgcol) { $this->SetFColor($bgcol); }
31088 else { $this->SetFColor($this->ConvertColor(255)); }
31089 $this->x = $x + $paddingL + 1; // 1mm left margin (cf. $fbwi above)
31090 // max width is $fbwi
31091 $loop = 0;
31092 while ( $loop == 0 ) {
31093 $this->SetFontSize($codestr_fontsize*1.4*_MPDFK, false); // don't write
31094 $sz = $this->GetStringWidth( $codestr );
31095 if ($sz > $fbwi)
31096 $codestr_fontsize -= 0.1;
31097 else
31098 $loop ++;
31099 }
31100 $this->SetFont('','',$codestr_fontsize*1.4*_MPDFK, true, true); // * 1.4 because font height is only 7/10 of given mm
31101 // WORD SPACING
31102 if ($fbwi > $sz) {
31103 $xtra = $fbwi - $sz;
31104 $charspacing = $xtra / (strlen($codestr)-1);
31105 if ($charspacing) { $this->_out(sprintf('BT %.3F Tc ET',$charspacing*_MPDFK)); }
31106 }
31107 $this->y = $y + $paddingT - ($codestr_fontsize ) - $tisbnm ;
31108 $this->Cell($fbw , $codestr_fontsize, $codestr);
31109 if ($charspacing) { $this->_out('BT 0 Tc ET'); }
31110 }
31111
31112
31113 // Bottom NUMERALS
31114 // mPDF 5.7.4
31115 if ($this->onlyCoreFonts) {
31116 $this->SetFont('ccourier');
31117 $fh = 1.3;
31118 }
31119 else {
31120 $this->SetFont('ocrb');
31121 $fh = 1.06;
31122 }
31123 $charRO = '';
31124 if ($btype=='EAN13' || $btype=='ISBN' || $btype=='ISSN') {
31125 $outerfontsize = 3; // Inner fontsize = 3
31126 $outerp = $xres * 4;
31127 $innerp = $xres * 2.5;
31128 $textw = ($bcw*0.5) - $outerp - $innerp;
31129 $chars = 6; // number of numerals in each half
31130 $charLO = substr($code,0,1); // Left Outer
31131 $charLI = substr($code,1,6); // Left Inner
31132 $charRI = substr($code,7,6); // Right Inner
31133 if (!$supplement) $charRO = '>'; // Right Outer
31134 }
31135 else if ($btype=='UPCA') {
31136 $outerfontsize = 2.3; // Inner fontsize = 3
31137 $outerp = $xres * 10;
31138 $innerp = $xres * 2.5;
31139 $textw = ($bcw*0.5) - $outerp - $innerp;
31140 $chars = 5;
31141 $charLO = substr($code,0,1); // Left Outer
31142 $charLI = substr($code,1,5); // Left Inner
31143 $charRI = substr($code,6,5); // Right Inner
31144 $charRO = substr($code,11,1); // Right Outer
31145 }
31146 else if ($btype=='UPCE') {
31147 $outerfontsize = 2.3; // Inner fontsize = 3
31148 $outerp = $xres * 4;
31149 $innerp = 0;
31150 $textw = ($bcw*0.5) - $outerp - $innerp;
31151 $chars = 3;
31152 $upce_code = $arrcode['code'];
31153 $charLO = substr($code,0,1); // Left Outer
31154 $charLI = substr($upce_code,0,3); // Left Inner
31155 $charRI = substr($upce_code,3,3); // Right Inner
31156 $charRO = substr($code,11,1); // Right Outer
31157 }
31158 else if ($btype=='EAN8') {
31159 $outerfontsize = 3; // Inner fontsize = 3
31160 $outerp = $xres * 4;
31161 $innerp = $xres * 2.5;
31162 $textw = ($bcw*0.5) - $outerp - $innerp;
31163 $chars = 4;
31164 $charLO = '<'; // Left Outer
31165 $charLI = substr($code,0,4); // Left Inner
31166 $charRI = substr($code,4,4); // Right Inner
31167 if (!$supplement) $charRO = '>'; // Right Outer
31168 }
31169
31170 $this->SetFontSize(($outerfontsize/3)*3*$fh*$size*_MPDFK); // 3mm numerals (FontSize is larger to account for space above/below characters)
31171
31172 if (!$this->usingCoreFont) { $cw = $this->_getCharWidth($this->CurrentFont['cw'],32)*3*$fh*$size/1000; } // character width at 3mm
31173 else { $cw = 600*3*$fh*$size/1000; } // mPDF 5.7.4
31174
31175 // Outer left character
31176 $y_text = $y + $paddingT + $bch - ($num_height/2);
31177 $y_text_outer = $y + $paddingT + $bch - ($num_height*($outerfontsize/3)/2);
31178
31179 $this->x = $x + $paddingL - ($cw*($outerfontsize/3)*0.1); // 0.1 is correction as char does not fill full width;
31180 $this->y = $y_text_outer;
31181 $this->Cell($cw, $num_height, $charLO );
31182
31183 // WORD SPACING for inner chars
31184 $xtra = $textw - ($cw*$chars);
31185 $charspacing = $xtra / ($chars-1);
31186 if ($charspacing) { $this->_out(sprintf('BT %.3F Tc ET',$charspacing*_MPDFK)); }
31187
31188 if ($bgcol) { $this->SetFColor($bgcol); }
31189 else { $this->SetFColor($this->ConvertColor(255)); }
31190
31191 $this->SetFontSize(3*$fh*$size*_MPDFK); // 3mm numerals (FontSize is larger to account for space above/below characters)
31192
31193 // Inner left half characters
31194 $this->x = $x + $paddingL + $llm + $outerp;
31195 $this->y = $y_text;
31196 $this->Cell($textw, $num_height, $charLI , 0, 0, '', 1);
31197
31198 // Inner right half characters
31199 $this->x = $x + $paddingL + $llm + ($bcw*0.5) + $innerp;
31200 $this->y = $y_text;
31201 $this->Cell($textw, $num_height, $charRI , 0, 0, '', 1);
31202
31203 if ($charspacing) { $this->_out('BT 0 Tc ET'); }
31204
31205 // Outer Right character
31206 $this->SetFontSize(($outerfontsize/3)*3*$fh*$size*_MPDFK); // 3mm numerals (FontSize is larger to account for space above/below characters)
31207
31208 $this->x = $x + $paddingL + $llm + $bcw + $rlm - ($cw*($outerfontsize/3)*0.9); // 0.9 is correction as char does not fill full width
31209 $this->y = $y_text_outer;
31210 $this->Cell($cw*($outerfontsize/3), $num_height, $charRO , 0, 0, 'R');
31211
31212 if ($supplement) { // EAN-2 or -5 Supplement
31213 // PRINT BARS
31214 $supparrcode = $this->barcode->getBarcodeArray($supplement_code, 'EAN'.$supplement);
31215 if ($supparrcode === false) { $this->Error('Error in barcode string (supplement): '.$codestr.' '.$supplement_code); }
31216 if(strlen($supplement_code) != $supplement) {
31217 $this->Error('Barcode supplement incorrect: '.$supplement_code);
31218 }
31219 $llm = $fbw - (($arrcode['lightmR'] - $supparrcode['sepM']) * $arrcode['nom-X'] * $size); // Left Light margin
31220 $rlm = $arrcode['lightmR'] * $arrcode['nom-X'] * $size; // Right Light margin
31221
31222 $bcw = ($supparrcode["maxw"] * $xres); // Barcode width = Should always be 31.35mm * $size
31223
31224 $fbw = $bcw + $llm + $rlm; // Full barcode width incl. light margins
31225 $ow = $fbw + $paddingL + $paddingR; // Full overall width incl. user-defined padding
31226 $bch = $fbh - (1.5 * $size) - ($num_height + 0.5); // Barcode height of bars (3mm for numerals)
31227
31228 $xpos = $x + $paddingL + $llm ;
31229 $ypos = $y + $paddingT + $num_height + 0.5;
31230 if ($col) { $this->SetFColor($col); }
31231 else { $this->SetFColor($this->ConvertColor(0)); }
31232 if ($supparrcode !== false) {
31233 foreach ($supparrcode["bcode"] AS $v) {
31234 $bw = ($v["w"] * $xres);
31235 if ($v["t"]) {
31236 // draw a vertical bar
31237 $this->Rect($xpos, $ypos, $bw, $bch, 'F');
31238 }
31239 $xpos += $bw;
31240 }
31241 }
31242
31243 // Characters
31244 if ($bgcol) { $this->SetFColor($bgcol); }
31245 else { $this->SetFColor($this->ConvertColor(255)); }
31246 $this->SetFontSize(3*$fh*$size*_MPDFK); // 3mm numerals (FontSize is larger to account for space above/below characters)
31247 $this->x = $x + $paddingL + $llm;
31248 $this->y = $y + $paddingT;
31249 $this->Cell($bcw, $num_height, $supplement_code, 0, 0, 'C');
31250
31251 // Outer Right character (light margin)
31252 $this->SetFontSize(($outerfontsize/3)*3*$fh*$size*_MPDFK); // 3mm numerals (FontSize is larger to account for space above/below characters)
31253 $this->x = $x + $paddingL + $llm + $bcw + $rlm - ($cw*0.9); // 0.9 is correction as char does not fill full width
31254 $this->y = $y + $paddingT;
31255 $this->Cell($cw*($outerfontsize/3), $num_height, '>', 0, 0, 'R');
31256 }
31257
31258
31259
31260 // Restore **************
31261 $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt);
31262 $this->DrawColor = $prevDrawColor;
31263 $this->TextColor = $prevTextColor;
31264 $this->FillColor = $prevFillColor;
31265 $this->SetLineWidth($lw);
31266 $this->SetY($y);
31267 }
31268
31269
31270
31271 // ====================================================
31272 // POSTAL and OTHER barcodes
31273 function WriteBarcode2($code, $x='', $y='', $size=1, $height=1, $bgcol=false, $col=false, $btype='IMB', $print_ratio='', $k=1) {
31274 if (empty($code)) { return; }
31275 if (!class_exists('PDFBarcode', false)) {
31276 include(_MPDF_PATH.'classes/barcode.php');
31277 }
31278 $this->barcode = new PDFBarcode();
31279 $arrcode = $this->barcode->getBarcodeArray($code, $btype, $print_ratio);
31280
31281 if ($arrcode === false) { $this->Error('Error in barcode string: '.$code); }
31282 if (empty($x)) { $x = $this->x; }
31283 if (empty($y)) { $y = $this->y; }
31284 $prevDrawColor = $this->DrawColor;
31285 $prevTextColor = $this->TextColor;
31286 $prevFillColor = $this->FillColor;
31287 $lw = $this->LineWidth;
31288 $this->SetLineWidth(0.01);
31289 $size /= $k; // in case resized in a table
31290 $xres = $arrcode['nom-X'] * $size;
31291
31292 if ($btype == 'IMB' || $btype == 'RM4SCC' || $btype == 'KIX' || $btype == 'POSTNET' || $btype == 'PLANET') {
31293 $llm = $arrcode['quietL'] / $k; // Left Quiet margin
31294 $rlm = $arrcode['quietR'] / $k; // Right Quiet margin
31295 $tlm = $blm = $arrcode['quietTB'] / $k;
31296 $height=1; // Overrides
31297 }
31298 else if (in_array($btype, array('C128A','C128B','C128C','EAN128A','EAN128B','EAN128C','C39','C39+','C39E','C39E+','S25','S25+','I25','I25+','I25B','I25B+','C93','MSI','MSI+','CODABAR','CODE11'))) {
31299 $llm = $arrcode['lightmL'] * $xres; // Left Quiet margin
31300 $rlm = $arrcode['lightmR'] * $xres; // Right Quiet margin
31301 $tlm = $blm = $arrcode['lightTB'] * $xres * $height;
31302 }
31303
31304
31305 $bcw = ($arrcode["maxw"] * $xres);
31306 $fbw = $bcw + $llm + $rlm; // Full barcode width incl. light margins
31307
31308 $bch = ($arrcode["nom-H"] * $size * $height);
31309 $fbh = $bch + $tlm + $blm; // Full barcode height
31310
31311 // PRINT border background color
31312 $xpos = $x;
31313 $ypos = $y;
31314 if ($col) {
31315 $this->SetDColor($col);
31316 $this->SetTColor($col);
31317 }
31318 else {
31319 $this->SetDColor($this->ConvertColor(0));
31320 $this->SetTColor($this->ConvertColor(0));
31321 }
31322 if ($bgcol) {
31323 $this->SetFColor($bgcol);
31324 }
31325 else { $this->SetFColor($this->ConvertColor(255)); }
31326
31327 // PRINT BARS
31328 if ($col) { $this->SetFColor($col); }
31329 else { $this->SetFColor($this->ConvertColor(0)); }
31330 $xpos = $x + $llm ;
31331
31332 if ($arrcode !== false) {
31333 foreach ($arrcode["bcode"] AS $v) {
31334 $bw = ($v["w"] * $xres);
31335 if ($v["t"]) {
31336 $ypos = $y + $tlm + ($bch * $v['p'] / $arrcode['maxh']);
31337 $this->Rect($xpos, $ypos, $bw, ($v['h'] * $bch / $arrcode['maxh']), 'F');
31338 }
31339 $xpos += $bw;
31340 }
31341 }
31342
31343 // PRINT BEARER BARS
31344 if ($btype == 'I25B' || $btype == 'I25B+') {
31345 $this->Rect($x, $y, $fbw, ($arrcode['lightTB'] * $xres * $height), 'F');
31346 $this->Rect($x, $y+$tlm+$bch, $fbw, ($arrcode['lightTB'] * $xres * $height), 'F');
31347 }
31348
31349 // Restore **************
31350 $this->DrawColor = $prevDrawColor;
31351 $this->TextColor = $prevTextColor;
31352 $this->FillColor = $prevFillColor;
31353 $this->SetLineWidth($lw);
31354 $this->SetY($y);
31355 }
31356
31357 /*-- END BARCODES --*/
31358
31359 // ====================================================
31360 // ====================================================
31361
31362 function StartTransform($returnstring=false) {
31363 if ($returnstring) { return('q'); }
31364 else { $this->_out('q'); }
31365 }
31366 function StopTransform($returnstring=false) {
31367 if ($returnstring) { return('Q'); }
31368 else { $this->_out('Q'); }
31369 }
31370 function transformScale($s_x, $s_y, $x='', $y='', $returnstring=false) {
31371 if ($x === '') {
31372 $x=$this->x;
31373 }
31374 if ($y === '') {
31375 $y=$this->y;
31376 }
31377 if (($s_x == 0) OR ($s_y == 0)) {
31378 $this->Error('Please do not use values equal to zero for scaling');
31379 }
31380 $y = ($this->h - $y) * _MPDFK;
31381 $x *= _MPDFK;
31382 //calculate elements of transformation matrix
31383 $s_x /= 100;
31384 $s_y /= 100;
31385 $tm = array();
31386 $tm[0] = $s_x;
31387 $tm[1] = 0;
31388 $tm[2] = 0;
31389 $tm[3] = $s_y;
31390 $tm[4] = $x * (1 - $s_x);
31391 $tm[5] = $y * (1 - $s_y);
31392 //scale the coordinate system
31393 if ($returnstring) { return($this->_transform($tm, true)); }
31394 else { $this->_transform($tm); }
31395 }
31396 function transformTranslate($t_x, $t_y, $returnstring=false) {
31397 //calculate elements of transformation matrix
31398 $tm = array();
31399 $tm[0] = 1;
31400 $tm[1] = 0;
31401 $tm[2] = 0;
31402 $tm[3] = 1;
31403 $tm[4] = $t_x * _MPDFK;
31404 $tm[5] = -$t_y * _MPDFK;
31405 //translate the coordinate system
31406 if ($returnstring) { return($this->_transform($tm, true)); }
31407 else { $this->_transform($tm); }
31408 }
31409 function transformRotate($angle, $x='', $y='', $returnstring=false) {
31410 if ($x === '') {
31411 $x=$this->x;
31412 }
31413 if ($y === '') {
31414 $y=$this->y;
31415 }
31416 $angle = -$angle;
31417 $y = ($this->h - $y) * _MPDFK;
31418 $x *= _MPDFK;
31419 //calculate elements of transformation matrix
31420 $tm = array();
31421 $tm[0] = cos(deg2rad($angle));
31422 $tm[1] = sin(deg2rad($angle));
31423 $tm[2] = -$tm[1];
31424 $tm[3] = $tm[0];
31425 $tm[4] = $x + $tm[1] * $y - $tm[0] * $x;
31426 $tm[5] = $y - $tm[0] * $y - $tm[1] * $x;
31427 //rotate the coordinate system around ($x,$y)
31428 if ($returnstring) { return($this->_transform($tm, true)); }
31429 else { $this->_transform($tm); }
31430 }
31431 // mPDF 5.7.3 TRANSFORMS
31432 function transformSkew($angle_x, $angle_y, $x='', $y='', $returnstring=false) {
31433 if ($x === '') {
31434 $x = $this->x;
31435 }
31436 if ($y === '') {
31437 $y = $this->y;
31438 }
31439 $angle_x = -$angle_x;
31440 $angle_y = -$angle_y;
31441 $x *= _MPDFK;
31442 $y = ($this->h - $y) * _MPDFK;
31443 //calculate elements of transformation matrix
31444 $tm = array();
31445 $tm[0] = 1;
31446 $tm[1] = tan(deg2rad($angle_y));
31447 $tm[2] = tan(deg2rad($angle_x));
31448 $tm[3] = 1;
31449 $tm[4] = -$tm[2] * $y;
31450 $tm[5] = -$tm[1] * $x;
31451 //skew the coordinate system
31452 if ($returnstring) { return($this->_transform($tm, true)); }
31453 else { $this->_transform($tm); }
31454 }
31455
31456 function _transform($tm, $returnstring=false) {
31457 if ($returnstring) { return(sprintf('%.4F %.4F %.4F %.4F %.4F %.4F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5])); }
31458 else { $this->_out(sprintf('%.4F %.4F %.4F %.4F %.4F %.4F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5])); }
31459 }
31460
31461
31462
31463
31464 // AUTOFONT =========================
31465 function markScriptToLang($html) {
31466 if ($this->onlyCoreFonts) { return $html; }
31467
31468 // sets $this->script2lang
31469 if (empty($this->script2lang)) {
31470 include(_MPDF_PATH.'config_script2lang.php');
31471 }
31472
31473 $n = '';
31474 $a=preg_split('/<(.*?)>/ms',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
31475 foreach($a as $i => $e) {
31476 if($i%2==0) {
31477 //ignore if in Textarea
31478 if ($i > 0 && strtolower(substr($a[$i-1],1,8)) == 'textarea') { $a[$i] = $e; continue; }
31479 $e = strcode2utf($e);
31480 $e = $this->lesser_entity_decode($e);
31481
31482 $earr = $this->UTF8StringToArray($e, false);
31483
31484 $scriptblock = 0;
31485 $scriptblocks = array();
31486 $scriptblocks[0] = 0;
31487 $chardata = array();
31488 $subchunk = 0;
31489 $charctr = 0;
31490 foreach($earr as $char) {
31491 $ucd_record = UCDN::get_ucd_record($char);
31492 $sbl = $ucd_record[6];
31493
31494 if ($sbl && $sbl != 40 && $sbl != 102) {
31495 if ($scriptblock == 0) { $scriptblock = $sbl; $scriptblocks[$subchunk] = $scriptblock; }
31496 else if ($scriptblock > 0 && $scriptblock != $sbl) {
31497 // NEW (non-common) Script encountered in this chunk.
31498 // Start a new subchunk
31499 $subchunk++;
31500 $scriptblock = $sbl;
31501 $charctr = 0;
31502 $scriptblocks[$subchunk] = $scriptblock;
31503 }
31504 }
31505
31506 $chardata[$subchunk][$charctr]['script'] = $sbl;
31507 $chardata[$subchunk][$charctr]['uni'] = $char;
31508 $charctr++;
31509 }
31510
31511 // If scriptblock[x] = common & non-baseScript
31512 // and scriptblock[x+1] = baseScript
31513 // Move common script from end of x to start of x+1
31514 for($sch=0;$sch<$subchunk;$sch++) {
31515 if ($scriptblocks[$sch] > 0 && $scriptblocks[$sch] != $this->baseScript && $scriptblocks[$sch+1] == $this->baseScript) {
31516 $end = count($chardata[$sch])-1;
31517 while($chardata[$sch][$end]['script'] == 0 && $end > 1) { // common script
31518 $tmp = array_pop($chardata[$sch]);
31519 array_unshift($chardata[$sch+1],$tmp);
31520 $end--;
31521 }
31522 }
31523 }
31524
31525 $o = '';
31526 for($sch=0;$sch<=$subchunk;$sch++) {
31527 if (isset($chardata[$sch])) {
31528 $s = '';
31529 for ($j=0;$j<count($chardata[$sch]);$j++) {
31530 $s.=code2utf($chardata[$sch][$j]['uni']);
31531 }
31532 // ZZZ99 Undo lesser_entity_decode as above - but only for <>&
31533 $s = str_replace("&","&amp;",$s);
31534 $s = str_replace("<","&lt;",$s);
31535 $s = str_replace(">","&gt;",$s);
31536
31537 // Check Vietnamese if Latin script - even if Basescript
31538 if ($scriptblocks[$sch] == UCDN::SCRIPT_LATIN && $this->autoVietnamese && preg_match("/([".$this->viet."])/u", $s)) {
31539 $o .= '<span lang="vi" class="lang_vi">'.$s.'</span>';
31540 }
31541 // Check Arabic for different languages if Arabic script - even if Basescript
31542 else if ($scriptblocks[$sch] == UCDN::SCRIPT_ARABIC && $this->autoArabic) {
31543 if (preg_match("/[".$this->sindhi ."]/u", $s) ) {
31544 $o .= '<span lang="sd" class="lang_sd">'.$s.'</span>';
31545 }
31546 else if (preg_match("/[".$this->urdu ."]/u", $s) ) {
31547 $o .= '<span lang="ur" class="lang_ur">'.$s.'</span>';
31548 }
31549 else if (preg_match("/[".$this->pashto ."]/u", $s) ) {
31550 $o .= '<span lang="ps" class="lang_ps">'.$s.'</span>';
31551 }
31552 else if (preg_match("/[".$this->persian ."]/u", $s) ) {
31553 $o .= '<span lang="fa" class="lang_fa">'.$s.'</span>';
31554 }
31555 else if ($this->baseScript != UCDN::SCRIPT_ARABIC && isset($this->script2lang[$scriptblocks[$sch]])) {
31556 $o .= '<span lang="'.$this->script2lang[$scriptblocks[$sch]].'" class="lang_'.$this->script2lang[$scriptblocks[$sch]].'">'.$s.'</span>';
31557 }
31558 else {
31559 // Just output chars
31560 $o .= $s;
31561 }
31562 }
31563 // Identify Script block if not Basescript, and mark up as language
31564 else if ($scriptblocks[$sch] > 0 && $scriptblocks[$sch] != $this->baseScript && isset($this->script2lang[$scriptblocks[$sch]])) {
31565 // Encase in <span>
31566 $o .= '<span lang="'.$this->script2lang[$scriptblocks[$sch]].'" class="lang_'.$this->script2lang[$scriptblocks[$sch]].'">';
31567 $o .= $s;
31568 $o .= '</span>';
31569 }
31570 else {
31571 // Just output chars
31572 $o .= $s;
31573 }
31574 }
31575 }
31576
31577 $a[$i] = $o;
31578 }
31579 else {
31580 $a[$i] = '<'.$e.'>';
31581 }
31582 }
31583 $n = implode('',$a);
31584
31585 return $n;
31586 }
31587
31588
31589
31590 //===========================
31591 // Functions
31592
31593 // Call-back function Used for usort in fn _tableWrite
31594
31595 function _cmpdom($a, $b) {
31596 return ($a["dom"] < $b["dom"]) ? -1 : 1;
31597 }
31598 function mb_strrev($str, $enc = 'utf-8'){
31599 $ch = array();
31600 $ch = preg_split('//u',$str);
31601 $revch = array_reverse($ch);
31602 return implode('',$revch);
31603 }
31604
31605 /*-- COLUMNS --*/
31606 // Callback function from function printcolumnbuffer in mpdf
31607 function columnAdjustAdd($type,$k,$xadj,$yadj,$a,$b,$c=0,$d=0,$e=0,$f=0) {
31608 if ($type == 'Td') { // xpos,ypos
31609 $a += ($xadj * $k);
31610 $b -= ($yadj * $k);
31611 return 'BT '.sprintf('%.3F %.3F',$a,$b).' Td';
31612 }
31613 else if ($type == 're') { // xpos,ypos,width,height
31614 $a += ($xadj * $k);
31615 $b -= ($yadj * $k);
31616 return sprintf('%.3F %.3F %.3F %.3F',$a,$b,$c,$d).' re';
31617 }
31618 else if ($type == 'l') { // xpos,ypos,x2pos,y2pos
31619 $a += ($xadj * $k);
31620 $b -= ($yadj * $k);
31621 return sprintf('%.3F %.3F l',$a,$b);
31622 }
31623 else if ($type == 'img') { // width,height,xpos,ypos
31624 $c += ($xadj * $k);
31625 $d -= ($yadj * $k);
31626 return sprintf('q %.3F 0 0 %.3F %.3F %.3F',$a,$b,$c,$d).' cm /'.$e;
31627 }
31628 else if ($type == 'draw') { // xpos,ypos
31629 $a += ($xadj * $k);
31630 $b -= ($yadj * $k);
31631 return sprintf('%.3F %.3F m',$a,$b);
31632 }
31633 else if ($type == 'bezier') { // xpos,ypos,x2pos,y2pos,x3pos,y3pos
31634 $a += ($xadj * $k);
31635 $b -= ($yadj * $k);
31636 $c += ($xadj * $k);
31637 $d -= ($yadj * $k);
31638 $e += ($xadj * $k);
31639 $f -= ($yadj * $k);
31640 return sprintf('%.3F %.3F %.3F %.3F %.3F %.3F',$a,$b,$c,$d,$e,$f).' c';
31641 }
31642 }
31643 /*-- END COLUMNS --*/
31644
31645
31646
31647 function ConvertColor($color="#000000"){
31648 $color = trim(strtolower($color));
31649 $c = false;
31650 $cstr = '';
31651 if ($color=='transparent') { return false; }
31652 else if ($color=='inherit') { return false; }
31653 else if (isset($this->SVGcolors[$color])) $color = $this->SVGcolors[$color];
31654
31655 if (preg_match('/^[\d]+$/',$color)) { $c = (array(1,$color)); } // i.e. integer only
31656 else if ($color[0] == '#') { //case of #nnnnnn or #nnn
31657 $cor = preg_replace('/\s+.*/','',$color); // in case of Background: #CCC url() x-repeat etc.
31658 if (strlen($cor) == 4) { // Turn #RGB into #RRGGBB
31659 $cor = "#" . $cor[1] . $cor[1] . $cor[2] . $cor[2] . $cor[3] . $cor[3];
31660 }
31661 $r = hexdec(substr($cor, 1, 2));
31662 $g = hexdec(substr($cor, 3, 2));
31663 $b = hexdec(substr($cor, 5, 2));
31664 $c = array(3,$r,$g,$b);
31665 }
31666 else if (preg_match('/(rgba|rgb|device-cmyka|cmyka|device-cmyk|cmyk|hsla|hsl|spot)\((.*?)\)/',$color,$m)) {
31667 $type= $m[1];
31668 $cores = explode(",", $m[2]);
31669 $ncores = count($cores);
31670 if (stristr($cores[0],'%') ) {
31671 $cores[0] += 0;
31672 if ($type=='rgb' || $type=='rgba') { $cores[0] = intval($cores[0]*255/100); }
31673 }
31674 if ($ncores>1 && stristr($cores[1],'%') ) {
31675 $cores[1] += 0;
31676 if ($type=='rgb' || $type=='rgba') { $cores[1] = intval($cores[1]*255/100); }
31677 if ($type=='hsl' || $type=='hsla') { $cores[1] = $cores[1]/100; }
31678 }
31679 if ($ncores>2 && stristr($cores[2],'%') ) {
31680 $cores[2] += 0;
31681 if ($type=='rgb' || $type=='rgba') { $cores[2] = intval($cores[2]*255/100); }
31682 if ($type=='hsl' || $type=='hsla') { $cores[2] = $cores[2]/100; }
31683 }
31684 if ($ncores>3 && stristr($cores[3],'%') ) {
31685 $cores[3] += 0;
31686 }
31687
31688 if ($type=='rgb') { $c = array(3,$cores[0],$cores[1],$cores[2]); }
31689 else if ($type=='rgba') { $c = array(5,$cores[0],$cores[1],$cores[2],$cores[3]*100); }
31690 else if ($type=='cmyk' || $type=='device-cmyk') { $c = array(4,$cores[0],$cores[1],$cores[2],$cores[3]); }
31691 else if ($type=='cmyka' || $type=='device-cmyka') { $c = array(6,$cores[0],$cores[1],$cores[2],$cores[3],$cores[4]*100); }
31692 else if ($type=='hsl' || $type=='hsla') {
31693 $conv = $this->hsl2rgb($cores[0]/360,$cores[1],$cores[2]);
31694 if ($type=='hsl') { $c = array(3,$conv[0],$conv[1],$conv[2]); }
31695 else if ($type=='hsla') { $c = array(5,$conv[0],$conv[1],$conv[2],$cores[3]*100); }
31696 }
31697 else if ($type=='spot') {
31698 $name = strtoupper(trim($cores[0]));
31699 if(!isset($this->spotColors[$name])) {
31700 if (isset($cores[5])) { $this->AddSpotColor($cores[0],$cores[2],$cores[3],$cores[4],$cores[5]); }
31701 else { $this->Error('Undefined spot color: '.$name); }
31702 }
31703 $c = array(2,$this->spotColors[$name]['i'],$cores[1]);
31704 }
31705 }
31706
31707
31708 // $this->restrictColorSpace
31709 // 1 - allow GRAYSCALE only [convert CMYK/RGB->gray]
31710 // 2 - allow RGB / SPOT COLOR / Grayscale [convert CMYK->RGB]
31711 // 3 - allow CMYK / SPOT COLOR / Grayscale [convert RGB->CMYK]
31712 if ($this->PDFA || $this->PDFX || $this->restrictColorSpace) {
31713 if ($c[0]==1) { // GRAYSCALE
31714 }
31715 else if ($c[0]==2) { // SPOT COLOR
31716 if (!isset($this->spotColorIDs[$c[1]])) { die('Error: Spot colour has not been defined - '.$this->spotColorIDs[$c[1]]); }
31717 if ($this->PDFA) {
31718 if ($this->PDFA && !$this->PDFAauto) { $this->PDFAXwarnings[] = "Spot color specified '".$this->spotColorIDs[$c[1]]."' (converted to process color)"; }
31719 if ($this->restrictColorSpace!=3) {
31720 $sp = $this->spotColors[$this->spotColorIDs[$c[1]]];
31721 $c = $this->cmyk2rgb(array(4,$sp['c'],$sp['m'],$sp['y'],$sp['k']));
31722 }
31723 }
31724 else if ($this->restrictColorSpace==1) {
31725 $sp = $this->spotColors[$this->spotColorIDs[$c[1]]];
31726 $c = $this->cmyk2gray(array(4,$sp['c'],$sp['m'],$sp['y'],$sp['k']));
31727 }
31728 }
31729 else if ($c[0]==3) { // RGB
31730 if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace==3)) {
31731 if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "RGB color specified '".$color."' (converted to CMYK)"; }
31732 $c = $this->rgb2cmyk($c);
31733 }
31734 else if ($this->restrictColorSpace==1) { $c = $this->rgb2gray($c); }
31735 else if ($this->restrictColorSpace==3) { $c = $this->rgb2cmyk($c); }
31736 }
31737 else if ($c[0]==4) { // CMYK
31738 if ($this->PDFA && $this->restrictColorSpace!=3) {
31739 if ($this->PDFA && !$this->PDFAauto) { $this->PDFAXwarnings[] = "CMYK color specified '".$color."' (converted to RGB)"; }
31740 $c = $this->cmyk2rgb($c);
31741 }
31742 else if ($this->restrictColorSpace==1) { $c = $this->cmyk2gray($c); }
31743 else if ($this->restrictColorSpace==2) { $c = $this->cmyk2rgb($c); }
31744 }
31745 else if ($c[0]==5) { // RGBa
31746 if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace==3)) {
31747 if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "RGB color with transparency specified '".$color."' (converted to CMYK without transparency)"; }
31748 $c = $this->rgb2cmyk($c);
31749 $c = array(4, $c[1], $c[2], $c[3], $c[4]);
31750 }
31751 else if ($this->PDFA && $this->restrictColorSpace!=3) {
31752 if (!$this->PDFAauto) { $this->PDFAXwarnings[] = "RGB color with transparency specified '".$color."' (converted to RGB without transparency)"; }
31753 $c = $this->rgb2cmyk($c);
31754 $c = array(4, $c[1], $c[2], $c[3], $c[4]);
31755 }
31756 else if ($this->restrictColorSpace==1) { $c = $this->rgb2gray($c); }
31757 else if ($this->restrictColorSpace==3) { $c = $this->rgb2cmyk($c); }
31758 }
31759 else if ($c[0]==6) { // CMYKa
31760 if ($this->PDFA && $this->restrictColorSpace!=3) {
31761 if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "CMYK color with transparency specified '".$color."' (converted to RGB without transparency)"; }
31762 $c = $this->cmyk2rgb($c);
31763 $c = array(3, $c[1], $c[2], $c[3]);
31764 }
31765 else if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace==3)) {
31766 if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "CMYK color with transparency specified '".$color."' (converted to CMYK without transparency)"; }
31767 $c = $this->cmyk2rgb($c);
31768 $c = array(3, $c[1], $c[2], $c[3]);
31769 }
31770 else if ($this->restrictColorSpace==1) { $c = $this->cmyk2gray($c); }
31771 else if ($this->restrictColorSpace==2) { $c = $this->cmyk2rgb($c); }
31772 }
31773 }
31774 if (is_array($c)) {
31775 $c = array_pad($c, 6, 0);
31776 $cstr = pack("a1ccccc", $c[0], ($c[1] & 0xFF), ($c[2] & 0xFF), ($c[3] & 0xFF), ($c[4] & 0xFF), ($c[5] & 0xFF) );
31777 }
31778 return $cstr;
31779 }
31780
31781 function rgb2gray($c) {
31782 if (isset($c[4])) { return array(1,(($c[1] * .21) + ($c[2] * .71) + ($c[3] * .07)), ord(1), $c[4]); }
31783 else { return array(1,(($c[1] * .21) + ($c[2] * .71) + ($c[3] * .07))); }
31784 }
31785
31786 function cmyk2gray($c) {
31787 $rgb = $this->cmyk2rgb($c);
31788 return $this->rgb2gray($rgb);
31789 }
31790
31791 function rgb2cmyk($c) {
31792 $cyan = 1 - ($c[1] / 255);
31793 $magenta = 1 - ($c[2] / 255);
31794 $yellow = 1 - ($c[3] / 255);
31795 $min = min($cyan, $magenta, $yellow);
31796
31797 if ($min == 1) {
31798 if ($c[0]==5) { return array (6,100,100,100,100, $c[4]); }
31799 else { return array (4,100,100,100,100); }
31800 // For K-Black
31801 //if ($c[0]==5) { return array (6,0,0,0,100, $c[4]); }
31802 //else { return array (4,0,0,0,100); }
31803 }
31804 $K = $min;
31805 $black = 1 - $K;
31806 if ($c[0]==5) { return array (6,($cyan-$K)*100/$black, ($magenta-$K)*100/$black, ($yellow-$K)*100/$black, $K*100, $c[4]); }
31807 else { return array (4,($cyan-$K)*100/$black, ($magenta-$K)*100/$black, ($yellow-$K)*100/$black, $K*100); }
31808 }
31809
31810
31811 function cmyk2rgb($c) {
31812 $rgb = array();
31813 $colors = 255 - ($c[4]*2.55);
31814 $rgb[0] = intval($colors * (255 - ($c[1]*2.55))/255);
31815 $rgb[1] = intval($colors * (255 - ($c[2]*2.55))/255);
31816 $rgb[2] = intval($colors * (255 - ($c[3]*2.55))/255);
31817 if ($c[0]==6) { return array (5,$rgb[0],$rgb[1],$rgb[2], $c[5]); }
31818 else { return array (3,$rgb[0],$rgb[1],$rgb[2]); }
31819 }
31820
31821 function rgb2hsl($var_r, $var_g, $var_b) {
31822 $var_min = min($var_r,$var_g,$var_b);
31823 $var_max = max($var_r,$var_g,$var_b);
31824 $del_max = $var_max - $var_min;
31825 $l = ($var_max + $var_min) / 2;
31826 if ($del_max == 0) {
31827 $h = 0;
31828 $s = 0;
31829 }
31830 else {
31831 if ($l < 0.5) { $s = $del_max / ($var_max + $var_min); }
31832 else { $s = $del_max / (2 - $var_max - $var_min); }
31833 $del_r = ((($var_max - $var_r) / 6) + ($del_max / 2)) / $del_max;
31834 $del_g = ((($var_max - $var_g) / 6) + ($del_max / 2)) / $del_max;
31835 $del_b = ((($var_max - $var_b) / 6) + ($del_max / 2)) / $del_max;
31836 if ($var_r == $var_max) { $h = $del_b - $del_g; }
31837 elseif ($var_g == $var_max) { $h = (1 / 3) + $del_r - $del_b; }
31838 elseif ($var_b == $var_max) { $h = (2 / 3) + $del_g - $del_r; };
31839 if ($h < 0) { $h += 1; }
31840 if ($h > 1) { $h -= 1; }
31841 }
31842 return array($h,$s,$l);
31843 }
31844
31845
31846 function hsl2rgb($h2,$s2,$l2) {
31847 // Input is HSL value of complementary colour, held in $h2, $s, $l as fractions of 1
31848 // Output is RGB in normal 255 255 255 format, held in $r, $g, $b
31849 // Hue is converted using function hue_2_rgb, shown at the end of this code
31850 if ($s2 == 0) {
31851 $r = $l2 * 255;
31852 $g = $l2 * 255;
31853 $b = $l2 * 255;
31854 }
31855 else {
31856 if ($l2 < 0.5) { $var_2 = $l2 * (1 + $s2); }
31857 else { $var_2 = ($l2 + $s2) - ($s2 * $l2); }
31858 $var_1 = 2 * $l2 - $var_2;
31859 $r = round(255 * $this->hue_2_rgb($var_1,$var_2,$h2 + (1 / 3)));
31860 $g = round(255 * $this->hue_2_rgb($var_1,$var_2,$h2));
31861 $b = round(255 * $this->hue_2_rgb($var_1,$var_2,$h2 - (1 / 3)));
31862 }
31863 return array($r,$g,$b);
31864 }
31865
31866 function hue_2_rgb($v1,$v2,$vh) {
31867 // Function to convert hue to RGB, called from above
31868 if ($vh < 0) { $vh += 1; };
31869 if ($vh > 1) { $vh -= 1; };
31870 if ((6 * $vh) < 1) { return ($v1 + ($v2 - $v1) * 6 * $vh); };
31871 if ((2 * $vh) < 1) { return ($v2); };
31872 if ((3 * $vh) < 2) { return ($v1 + ($v2 - $v1) * ((2 / 3 - $vh) * 6)); };
31873 return ($v1);
31874 }
31875
31876 function _invertColor($cor) {
31877 if ($cor[0]==3 || $cor[0]==5) { // RGB
31878 return array(3, (255-$cor[1]), (255-$cor[2]), (255-$cor[3]));
31879 }
31880 else if ($cor[0]==4 || $cor[0]==6) { // CMYK
31881 return array(4, (100-$cor[1]), (100-$cor[2]), (100-$cor[3]), (100-$cor[4]));
31882 }
31883 else if ($cor[0]==1) { // Grayscale
31884 return array(1, (255-$cor[1]));
31885 }
31886 // Cannot cope with non-RGB colors at present
31887 die('Error in _invertColor - trying to invert non-RGB color');
31888 }
31889
31890 function _colAtoString($cor) {
31891 $s = '';
31892 if ($cor{0}==1) $s = 'rgb('.ord($cor{1}).','.ord($cor{1}).','.ord($cor{1}).')';
31893 else if ($cor{0}==2) $s = 'spot('.ord($cor{1}).','.ord($cor{2}).')'; // SPOT COLOR
31894 else if ($cor{0}==3) $s = 'rgb('.ord($cor{1}).','.ord($cor{2}).','.ord($cor{3}).')';
31895 else if ($cor{0}==4) $s = 'cmyk('.ord($cor{1}).','.ord($cor{2}).','.ord($cor{3}).','.ord($cor{4}).')';
31896 else if ($cor{0}==5) $s = 'rgba('.ord($cor{1}).','.ord($cor{2}).','.ord($cor{3}).','.sprintf('%0.2F',ord($cor{4})/100).')';
31897 else if ($cor{0}==6) $s = 'cmyka('.ord($cor{1}).','.ord($cor{2}).','.ord($cor{3}).','.ord($cor{4}).','.sprintf('%0.2F',ord($cor{5})/100).')';
31898 return $s;
31899 }
31900
31901 function ConvertSize($size=5,$maxsize=0,$fontsize=false,$usefontsize=true){
31902 // usefontsize - set false for e.g. margins - will ignore fontsize for % values
31903 // Depends of maxsize value to make % work properly. Usually maxsize == pagewidth
31904 // For text $maxsize = Fontsize
31905 // Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize
31906 // Returns values using 'mm' units
31907 $size = trim(strtolower($size));
31908
31909 if ( $size == 'thin' ) $size = 1*(25.4/$this->dpi); //1 pixel width for table borders
31910 elseif ( stristr($size,'px') ) $size *= (25.4/$this->dpi); //pixels
31911 elseif ( stristr($size,'cm') ) $size *= 10; //centimeters
31912 elseif ( stristr($size,'mm') ) $size += 0; //millimeters
31913 elseif ( stristr($size,'pt') ) $size *= 25.4/72; //72 pts/inch
31914 elseif ( stristr($size,'rem') ) {
31915 $size += 0; //make "0.83rem" become simply "0.83"
31916 $size *= ($this->default_font_size / _MPDFK);
31917 }
31918 elseif ( stristr($size,'em') ) {
31919 $size += 0; //make "0.83em" become simply "0.83"
31920 if ($fontsize) { $size *= $fontsize; }
31921 else { $size *= $maxsize; }
31922 }
31923 elseif ( stristr($size,'%') ) {
31924 $size += 0; //make "90%" become simply "90"
31925 if ($fontsize && $usefontsize) { $size *= $fontsize/100; }
31926 else { $size *= $maxsize/100; }
31927 }
31928 elseif ( stristr($size,'in') ) $size *= 25.4; //inches
31929 elseif ( stristr($size,'pc') ) $size *= 38.1/9; //PostScript picas
31930 elseif ( stristr($size,'ex') ) { // Approximates "ex" as half of font height
31931 $size += 0; //make "3.5ex" become simply "3.5"
31932 if ($fontsize) { $size *= $fontsize/2; }
31933 else { $size *= $maxsize/2; }
31934 }
31935 elseif ( $size == 'medium' ) $size = 3*(25.4/$this->dpi); //3 pixel width for table borders
31936 elseif ( $size == 'thick' ) $size = 5*(25.4/$this->dpi); //5 pixel width for table borders
31937 elseif ($size == 'xx-small') {
31938 if ($fontsize) { $size *= $fontsize*0.7; }
31939 else { $size *= $maxsize*0.7; }
31940 }
31941 elseif ($size == 'x-small') {
31942 if ($fontsize) { $size *= $fontsize*0.77; }
31943 else { $size *= $maxsize*0.77; }
31944 }
31945 elseif ($size == 'small') {
31946 if ($fontsize) { $size *= $fontsize*0.86; }
31947 else { $size *= $maxsize*0.86; }
31948 }
31949 elseif ($size == 'medium') {
31950 if ($fontsize) { $size *= $fontsize; }
31951 else { $size *= $maxsize; }
31952 }
31953 elseif ($size == 'large') {
31954 if ($fontsize) { $size *= $fontsize*1.2; }
31955 else { $size *= $maxsize*1.2; }
31956 }
31957 elseif ($size == 'x-large') {
31958 if ($fontsize) { $size *= $fontsize*1.5; }
31959 else { $size *= $maxsize*1.5; }
31960 }
31961 elseif ($size == 'xx-large') {
31962 if ($fontsize) { $size *= $fontsize*2; }
31963 else { $size *= $maxsize*2; }
31964 }
31965 else $size *= (25.4/$this->dpi); //nothing == px
31966
31967 return $size;
31968 }
31969
31970 // mPDF 5.7.3 TRANSFORMS
31971 function ConvertAngle($s, $makepositive=true) {
31972 if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i',$s,$m)) {
31973 $angle = $m[1] + 0;
31974 if (strtolower($m[2])=='deg') { $angle = $angle; }
31975 else if (strtolower($m[2])=='grad') { $angle *= (360/400); }
31976 else if (strtolower($m[2])=='rad') { $angle = rad2deg($angle); }
31977 while($angle >= 360) { $angle -= 360; }
31978 while($angle <= -360) { $angle += 360; }
31979 if ($makepositive) { // always returns an angle between 0 and 360deg
31980 if ($angle < 0) { $angle += 360; }
31981 }
31982 }
31983 else { $angle = $s + 0; }
31984 return $angle;
31985 }
31986
31987 function lesser_entity_decode($html) {
31988 //supports the most used entity codes (only does ascii safe characters)
31989 $html = str_replace("&lt;","<",$html);
31990 $html = str_replace("&gt;",">",$html);
31991
31992 $html = str_replace("&apos;","'",$html);
31993 $html = str_replace("&quot;",'"',$html);
31994 $html = str_replace("&amp;","&",$html);
31995 return $html;
31996 }
31997
31998 function AdjustHTML($html, $tabSpaces=8) {
31999 //Try to make the html text more manageable (turning it into XHTML)
32000 if (PHP_VERSION_ID < 50307) {
32001 if (strlen($html) > 100000) {
32002 if (PHP_VERSION_ID < 50200) $this->Error("The HTML code is more than 100,000 characters. You should use WriteHTML() with smaller string lengths.");
32003 else ini_set("pcre.backtrack_limit","1000000");
32004 }
32005 }
32006
32007 /*-- ANNOTATIONS --*/
32008 preg_match_all("/(<annotation.*?>)/si", $html, $m);
32009 if (count($m[1])) {
32010 for($i=0;$i<count($m[1]);$i++) {
32011 $sub = preg_replace("/\n/si", "\xbb\xa4\xac", $m[1][$i]);
32012 $html = preg_replace('/'.preg_quote($m[1][$i], '/').'/si', $sub, $html);
32013 }
32014 }
32015 /*-- END ANNOTATIONS --*/
32016
32017 preg_match_all("/(<svg.*?<\/svg>)/si", $html, $svgi);
32018 if (count($svgi[0])) {
32019 for($i=0;$i<count($svgi[0]);$i++) {
32020 $file = _MPDF_TEMP_PATH.'_tempSVG'.uniqid(rand(1,100000),true).'_'.$i.'.svg';
32021 //Save to local file
32022 file_put_contents($file, $svgi[0][$i]);
32023 $html = str_replace($svgi[0][$i], '<img src="'.$file.'" />', $html);
32024 }
32025 }
32026
32027 //Remove javascript code from HTML (should not appear in the PDF file)
32028 $html = preg_replace('/<script.*?<\/script>/is','',$html);
32029
32030 //Remove special comments
32031 $html = preg_replace('/<!--mpdf/i','',$html);
32032 $html = preg_replace('/mpdf-->/i','',$html);
32033
32034 //Remove comments from HTML (should not appear in the PDF file)
32035 $html = preg_replace('/<!--.*?-->/s','',$html);
32036
32037 $html = preg_replace('/\f/','',$html); //replace formfeed by nothing
32038 $html = preg_replace('/\r/','',$html); //replace carriage return by nothing
32039
32040 // Well formed XHTML end tags
32041 $html = preg_replace('/<(br|hr)>/i',"<\\1 />",$html); // mPDF 6
32042 $html = preg_replace('/<(br|hr)\/>/i',"<\\1 />",$html);
32043 // Get rid of empty <thead></thead> etc
32044 $html = preg_replace('/<tr>\s*<\/tr>/i','',$html);
32045 $html = preg_replace('/<thead>\s*<\/thead>/i','',$html);
32046 $html = preg_replace('/<tfoot>\s*<\/tfoot>/i','',$html);
32047 $html = preg_replace('/<table[^>]*>\s*<\/table>/i','',$html);
32048
32049 // Remove spaces at end of table cells
32050 $html = preg_replace("/[ \n\r]+<\/t(d|h)/",'</t\\1',$html);
32051
32052 $html = preg_replace("/[ ]*<dottab\s*[\/]*>[ ]*/",'<dottab />',$html);
32053
32054 // Concatenates any Substitute characters from symbols/dingbats
32055 $html = str_replace('</tts><tts>','|',$html);
32056 $html = str_replace('</ttz><ttz>','|',$html);
32057 $html = str_replace('</tta><tta>','|',$html);
32058
32059 $html = preg_replace('/<br \/>\s*/is',"<br />",$html);
32060
32061 $html = preg_replace('/<wbr[ \/]*>\s*/is',"&#173;",$html);
32062
32063 // Preserve '\n's in content between the tags <pre> and </pre>
32064 if (preg_match('/<pre/',$html)) {
32065 $html_a = preg_split('/(\<\/?pre[^\>]*\>)/', $html, -1, 2);
32066 $h = array();
32067 $c=0;
32068 foreach($html_a AS $s) {
32069 if ($c>1 && preg_match('/^<\/pre/i',$s)) { $c--; $s=preg_replace('/<\/pre/i','</innerpre',$s); }
32070 else if ($c>0 && preg_match('/^<pre/i',$s)) { $c++; $s=preg_replace('/<pre/i','<innerpre',$s); }
32071 else if (preg_match('/^<pre/i',$s)) { $c++; }
32072 else if (preg_match('/^<\/pre/i',$s)) { $c--; }
32073 array_push($h, $s);
32074 }
32075 $html = implode("", $h);
32076 }
32077 $thereispre = preg_match_all('#<pre(.*?)>(.*?)</pre>#si',$html,$temp);
32078 // Preserve '\n's in content between the tags <textarea> and </textarea>
32079 $thereistextarea = preg_match_all('#<textarea(.*?)>(.*?)</textarea>#si',$html,$temp2);
32080 $html = preg_replace('/[\n]/',' ',$html); //replace linefeed by spaces
32081 $html = preg_replace('/[\t]/',' ',$html); //replace tabs by spaces
32082
32083 // Converts < to &lt; when not a tag
32084 $html = preg_replace('/<([^!\/a-zA-Z_:])/i','&lt;\\1',$html); // mPDF 5.7.3
32085 $html = preg_replace("/[ ]+/",' ',$html);
32086
32087 $html = preg_replace('/\/li>\s+<\/(u|o)l/i','/li></\\1l',$html);
32088 $html = preg_replace('/\/(u|o)l>\s+<\/li/i','/\\1l></li',$html);
32089 $html = preg_replace('/\/li>\s+<\/(u|o)l/i','/li></\\1l',$html);
32090 $html = preg_replace('/\/li>\s+<li/i','/li><li',$html);
32091 $html = preg_replace('/<(u|o)l([^>]*)>[ ]+/i','<\\1l\\2>',$html);
32092 $html = preg_replace('/[ ]+<(u|o)l/i','<\\1l',$html);
32093
32094 // Make self closing tabs valid XHTML
32095 // Tags which are self-closing: 1) Replaceable and 2) Non-replaced items
32096 $selftabs = 'input|hr|img|br|jpgraph|barcode|dottab';
32097 $selftabs2 = 'indexentry|indexinsert|bookmark|watermarktext|watermarkimage|column_break|columnbreak|newcolumn|newpage|page_break|pagebreak|formfeed|columns|toc|tocpagebreak|setpageheader|setpagefooter|sethtmlpageheader|sethtmlpagefooter|annotation';
32098 $html = preg_replace('/(<('.$selftabs.'|'.$selftabs2.')[^>\/]*)>/i','\\1 />',$html);
32099
32100 $iterator = 0;
32101 while($thereispre) //Recover <pre attributes>content</pre>
32102 {
32103 $temp[2][$iterator] = preg_replace('/<([^!\/a-zA-Z_:])/','&lt;\\1',$temp[2][$iterator]); // mPDF 5.7.2 // mPDF 5.7.3
32104
32105 $temp[2][$iterator] = preg_replace_callback("/^([^\n\t]*?)\t/m", array($this, 'tabs2spaces_callback'), $temp[2][$iterator]); // mPDF 5.7+
32106 $temp[2][$iterator] = preg_replace('/\t/',str_repeat(" ",$tabSpaces),$temp[2][$iterator]);
32107
32108 $temp[2][$iterator] = preg_replace('/\n/',"<br />",$temp[2][$iterator]);
32109 $temp[2][$iterator] = str_replace('\\',"\\\\",$temp[2][$iterator]);
32110 //$html = preg_replace('#<pre(.*?)>(.*?)</pre>#si','<erp'.$temp[1][$iterator].'>'.$temp[2][$iterator].'</erp>',$html,1);
32111 $html = preg_replace('#<pre(.*?)>(.*?)</pre>#si','<erp'.$temp[1][$iterator].'>'.str_replace('$','\$',$temp[2][$iterator]).'</erp>',$html,1); // mPDF 5.7+
32112 $thereispre--;
32113 $iterator++;
32114 }
32115 $iterator = 0;
32116 while($thereistextarea) //Recover <textarea attributes>content</textarea>
32117 {
32118 $temp2[2][$iterator] = preg_replace('/\t/',str_repeat(" ",$tabSpaces),$temp2[2][$iterator]);
32119 $temp2[2][$iterator] = str_replace('\\',"\\\\",$temp2[2][$iterator]);
32120 $html = preg_replace('#<textarea(.*?)>(.*?)</textarea>#si','<aeratxet'.$temp2[1][$iterator].'>'.trim($temp2[2][$iterator]) .'</aeratxet>',$html,1);
32121 $thereistextarea--;
32122 $iterator++;
32123 }
32124 //Restore original tag names
32125 $html = str_replace("<erp","<pre",$html);
32126 $html = str_replace("</erp>","</pre>",$html);
32127 $html = str_replace("<aeratxet","<textarea",$html);
32128 $html = str_replace("</aeratxet>","</textarea>",$html);
32129 $html = str_replace("</innerpre","</pre",$html);
32130 $html = str_replace("<innerpre","<pre",$html);
32131
32132 $html = preg_replace('/<textarea([^>]*)><\/textarea>/si','<textarea\\1> </textarea>',$html);
32133 $html = preg_replace('/(<table[^>]*>)\s*(<caption)(.*?<\/caption>)(.*?<\/table>)/si','\\2 position="top"\\3\\1\\4\\2 position="bottom"\\3',$html); // *TABLES*
32134 $html = preg_replace('/<(h[1-6])([^>]*)(>(?:(?!h[1-6]).)*?<\/\\1>\s*<table)/si','<\\1\\2 keep-with-table="1"\\3',$html); // *TABLES*
32135 $html = preg_replace("/\xbb\xa4\xac/", "\n", $html);
32136
32137 // Fixes <p>&#8377</p> which browser copes with even though it is wrong!
32138 $html = preg_replace("/(&#[x]{0,1}[0-9a-f]{1,5})</i", "\\1;<", $html);
32139 return $html;
32140 }
32141 // mPDF 5.7+
32142 function tabs2spaces_callback($matches) {
32143 return (stripslashes($matches[1]) . str_repeat(' ', $this->tabSpaces - (mb_strlen(stripslashes($matches[1])) % $this->tabSpaces)));
32144 }
32145 // mPDF 5.7+
32146 function date_callback($matches) {
32147 return date($matches[1]);
32148 }
32149
32150
32151 function dec2other($num, $cp, $check=true) {
32152 // From printlistbuffer: font is set, so check if character is available
32153 // From docPageNum: font is not set, so no check
32154 $nstr = (string) $num;
32155 $rnum = '';
32156 for ($i=0;$i<strlen($nstr);$i++) {
32157 if (!$check || $this->_charDefined($this->CurrentFont['cw'],$cp+intval($nstr[$i]))) {
32158 $rnum .= code2utf($cp+intval($nstr[$i]));
32159 }
32160 else { $rnum .= $nstr[$i]; }
32161 }
32162 return $rnum;
32163 }
32164
32165 function dec2cjk($num) {
32166 $nstr = (string) $num;
32167 $rnum = '';
32168 $glyphs = array(0x3007, 0x4E00, 0x4E8C, 0x4E09, 0x56DB, 0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D);
32169 for ($i=0;$i<strlen($nstr);$i++) {
32170 $rnum .= code2utf($glyphs[intval($nstr[$i])]);
32171 }
32172 return $rnum;
32173 }
32174
32175 function dec2alpha($valor,$toupper="true"){
32176 // returns a string from A-Z to AA-ZZ to AAA-ZZZ
32177 // OBS: A = 65 ASCII TABLE VALUE
32178 if (($valor < 1) || ($valor > 18278)) return "?"; //supports 'only' up to 18278
32179 $c1 = $c2 = $c3 = '';
32180 if ($valor > 702) // 3 letters (up to 18278)
32181 {
32182 $c1 = 65 + floor(($valor-703)/676);
32183 $c2 = 65 + floor((($valor-703)%676)/26);
32184 $c3 = 65 + floor((($valor-703)%676)%26);
32185 }
32186 elseif ($valor > 26) // 2 letters (up to 702)
32187 {
32188 $c1 = (64 + (int)(($valor-1) / 26));
32189 $c2 = (64 + (int)($valor % 26));
32190 if ($c2 == 64) $c2 += 26;
32191 }
32192 else // 1 letter (up to 26)
32193 {
32194 $c1 = (64 + $valor);
32195 }
32196 $alpha = chr($c1);
32197 if ($c2 != '') $alpha .= chr($c2);
32198 if ($c3 != '') $alpha .= chr($c3);
32199 if (!$toupper) $alpha = strtolower($alpha);
32200 return $alpha;
32201 }
32202
32203 // mPDF 6
32204 function dec2hebrew($in, $reverse = false) {
32205 // reverse is used when called from Lists, as these do not pass through bidi-algorithm
32206 $i = intval( $in ); // I initially be the counter value
32207 $s = ''; // S initially be the empty string
32208 //and glyph list initially be the list of additive tuples.
32209 $additive_nums = array(400, 300, 200, 100, 90, 80, 70, 60, 50, 40, 30, 20, 19, 18, 17, 16, 15, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
32210 $additive_glyphs = array(0x05EA, 0x05E9, 0x05E8, 0x05E7, 0x05E6, 0x05E4, 0x05E2, 0x05E1, 0x05E0, 0x05DE, 0x05DC, 0x05DB,
32211 array(0x05D9,0x05D8), array(0x05D9,0x05D7), array(0x05D9,0x05D6), array(0x05D8,0x05D6), array(0x05D8,0x05D5), 0x05D9,
32212 0x05D8, 0x05D7, 0x05D6, 0x05D5, 0x05D4, 0x05D3, 0x05D2, 0x05D1, 0x05D0);
32213 /* NB This system manually specifies the values for 19-15 to force the correct display of 15 and 16, which are commonly
32214 rewritten to avoid a close resemblance to the Tetragrammaton. */
32215 // This function only works up to 1,000
32216 if ($i>999) { return $in; } // return as initial numeric string
32217
32218 // If I is initially 0, and there is an additive tuple with a weight of 0, append that tuple's counter glyph to S and return S.
32219 if ($i==0) { return '0'; }
32220
32221 // Otherwise, while I is greater than 0 and there are elements left in the glyph list:
32222 for ($t=0; $t<count($additive_nums); $t++) {
32223
32224 // Pop the first additive tuple from the glyph list. This is the current tuple.
32225 $ct = $additive_nums[$t];
32226 // Append the current tuple's counter glyph to S x floor( I / current tuple's weight ) times (this may be 0).
32227 $n = floor($i / $ct);
32228 for($j=0;$j<$n;$j++) {
32229 if (is_array($additive_glyphs[$t])) {
32230 foreach ($additive_glyphs[$t] AS $ag) {
32231 if ($reverse) { $s = code2utf($ag) . $s; }
32232 else { $s .= code2utf($ag); }
32233 }
32234 }
32235 else {
32236 if ($reverse) { $s = code2utf($additive_glyphs[$t]) . $s; }
32237 else { $s .= code2utf($additive_glyphs[$t]); }
32238 }
32239 $i -= ($ct * $n);
32240 }
32241 if ($i==0) { return $s; }
32242 }
32243 return $in; // return as initial string
32244 }
32245
32246
32247 function dec2roman($valor,$toupper=true){
32248 //returns a string as a roman numeral
32249 $r1=$r2=$r3=$r4='';
32250 if (($valor >= 5000) || ($valor < 1)) return "?"; //supports 'only' up to 4999
32251 $aux = (int)($valor/1000);
32252 if ($aux!==0)
32253 {
32254 $valor %= 1000;
32255 while($aux!==0)
32256 {
32257 $r1 .= "M";
32258 $aux--;
32259 }
32260 }
32261 $aux = (int)($valor/100);
32262 if ($aux!==0)
32263 {
32264 $valor %= 100;
32265 switch($aux){
32266 case 3: $r2="C";
32267 case 2: $r2.="C";
32268 case 1: $r2.="C"; break;
32269 case 9: $r2="CM"; break;
32270 case 8: $r2="C";
32271 case 7: $r2.="C";
32272 case 6: $r2.="C";
32273 case 5: $r2="D".$r2; break;
32274 case 4: $r2="CD"; break;
32275 default: break;
32276 }
32277 }
32278 $aux = (int)($valor/10);
32279 if ($aux!==0)
32280 {
32281 $valor %= 10;
32282 switch($aux){
32283 case 3: $r3="X";
32284 case 2: $r3.="X";
32285 case 1: $r3.="X"; break;
32286 case 9: $r3="XC"; break;
32287 case 8: $r3="X";
32288 case 7: $r3.="X";
32289 case 6: $r3.="X";
32290 case 5: $r3="L".$r3; break;
32291 case 4: $r3="XL"; break;
32292 default: break;
32293 }
32294 }
32295 switch($valor){
32296 case 3: $r4="I";
32297 case 2: $r4.="I";
32298 case 1: $r4.="I"; break;
32299 case 9: $r4="IX"; break;
32300 case 8: $r4="I";
32301 case 7: $r4.="I";
32302 case 6: $r4.="I";
32303 case 5: $r4="V".$r4; break;
32304 case 4: $r4="IV"; break;
32305 default: break;
32306 }
32307 $roman = $r1.$r2.$r3.$r4;
32308 if (!$toupper) $roman = strtolower($roman);
32309 return $roman;
32310 }
32311
32312 //===========================
32313 /*-- IMPORTS --*/
32314 function SetImportUse() {
32315 $this->enableImports = true;
32316 ini_set('auto_detect_line_endings',1);
32317 require_once(_MPDF_PATH."mpdfi/pdf_context.php");
32318 require_once(_MPDF_PATH."mpdfi/pdf_parser.php");
32319 require_once(_MPDF_PATH."mpdfi/fpdi_pdf_parser.php");
32320 }
32321
32322 // from mPDFI
32323 function hex2str($hex) {
32324 return pack("H*", str_replace(array("\r","\n"," "),"", $hex));
32325 }
32326
32327 function str2hex($str) {
32328 return current(unpack("H*",$str));
32329 }
32330
32331
32332 function pdf_write_value(&$value) {
32333 switch ($value[0]) {
32334 case PDF_TYPE_NUMERIC :
32335 case PDF_TYPE_TOKEN :
32336 // A numeric value or a token.
32337 // Simply output them
32338 $this->_out($value[1]." ", false);
32339 break;
32340
32341 case PDF_TYPE_ARRAY :
32342 // An array. Output the proper
32343 // structure and move on.
32344 $this->_out("[",false);
32345 for ($i = 0; $i < count($value[1]); $i++) {
32346 $this->pdf_write_value($value[1][$i]);
32347 }
32348 $this->_out("]");
32349 break;
32350
32351 case PDF_TYPE_DICTIONARY :
32352 // A dictionary.
32353 $this->_out("<<",false);
32354 reset ($value[1]);
32355 while (list($k, $v) = each($value[1])) {
32356 $this->_out($k . " ",false);
32357 $this->pdf_write_value($v);
32358 }
32359 $this->_out(">>");
32360 break;
32361
32362 case PDF_TYPE_OBJREF :
32363 // An indirect object reference
32364 // Fill the object stack if needed
32365 $cpfn =& $this->current_parser->filename;
32366 if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) {
32367 $this->_newobj(false,true);
32368 $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value);
32369 $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value);
32370 }
32371 $objid = $this->_don_obj_stack[$cpfn][$value[1]][0];
32372 $this->_out("{$objid} 0 R"); //{$value[2]}
32373 break;
32374
32375 case PDF_TYPE_STRING :
32376 if ($this->encrypted) {
32377 $value[1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[1]);
32378 $value[1] = $this->_escape($value[1]);
32379 }
32380 // A string.
32381 $this->_out('('.$value[1].')');
32382 break;
32383
32384 case PDF_TYPE_STREAM :
32385 // A stream. First, output the
32386 // stream dictionary, then the
32387 // stream data itself.
32388 $this->pdf_write_value($value[1]);
32389 if ($this->encrypted) {
32390 $value[2][1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[2][1]);
32391 }
32392 $this->_out("stream");
32393 $this->_out($value[2][1]);
32394 $this->_out("endstream");
32395 break;
32396
32397 case PDF_TYPE_HEX :
32398 if ($this->encrypted) {
32399 $value[1] = $this->hex2str($value[1]);
32400 $value[1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[1]);
32401 // remake hexstring of encrypted string
32402 $value[1] = $this->str2hex($value[1]);
32403 }
32404 $this->_out("<".$value[1].">");
32405 break;
32406
32407 case PDF_TYPE_NULL :
32408 // The null object.
32409 $this->_out("null");
32410 break;
32411 }
32412 }
32413
32414 // ========== OVERWRITE SEARCH STRING IN A PDF FILE ================
32415 function OverWrite($file_in, $search, $replacement, $dest="D", $file_out="mpdf" ) {
32416 $pdf = file_get_contents($file_in);
32417
32418 if (!is_array($search)) {
32419 $x = $search;
32420 $search = array($x);
32421 }
32422 if (!is_array($replacement)) {
32423 $x = $replacement;
32424 $replacement = array($x); // mPDF 5.7.4
32425 }
32426
32427 if (!$this->onlyCoreFonts && !$this->usingCoreFont) {
32428 foreach($search AS $k=>$val) {
32429 $search[$k] = $this->UTF8ToUTF16BE($search[$k] , false);
32430 $search[$k] = $this->_escape($search[$k]);
32431 $replacement[$k] = $this->UTF8ToUTF16BE($replacement[$k], false);
32432 $replacement[$k] = $this->_escape($replacement[$k]);
32433 }
32434 }
32435 else {
32436 foreach($replacement AS $k=>$val) {
32437 $replacement[$k] = mb_convert_encoding($replacement[$k],$this->mb_enc,'utf-8');
32438 $replacement[$k] = $this->_escape($replacement[$k]);
32439 }
32440 }
32441
32442 // Get xref into array
32443 $xref = array();
32444 preg_match("/xref\n0 (\d+)\n(.*?)\ntrailer/s",$pdf,$m);
32445 $xref_objid = $m[1];
32446 preg_match_all('/(\d{10}) (\d{5}) (f|n)/',$m[2],$x);
32447 for($i=0; $i<count($x[0]); $i++) {
32448 $xref[] = array(intval($x[1][$i]), $x[2][$i], $x[3][$i]);
32449 }
32450
32451 $changes = array();
32452 preg_match("/<<\s*\/Type\s*\/Pages\s*\/Kids\s*\[(.*?)\]\s*\/Count/s",$pdf,$m);
32453 preg_match_all("/(\d+) 0 R /s",$m[1],$o);
32454 $objlist = $o[1];
32455 foreach($objlist AS $obj) {
32456 if ($this->compress) {
32457 preg_match("/".($obj+1)." 0 obj\n<<\s*\/Filter\s*\/FlateDecode\s*\/Length (\d+)>>\nstream\n(.*?)\nendstream\n/s",$pdf,$m);
32458 }
32459 else {
32460 preg_match("/".($obj+1)." 0 obj\n<<\s*\/Length (\d+)>>\nstream\n(.*?)\nendstream\n/s",$pdf,$m);
32461 }
32462 $s = $m[2];
32463 if (!$s) { continue; }
32464 $oldlen = $m[1];
32465 if ($this->encrypted) {
32466 $s = $this->_RC4($this->_objectkey($obj+1), $s);
32467 }
32468 if ($this->compress) {
32469 $s = gzuncompress($s);
32470 }
32471 foreach($search AS $k=>$val) {
32472 $s = str_replace($search[$k],$replacement[$k],$s);
32473 }
32474 if ($this->compress) {
32475 $s = gzcompress($s);
32476 }
32477 if ($this->encrypted) {
32478 $s = $this->_RC4($this->_objectkey($obj+1), $s);
32479 }
32480 $newlen = strlen($s);
32481 $changes[($xref[$obj+1][0])] = ($newlen - $oldlen) + (strlen($newlen) - strlen($oldlen ));
32482 if ($this->compress) {
32483 $newstr = ($obj+1) . " 0 obj\n<</Filter /FlateDecode /Length ".$newlen.">>\nstream\n".$s."\nendstream\n";
32484 }
32485 else {
32486 $newstr = ($obj+1) . " 0 obj\n<</Length ".$newlen.">>\nstream\n".$s."\nendstream\n";
32487 }
32488 $pdf = str_replace($m[0],$newstr,$pdf);
32489 }
32490
32491 // Update xref in PDF
32492 krsort($changes);
32493 $newxref = "xref\n0 ".$xref_objid."\n";
32494 foreach($xref AS $v) {
32495 foreach($changes AS $ck => $cv) {
32496 if ($v[0] > $ck) { $v[0] += $cv; }
32497 }
32498 $newxref .= sprintf('%010d',$v[0]) . ' ' . $v[1] . ' ' .$v[2] . " \n";
32499 }
32500 $newxref .= "trailer";
32501 $pdf = preg_replace("/xref\n0 \d+\n.*?\ntrailer/s",$newxref,$pdf);
32502
32503 // Update startxref in PDF
32504 preg_match("/startxref\n(\d+)\n%%EOF/s", $pdf, $m);
32505 $startxref = $m[1];
32506 $startxref += array_sum($changes);
32507 $pdf = preg_replace("/startxref\n(\d+)\n%%EOF/s","startxref\n".$startxref."\n%%EOF",$pdf);
32508
32509 // OUTPUT
32510 switch($dest) {
32511 case 'I':
32512 //Send to standard output
32513 if(isset($_SERVER['SERVER_NAME']))
32514 {
32515 //We send to a browser
32516 Header('Content-Type: application/pdf');
32517 Header('Content-Length: '.strlen($pdf));
32518 Header('Content-disposition: inline; filename='.$file_out);
32519 }
32520 echo $pdf;
32521 break;
32522 case 'F':
32523 //Save to local file
32524 if (!$file_out) { $file_out = 'mpdf.pdf'; }
32525 $f=fopen($file_out,'wb');
32526 if(!$f) die('Unable to create output file: '.$file_out);
32527 fwrite($f,$pdf,strlen($pdf));
32528 fclose($f);
32529 break;
32530 case 'S':
32531 //Return as a string
32532 return $pdf;
32533 case 'D':
32534 default:
32535 //Download file
32536 if(isset($_SERVER['HTTP_USER_AGENT']) and strpos($_SERVER['HTTP_USER_AGENT'],'MSIE'))
32537 Header('Content-Type: application/force-download');
32538 else
32539 Header('Content-Type: application/octet-stream');
32540 Header('Content-Length: '.strlen($pdf));
32541 Header('Content-disposition: attachment; filename='.$file_out);
32542 echo $pdf;
32543 break;
32544 }
32545 }
32546
32547
32548 function GetTemplateSize($tplidx, $_w=0, $_h=0) {
32549 if (!$this->tpls[$tplidx])
32550 return false;
32551 $w = $this->tpls[$tplidx]['box']['w'];
32552 $h = $this->tpls[$tplidx]['box']['h'];
32553 if ($_w == 0 and $_h == 0) {
32554 $_w = $w;
32555 $_h = $h;
32556 }
32557 if($_w==0)
32558 $_w=$_h*$w/$h;
32559 if($_h==0)
32560 $_h=$_w*$h/$w;
32561 return array("w" => $_w, "h" => $_h);
32562 }
32563
32564 // Thumbnails
32565 function Thumbnail($file, $npr=3, $spacing=10) { //$npr = number per row
32566 $w = (($this->pgwidth + $spacing)/$npr) - $spacing;
32567 $oldlinewidth = $this->LineWidth;
32568 $this->SetLineWidth(0.02);
32569 $this->SetDColor($this->ConvertColor(0));
32570 $h = 0;
32571 $maxh = 0;
32572 $x = $_x = $this->lMargin;
32573 $_y = $this->tMargin;
32574 if ($this->y==0) { $y = $_y; } else { $y = $this->y; }
32575 $pagecount = $this->SetSourceFile($file);
32576 for ($n = 1; $n <= $pagecount; $n++) {
32577 $tplidx = $this->ImportPage($n);
32578 $size = $this->useTemplate($tplidx, $x, $y, $w);
32579 $this->Rect($x, $y, $size['w'], $size['h']);
32580 $h = max($h, $size['h']);
32581 $maxh = max($h, $maxh);
32582 if ($n % $npr == 0) {
32583 if (($y + $h + $spacing + $maxh)>$this->PageBreakTrigger && $n != $pagecount) {
32584 $this->AddPage();
32585 $x = $_x;
32586 $y = $_y;
32587 }
32588 else {
32589 $y += $h+$spacing ;
32590 $x = $_x;
32591 $h = 0;
32592 }
32593 }
32594 else {
32595 $x += $w+$spacing ;
32596 }
32597 }
32598 $this->SetLineWidth($oldlinewidth);
32599 }
32600
32601 function SetSourceFile($filename) {
32602 $this->current_filename = $filename;
32603 $fn =& $this->current_filename;
32604 if (!isset($this->parsers[$fn]))
32605 // $this->parsers[$fn] =& new fpdi_pdf_parser($fn,$this);
32606 $this->parsers[$fn] = new fpdi_pdf_parser($fn,$this);
32607 if (!$this->parsers[$fn]->success) {
32608 $this->Error($this->parsers[$fn]->errormsg); // Delete this line to return false on fail
32609 return false;
32610 }
32611 $this->current_parser =& $this->parsers[$fn];
32612 return $this->parsers[$fn]->getPageCount();
32613 }
32614 function ImportPage($pageno=1, $crop_x=null, $crop_y=null, $crop_w=0, $crop_h=0, $boxName='/CropBox') {
32615 $fn =& $this->current_filename;
32616 $parser =& $this->parsers[$fn];
32617 $parser->setPageno($pageno);
32618
32619 $this->tpl++;
32620 $this->tpls[$this->tpl] = array();
32621 $tpl =& $this->tpls[$this->tpl];
32622 $tpl['parser'] =& $parser;
32623 $tpl['resources'] = $parser->getPageResources();
32624 $tpl['buffer'] = $parser->getContent();
32625 if (!in_array($boxName, $parser->availableBoxes))
32626 return $this->Error(sprintf("Unknown box: %s", $boxName));
32627 $pageboxes = $parser->getPageBoxes($pageno);
32628 /**
32629 * MediaBox
32630 * CropBox: Default -> MediaBox
32631 * BleedBox: Default -> CropBox
32632 * TrimBox: Default -> CropBox
32633 * ArtBox: Default -> CropBox
32634 */
32635 if (!isset($pageboxes[$boxName]) && ($boxName == "/BleedBox" || $boxName == "/TrimBox" || $boxName == "/ArtBox"))
32636 $boxName = "/CropBox";
32637 if (!isset($pageboxes[$boxName]) && $boxName == "/CropBox")
32638 $boxName = "/MediaBox";
32639 if (!isset($pageboxes[$boxName]))
32640 return false;
32641 $box = $pageboxes[$boxName];
32642
32643 $tpl['box'] = $box;
32644 // To build an array that can be used by useTemplate()
32645 $this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl],$box);
32646 // An imported page will start at 0,0 everytime. Translation will be set in _putformxobjects()
32647 $tpl['x'] = 0;
32648 $tpl['y'] = 0;
32649 $tpl['w'] = $tpl['box']['w'] ;
32650 $tpl['h'] = $tpl['box']['h'] ;
32651 if ($crop_w) { $tpl['box']['w'] = $crop_w; }
32652 if ($crop_h) { $tpl['box']['h'] = $crop_h; }
32653 if (isset($crop_x)) { $tpl['box']['x'] = $crop_x; }
32654 if (isset($crop_y)) {$tpl['box']['y'] = $tpl['h'] - $crop_y - $crop_h ; }
32655
32656 $page =& $parser->pages[$parser->pageno];
32657 // fix for rotated pages
32658 $rotation = $parser->getPageRotation($pageno);
32659
32660 if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0 && $tpl['box']['w'] == $tpl['w']) {
32661 $steps = $angle / 90;
32662
32663 $_w = $tpl['w'];
32664 $_h = $tpl['h'];
32665 $tpl['w'] = $steps % 2 == 0 ? $_w : $_h;
32666 $tpl['h'] = $steps % 2 == 0 ? $_h : $_w;
32667 if ($steps % 2 != 0) {
32668 $x = $y = ($steps == 1 || $steps == -3) ? $tpl['h'] : $tpl['w'];
32669 } else {
32670 $x = $tpl['w'];
32671 $y = $tpl['h'];
32672 }
32673 $cx=($x/2+$tpl['box']['x'])*_MPDFK;
32674 $cy=($y/2+$tpl['box']['y'])*_MPDFK;
32675 $angle*=-1;
32676 $angle*=M_PI/180;
32677 $c=cos($angle);
32678 $s=sin($angle);
32679 $tpl['box']['w'] = $tpl['w'] ;
32680 $tpl['box']['h'] = $tpl['h'] ;
32681 $tpl['buffer'] = sprintf('q %.5F %.5F %.5F %.5F %.2F %.2F cm 1 0 0 1 %.2F %.2F cm %s Q',$c,$s,-$s,$c,$cx,$cy,-$cx,-$cy, $tpl['buffer']);
32682 }
32683 return $this->tpl;
32684 }
32685 function UseTemplate($tplidx, $_x=null, $_y=null, $_w=0, $_h=0) {
32686 if (!isset($this->tpls[$tplidx]))
32687 $this->Error("Template does not exist!");
32688 if($this->state==0) { $this->AddPage(); }
32689 $out = 'q 0 J 1 w 0 j 0 G'."\n"; // reset standard values
32690 $x = $this->tpls[$tplidx]['x'];
32691 $y = $this->tpls[$tplidx]['y'];
32692 $w = $this->tpls[$tplidx]['w'];
32693 $h = $this->tpls[$tplidx]['h'];
32694 if ($_x == null) { $_x = $x; }
32695 if ($_y == null) { $_y = $y; }
32696 if ($_x === -1) { $_x = $this->x; }
32697 if ($_y === -1) { $_y = $this->y; }
32698
32699 $wh = $this->getTemplateSize($tplidx,$_w,$_h);
32700 $_w = $wh['w'];
32701 $_h = $wh['h'];
32702 $out .= sprintf("q %.4F 0 0 %.4F %.2F %.2F cm", ($_w/$this->tpls[$tplidx]['box']['w']), ($_h/$this->tpls[$tplidx]['box']['h']), $_x*_MPDFK, ($this->h-($_y+$_h))*_MPDFK)."\n";
32703 $out .= $this->tplprefix.$tplidx." Do Q\n";
32704
32705 $s = array("w" => $_w, "h" => $_h);
32706 $out .= "Q\n";
32707 $this->pages[$this->page] = $out . $this->pages[$this->page];
32708 return $s;
32709 }
32710 function SetPageTemplate($tplidx='') {
32711 if (!isset($this->tpls[$tplidx])) {
32712 $this->pageTemplate = '';
32713 return false;
32714 }
32715 $this->pageTemplate = $tplidx;
32716 }
32717 function SetDocTemplate($file='', $continue=0) {
32718 $this->docTemplate = $file;
32719 $this->docTemplateContinue = $continue;
32720 }
32721 /*-- END IMPORTS --*/
32722
32723
32724 /* ---------------------------------------------- */
32725 /* ---------------------------------------------- */
32726 /* ---------------------------------------------- */
32727 /* ---------------------------------------------- */
32728 /* ---------------------------------------------- */
32729
32730 // JAVASCRIPT
32731 function _set_object_javascript ($string) {
32732 $this->_newobj();
32733 $this->_out('<<');
32734 $this->_out('/S /JavaScript ');
32735 $this->_out('/JS '.$this->_textstring($string));
32736 $this->_out('>>');
32737 $this->_out('endobj');
32738 }
32739
32740 function SetJS($script) {
32741 $this->js = $script;
32742 }
32743
32744
32745
32746
32747 }//end of Class
32748
32749
32750
32751
32752 ?>