PluginProbe
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin / 1.7
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin v1.7
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.7, at mpdf/mpdf.php

32,770 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: 5.7.1 based on *
6 // FPDF by Olivier PLATHEY *
7 // HTML2FPDF by Renato Coelho *
8 // Date: 2013-09-01 *
9 // Author: Ian Back <ianb@bpm1.com> *
10 // License: GPL *
11 // *
12 // Changes: See changelog.txt *
13 // ******************************************************************************
14
15
16 define('mPDF_VERSION','5.7.1');
17
18 //Scale factor
19 define('_MPDFK', (72/25.4));
20
21 /*-- HTML-CSS --*/
22 define('AUTOFONT_CJK',1);
23 define('AUTOFONT_THAIVIET',2);
24 define('AUTOFONT_RTL',4);
25 define('AUTOFONT_INDIC',8);
26 define('AUTOFONT_ALL',15);
27
28 define('_BORDER_ALL',15);
29 define('_BORDER_TOP',8);
30 define('_BORDER_RIGHT',4);
31 define('_BORDER_BOTTOM',2);
32 define('_BORDER_LEFT',1);
33 /*-- END HTML-CSS --*/
34
35 if (!defined('_MPDF_PATH')) define('_MPDF_PATH', dirname(preg_replace('/\\\\/','/',__FILE__)) . '/');
36 if (!defined('_MPDF_URI')) define('_MPDF_URI',_MPDF_PATH);
37
38 require_once(_MPDF_PATH.'includes/functions.php');
39 require_once(_MPDF_PATH.'config_cp.php');
40
41 if (!defined('_JPGRAPH_PATH')) define("_JPGRAPH_PATH", _MPDF_PATH.'jpgraph/');
42
43 if (!defined('_MPDF_TEMP_PATH')) define("_MPDF_TEMP_PATH", _MPDF_PATH.'tmp/');
44
45 if (!defined('_MPDF_TTFONTPATH')) { define('_MPDF_TTFONTPATH',_MPDF_PATH.'ttfonts/'); }
46 if (!defined('_MPDF_TTFONTDATAPATH')) { define('_MPDF_TTFONTDATAPATH',_MPDF_PATH.'ttfontdata/'); }
47
48 $errorlevel=error_reporting();
49 $errorlevel=error_reporting($errorlevel & ~E_NOTICE);
50
51 //error_reporting(E_ALL);
52
53 if(function_exists("date_default_timezone_set")) {
54 if (ini_get("date.timezone")=="") { date_default_timezone_set("Europe/London"); }
55 }
56 if (!function_exists("mb_strlen")) { die("Error - mPDF requires mb_string functions. Ensure that PHP is compiled with php_mbstring.dll enabled."); }
57
58 if (!defined('PHP_VERSION_ID')) {
59 $version = explode('.', PHP_VERSION);
60 define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
61 }
62 // Machine dependent number of bytes used to pack "double" into binary (used in cacheTables)
63 $test = pack("d", 134455.474557333333666);
64 define("_DSIZE", strlen($test));
65
66 class mPDF
67 {
68
69 ///////////////////////////////
70 // EXTERNAL (PUBLIC) VARIABLES
71 // Define these in config.php
72 ///////////////////////////////
73 var $CJKforceend; // mPDF 5.6.40
74 // mPDF 5.6.34
75 var $h2bookmarks;
76 var $h2toc;
77 var $decimal_align; // mPDF 5.6.13
78 var $margBuffer; // mPDF 5.4.04
79 var $splitTableBorderWidth; // mPDF 5.4.16
80
81 var $cacheTables;
82 var $bookmarkStyles;
83 var $useActiveForms;
84
85 var $repackageTTF;
86 var $allowCJKorphans;
87 var $allowCJKoverflow;
88
89 var $useKerning;
90 var $restrictColorSpace;
91 var $bleedMargin;
92 var $crossMarkMargin;
93 var $cropMarkMargin;
94 var $cropMarkLength;
95 var $nonPrintMargin;
96
97 var $PDFX;
98 var $PDFXauto;
99
100 var $PDFA;
101 var $PDFAauto;
102 var $ICCProfile;
103
104 var $printers_info;
105 var $iterationCounter;
106 var $smCapsScale;
107 var $smCapsStretch;
108
109 var $backupSubsFont;
110 var $backupSIPFont;
111 var $debugfonts;
112 var $useAdobeCJK;
113 var $percentSubset;
114 var $maxTTFFilesize;
115 var $BMPonly;
116
117 var $tableMinSizePriority;
118
119 var $dpi;
120 var $watermarkImgAlphaBlend;
121 var $watermarkImgBehind;
122 var $justifyB4br;
123 var $packTableData;
124 var $pgsIns;
125 var $simpleTables;
126 var $enableImports;
127
128 var $debug;
129 var $showStats;
130 var $setAutoTopMargin;
131 var $setAutoBottomMargin;
132 var $autoMarginPadding;
133 var $collapseBlockMargins;
134 var $falseBoldWeight;
135 var $normalLineheight;
136 var $progressBar;
137 var $incrementFPR1;
138 var $incrementFPR2;
139 var $incrementFPR3;
140 var $incrementFPR4;
141
142 var $SHYlang;
143 var $SHYleftmin;
144 var $SHYrightmin;
145 var $SHYcharmin;
146 var $SHYcharmax;
147 var $SHYlanguages;
148 // PageNumber Conditional Text
149 var $pagenumPrefix;
150 var $pagenumSuffix;
151 var $nbpgPrefix;
152 var $nbpgSuffix;
153 var $showImageErrors;
154 var $allow_output_buffering;
155 var $autoPadding;
156 var $useGraphs;
157 var $autoFontGroupSize;
158 var $tabSpaces;
159 var $useLang;
160 var $restoreBlockPagebreaks;
161 var $watermarkTextAlpha;
162 var $watermarkImageAlpha;
163 var $watermark_size;
164 var $watermark_pos;
165 var $annotSize;
166 var $annotMargin;
167 var $annotOpacity;
168 var $title2annots;
169 var $keepColumns;
170 var $keep_table_proportions;
171 var $ignore_table_widths;
172 var $ignore_table_percents;
173 var $list_align_style;
174 var $list_number_suffix;
175 var $useSubstitutions;
176 var $CSSselectMedia;
177
178 var $forcePortraitHeaders;
179 var $forcePortraitMargins;
180 var $displayDefaultOrientation;
181 var $ignore_invalid_utf8;
182 var $allowedCSStags;
183 var $onlyCoreFonts;
184 var $allow_charset_conversion;
185
186 var $jSWord;
187 var $jSmaxChar;
188 var $jSmaxCharLast;
189 var $jSmaxWordLast;
190
191 var $max_colH_correction;
192
193
194 var $table_error_report;
195 var $table_error_report_param;
196 var $biDirectional;
197 var $text_input_as_HTML;
198 var $anchor2Bookmark;
199 var $list_indent_first_level;
200 var $shrink_tables_to_fit;
201
202 var $allow_html_optional_endtags;
203
204 var $img_dpi;
205
206 var $defaultheaderfontsize;
207 var $defaultheaderfontstyle;
208 var $defaultheaderline;
209 var $defaultfooterfontsize;
210 var $defaultfooterfontstyle;
211 var $defaultfooterline;
212 var $header_line_spacing;
213 var $footer_line_spacing;
214
215 var $pregUHCchars;
216 var $pregSJISchars;
217 var $pregCJKchars;
218 var $pregASCIIchars1;
219 var $pregASCIIchars2;
220 var $pregASCIIchars3;
221 var $pregVIETchars;
222 var $pregVIETPluschars;
223
224 var $pregRTLchars;
225 var $pregHEBchars;
226 var $pregARABICchars;
227 var $pregNonARABICchars;
228 // INDIC
229 var $pregHIchars;
230 var $pregBNchars;
231 var $pregPAchars;
232 var $pregGUchars;
233 var $pregORchars;
234 var $pregTAchars;
235 var $pregTEchars;
236 var $pregKNchars;
237 var $pregMLchars;
238 var $pregSHchars;
239 var $pregINDextra;
240
241 var $mirrorMargins;
242 var $default_lineheight_correction;
243 var $watermarkText;
244 var $watermarkImage;
245 var $showWatermarkText;
246 var $showWatermarkImage;
247
248 var $fontsizes;
249
250 // Aliases for backward compatability
251 var $UnvalidatedText; // alias = $watermarkText
252 var $TopicIsUnvalidated; // alias = $showWatermarkText
253 var $useOddEven; // alias = $mirrorMargins
254 var $useSubstitutionsMB; // alias = $useSubstitutions
255
256
257
258 //////////////////////
259 // CLASS OBJECTS
260 //////////////////////
261 var $cssmgr;
262 var $grad;
263 var $bmp;
264 var $wmf;
265 var $tocontents;
266 var $form;
267 var $directw;
268
269 //////////////////////
270 // INTERNAL VARIABLES
271 //////////////////////
272 var $writingToC; // mPDF 5.6.38
273 // mPDF 5.6.01
274 var $layers;
275 var $current_layer;
276 var $open_layer_pane;
277 var $decimal_offset; // mPDF 5.6.13
278 var $inMeter; // mPDF 5.5.09
279
280 var $CJKleading;
281 var $CJKfollowing;
282 var $CJKoverflow;
283
284 var $textshadow;
285
286 var $colsums;
287 var $spanborder;
288 var $spanborddet;
289
290 var $visibility;
291
292 var $useRC128encryption;
293 var $uniqid;
294
295 var $kerning;
296 var $fixedlSpacing;
297 var $minwSpacing;
298 var $lSpacingCSS;
299 var $wSpacingCSS;
300
301 var $listDir;
302 var $spotColorIDs;
303 var $SVGcolors;
304 var $spotColors;
305 var $defTextColor;
306 var $defDrawColor;
307 var $defFillColor;
308
309 var $tableBackgrounds;
310 var $inlineDisplayOff;
311 var $kt_y00;
312 var $kt_p00;
313 var $upperCase;
314 var $checkSIP;
315 var $checkSMP;
316 var $checkCJK;
317 var $tableCJK;
318
319 var $watermarkImgAlpha;
320 var $PDFAXwarnings;
321 var $MetadataRoot;
322 var $OutputIntentRoot;
323 var $InfoRoot;
324 var $current_filename;
325 var $parsers;
326 var $current_parser;
327 var $_obj_stack;
328 var $_don_obj_stack;
329 var $_current_obj_id;
330 var $tpls;
331 var $tpl;
332 var $tplprefix;
333 var $_res;
334
335 var $pdf_version;
336 var $noImageFile;
337 var $lastblockbottommargin;
338 var $baselineC;
339 var $subPos;
340 var $subArrMB;
341 var $ReqFontStyle;
342 var $tableClipPath ;
343 var $forceExactLineheight;
344 var $listOcc;
345
346 var $fullImageHeight;
347 var $inFixedPosBlock; // Internal flag for position:fixed block
348 var $fixedPosBlock; // Buffer string for position:fixed block
349 var $fixedPosBlockDepth;
350 var $fixedPosBlockBBox;
351 var $fixedPosBlockSave;
352 var $maxPosL;
353 var $maxPosR;
354
355 var $loaded;
356
357 var $extraFontSubsets;
358 var $docTemplateStart; // Internal flag for page (page no. -1) that docTemplate starts on
359 var $time0;
360
361 // Classes
362 var $indic;
363 var $barcode;
364
365 var $SHYpatterns;
366 var $loadedSHYpatterns;
367 var $loadedSHYdictionary;
368 var $SHYdictionary;
369 var $SHYdictionaryWords;
370
371 var $spanbgcolorarray;
372 var $default_font;
373 var $list_lineheight;
374 var $headerbuffer;
375 var $lastblocklevelchange;
376 var $nestedtablejustfinished;
377 var $linebreakjustfinished;
378 var $cell_border_dominance_L;
379 var $cell_border_dominance_R;
380 var $cell_border_dominance_T;
381 var $cell_border_dominance_B;
382 var $table_keep_together;
383 var $plainCell_properties;
384 var $inherit_lineheight;
385 var $listitemtype;
386 var $shrin_k1;
387 var $outerfilled;
388
389 var $blockContext;
390 var $floatDivs;
391
392
393 var $patterns;
394 var $pageBackgrounds;
395
396 var $bodyBackgroundGradient;
397 var $bodyBackgroundImage;
398 var $bodyBackgroundColor;
399
400 var $writingHTMLheader; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
401 var $writingHTMLfooter;
402 var $autoFontGroups;
403 var $angle;
404
405 var $gradients;
406
407 var $kwt_Reference;
408 var $kwt_BMoutlines;
409 var $kwt_toc;
410
411 var $tbrot_Reference;
412 var $tbrot_BMoutlines;
413 var $tbrot_toc;
414
415 var $col_Reference;
416 var $col_BMoutlines;
417 var $col_toc;
418
419 var $currentGraphId;
420 var $graphs;
421
422 var $floatbuffer;
423 var $floatmargins;
424
425 var $bullet;
426 var $bulletarray;
427
428 var $rtlAsArabicFarsi; // DEPRACATED
429
430 var $currentLang;
431 var $default_lang;
432 var $default_available_fonts;
433 var $pageTemplate;
434 var $docTemplate;
435 var $docTemplateContinue;
436
437 var $arabGlyphs;
438 var $arabHex;
439 var $persianGlyphs;
440 var $persianHex;
441 var $arabVowels;
442 var $arabPrevLink;
443 var $arabNextLink;
444
445
446 var $formobjects; // array of Form Objects for WMF
447 var $InlineProperties;
448 var $InlineAnnots;
449 var $ktAnnots;
450 var $tbrot_Annots;
451 var $kwt_Annots;
452 var $columnAnnots;
453 var $columnForms;
454
455 var $PageAnnots;
456
457 var $pageDim; // Keep track of page wxh for orientation changes - set in _beginpage, used in _putannots
458
459 var $breakpoints;
460
461 var $tableLevel;
462 var $tbctr;
463 var $innermostTableLevel;
464 var $saveTableCounter;
465 var $cellBorderBuffer;
466
467 var $saveHTMLFooter_height;
468 var $saveHTMLFooterE_height;
469
470 var $firstPageBoxHeader;
471 var $firstPageBoxHeaderEven;
472 var $firstPageBoxFooter;
473 var $firstPageBoxFooterEven;
474
475 var $page_box;
476 var $show_marks; // crop or cross marks
477
478 var $basepathIsLocal;
479
480 var $use_kwt;
481 var $kwt;
482 var $kwt_height;
483 var $kwt_y0;
484 var $kwt_x0;
485 var $kwt_buffer;
486 var $kwt_Links;
487 var $kwt_moved;
488 var $kwt_saved;
489
490 var $PageNumSubstitutions;
491
492 var $table_borders_separate;
493 var $base_table_properties;
494 var $borderstyles;
495
496 var $listjustfinished;
497 var $blockjustfinished;
498
499 var $orig_bMargin;
500 var $orig_tMargin;
501 var $orig_lMargin;
502 var $orig_rMargin;
503 var $orig_hMargin;
504 var $orig_fMargin;
505
506 var $pageheaders;
507 var $pagefooters;
508
509 var $pageHTMLheaders;
510 var $pageHTMLfooters;
511
512 var $saveHTMLHeader;
513 var $saveHTMLFooter;
514
515 var $HTMLheaderPageLinks;
516 var $HTMLheaderPageAnnots;
517 var $HTMLheaderPageForms;
518
519 // See config_fonts.php for these next 5 values
520 var $available_unifonts;
521 var $sans_fonts;
522 var $serif_fonts;
523 var $mono_fonts;
524 var $defaultSubsFont;
525
526 // List of ALL available CJK fonts (incl. styles) (Adobe add-ons) hw removed
527 var $available_CJK_fonts;
528
529 var $HTMLHeader;
530 var $HTMLFooter;
531 var $HTMLHeaderE;
532 var $HTMLFooterE;
533 var $bufferoutput;
534
535 var $showdefaultpagenos; // DEPRACATED -left for backward compatability
536
537
538 // CJK fonts
539 var $Big5_widths;
540 var $GB_widths;
541 var $SJIS_widths;
542 var $UHC_widths;
543
544 // SetProtection
545 var $encrypted; //whether document is protected
546 var $Uvalue; //U entry in pdf document
547 var $Ovalue; //O entry in pdf document
548 var $Pvalue; //P entry in pdf document
549 var $enc_obj_id; //encryption object id
550 var $last_rc4_key; //last RC4 key encrypted (cached for optimisation)
551 var $last_rc4_key_c; //last RC4 computed key
552 var $encryption_key;
553 var $padding; //used for encryption
554
555
556 // Bookmark
557 var $BMoutlines;
558 var $OutlineRoot;
559 // INDEX
560 var $ColActive;
561 var $Reference;
562 var $CurrCol;
563 var $NbCol;
564 var $y0; //Top ordinate of columns
565 var $ColL;
566 var $ColWidth;
567 var $ColGap;
568 // COLUMNS
569 var $ColR;
570 var $ChangeColumn;
571 var $columnbuffer;
572 var $ColDetails;
573 var $columnLinks;
574 var $colvAlign;
575 // Substitutions
576 var $substitute; // Array of substitution strings e.g. <ttz>112</ttz>
577 var $entsearch; // Array of HTML entities (>ASCII 127) to substitute
578 var $entsubstitute; // Array of substitution decimal unicode for the Hi entities
579
580
581 // Default values if no style sheet offered (cf. http://www.w3.org/TR/CSS21/sample.html)
582 var $defaultCSS;
583
584 var $linemaxfontsize;
585 var $lineheight_correction;
586 var $lastoptionaltag; // Save current block item which HTML specifies optionsl endtag
587 var $pageoutput;
588 var $charset_in;
589 var $blk;
590 var $blklvl;
591 var $ColumnAdjust;
592 var $ws; // Word spacing
593 var $HREF;
594 var $pgwidth;
595 var $fontlist;
596 var $oldx;
597 var $oldy;
598 var $B;
599 var $U; //underlining flag
600 var $S; // SmallCaps flag
601 var $I;
602
603 var $tdbegin;
604 var $table;
605 var $cell;
606 var $col;
607 var $row;
608
609 var $divbegin;
610 var $divalign;
611 var $divwidth;
612 var $divheight;
613 var $divrevert;
614 var $spanbgcolor;
615
616 var $spanlvl;
617 var $listlvl;
618 var $listnum;
619 var $listtype;
620 var $listoccur;
621 var $listlist;
622 var $listitem;
623
624 var $pjustfinished;
625 var $ignorefollowingspaces;
626 var $SUP;
627 var $SUB;
628 var $SMALL;
629 var $BIG;
630 var $toupper;
631 var $tolower;
632 var $capitalize;
633 var $dash_on;
634 var $dotted_on;
635 var $strike;
636
637 var $textbuffer;
638 var $currentfontstyle;
639 var $currentfontfamily;
640 var $currentfontsize;
641 var $colorarray;
642 var $bgcolorarray;
643 var $internallink;
644 var $enabledtags;
645
646 var $lineheight;
647 var $basepath;
648 var $textparam;
649
650 var $specialcontent;
651 var $selectoption;
652 var $objectbuffer;
653
654 // Table Rotation
655 var $table_rotate;
656 var $tbrot_maxw;
657 var $tbrot_maxh;
658 var $tablebuffer;
659 var $tbrot_align;
660 var $tbrot_Links;
661
662 var $divbuffer; // Buffer used when keeping DIV on one page
663 var $keep_block_together; // Keep a Block from page-break-inside: avoid
664 var $ktLinks; // Keep-together Block links array
665 var $ktBlock; // Keep-together Block array
666 var $ktForms;
667 var $ktReference;
668 var $ktBMoutlines;
669 var $_kttoc;
670
671 var $tbrot_y0;
672 var $tbrot_x0;
673 var $tbrot_w;
674 var $tbrot_h;
675
676 var $mb_enc;
677 var $directionality;
678
679 var $extgstates; // Used for alpha channel - Transparency (Watermark)
680 var $mgl;
681 var $mgt;
682 var $mgr;
683 var $mgb;
684
685 var $tts;
686 var $ttz;
687 var $tta;
688
689 var $headerDetails;
690 var $footerDetails;
691
692 // Best to alter the below variables using default stylesheet above
693 var $page_break_after_avoid;
694 var $margin_bottom_collapse;
695 var $list_indent;
696 var $list_align;
697 var $list_margin_bottom;
698 var $default_font_size; // in pts
699 var $original_default_font_size; // used to save default sizes when using table default
700 var $original_default_font;
701 var $watermark_font;
702 var $defaultAlign;
703
704 // TABLE
705 var $defaultTableAlign;
706 var $tablethead;
707 var $thead_font_weight;
708 var $thead_font_style;
709 var $thead_font_smCaps;
710 var $thead_valign_default;
711 var $thead_textalign_default;
712 var $tabletfoot;
713 var $tfoot_font_weight;
714 var $tfoot_font_style;
715 var $tfoot_font_smCaps;
716 var $tfoot_valign_default;
717 var $tfoot_textalign_default;
718
719 var $trow_text_rotate;
720
721 var $cellPaddingL;
722 var $cellPaddingR;
723 var $cellPaddingT;
724 var $cellPaddingB;
725 var $table_lineheight;
726 var $table_border_attr_set;
727 var $table_border_css_set;
728
729 var $shrin_k; // factor with which to shrink tables - used internally - do not change
730 var $shrink_this_table_to_fit; // 0 or false to disable; value (if set) gives maximum factor to reduce fontsize
731 var $MarginCorrection; // corrects for OddEven Margins
732 var $margin_footer;
733 var $margin_header;
734
735 var $tabletheadjustfinished;
736 var $usingCoreFont;
737 var $charspacing;
738
739 //Private properties FROM FPDF
740 var $DisplayPreferences;
741 var $flowingBlockAttr;
742 var $page; //current page number
743 var $n; //current object number
744 var $offsets; //array of object offsets
745 var $buffer; //buffer holding in-memory PDF
746 var $pages; //array containing pages
747 var $state; //current document state
748 var $compress; //compression flag
749 var $DefOrientation; //default orientation
750 var $CurOrientation; //current orientation
751 var $OrientationChanges; //array indicating orientation changes
752 var $k; //scale factor (number of points in user unit)
753 var $fwPt;
754 var $fhPt; //dimensions of page format in points
755 var $fw;
756 var $fh; //dimensions of page format in user unit
757 var $wPt;
758 var $hPt; //current dimensions of page in points
759 var $w;
760 var $h; //current dimensions of page in user unit
761 var $lMargin; //left margin
762 var $tMargin; //top margin
763 var $rMargin; //right margin
764 var $bMargin; //page break margin
765 var $cMarginL; //cell margin Left
766 var $cMarginR; //cell margin Right
767 var $cMarginT; //cell margin Left
768 var $cMarginB; //cell margin Right
769 var $DeflMargin; //Default left margin
770 var $DefrMargin; //Default right margin
771 var $x;
772 var $y; //current position in user unit for cell positioning
773 var $lasth; //height of last cell printed
774 var $LineWidth; //line width in user unit
775 var $CoreFonts; //array of standard font names
776 var $fonts; //array of used fonts
777 var $FontFiles; //array of font files
778 var $images; //array of used images
779 var $PageLinks; //array of links in pages
780 var $links; //array of internal links
781 var $FontFamily; //current font family
782 var $FontStyle; //current font style
783 var $CurrentFont; //current font info
784 var $FontSizePt; //current font size in points
785 var $FontSize; //current font size in user unit
786 var $DrawColor; //commands for drawing color
787 var $FillColor; //commands for filling color
788 var $TextColor; //commands for text color
789 var $ColorFlag; //indicates whether fill and text colors are different
790 var $autoPageBreak; //automatic page breaking
791 var $PageBreakTrigger; //threshold used to trigger page breaks
792 var $InFooter; //flag set when processing footer
793 var $InHTMLFooter;
794
795 var $processingFooter; //flag set when processing footer - added for columns
796 var $processingHeader; //flag set when processing header - added for columns
797 var $ZoomMode; //zoom display mode
798 var $LayoutMode; //layout display mode
799 var $title; //title
800 var $subject; //subject
801 var $author; //author
802 var $keywords; //keywords
803 var $creator; //creator
804
805 var $aliasNbPg; //alias for total number of pages
806 var $aliasNbPgGp; //alias for total number of pages in page group
807 var $aliasNbPgHex;
808 var $aliasNbPgGpHex;
809
810 var $ispre;
811
812 var $outerblocktags;
813 var $innerblocktags;
814
815
816 // **********************************
817 // **********************************
818 // **********************************
819 // **********************************
820 // **********************************
821 // **********************************
822 // **********************************
823 // **********************************
824 // **********************************
825
826 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') {
827
828 /*-- BACKGROUNDS --*/
829 if (!class_exists('grad', false)) { include(_MPDF_PATH.'classes/grad.php'); }
830 if (empty($this->grad)) { $this->grad = new grad($this); }
831 /*-- END BACKGROUNDS --*/
832 /*-- FORMS --*/
833 if (!class_exists('form', false)) { include(_MPDF_PATH.'classes/form.php'); }
834 if (empty($this->form)) { $this->form = new form($this); }
835 /*-- END FORMS --*/
836
837 $this->time0 = microtime(true);
838 //Some checks
839 $this->_dochecks();
840
841 // Set up Aliases for backwards compatability
842 $this->UnvalidatedText =& $this->watermarkText;
843 $this->TopicIsUnvalidated =& $this->showWatermarkText;
844 $this->AliasNbPg =& $this->aliasNbPg;
845 $this->AliasNbPgGp =& $this->aliasNbPgGp;
846 $this->BiDirectional =& $this->biDirectional;
847 $this->Anchor2Bookmark =& $this->anchor2Bookmark;
848 $this->KeepColumns =& $this->keepColumns;
849 $this->useOddEven =& $this->mirrorMargins;
850 $this->useSubstitutionsMB =& $this->useSubstitutions;
851
852 $this->writingToC = false; // mPDF 5.6.38
853 // mPDF 5.6.01
854 $this->layers = array();
855 $this->current_layer = 0;
856 $this->open_layer_pane = false;
857
858 $this->visibility='visible';
859
860 //Initialization of properties
861 $this->spotColors=array();
862 $this->spotColorIDs = array();
863 $this->tableBackgrounds = array();
864
865 $this->kt_y00 = '';
866 $this->kt_p00 = '';
867 $this->iterationCounter = false;
868 $this->BMPonly = array();
869 $this->page=0;
870 $this->n=2;
871 $this->buffer='';
872 $this->objectbuffer = array();
873 $this->pages=array();
874 $this->OrientationChanges=array();
875 $this->state=0;
876 $this->fonts=array();
877 $this->FontFiles=array();
878 $this->images=array();
879 $this->links=array();
880 $this->InFooter=false;
881 $this->processingFooter=false;
882 $this->processingHeader=false;
883 $this->lasth=0;
884 $this->FontFamily='';
885 $this->FontStyle='';
886 $this->FontSizePt=9;
887 $this->U=false;
888 // Small Caps
889 $this->upperCase = array();
890 $this->S = false;
891 $this->smCapsScale = 1;
892 $this->smCapsStretch = 100;
893 $this->margBuffer = 0; // mPDF 5.4.04
894 $this->inMeter = false; // mPDF 5.5.09
895 $this->decimal_offset = 0;
896
897 $this->defTextColor = $this->TextColor = $this->SetTColor($this->ConvertColor(0),true);
898 $this->defDrawColor = $this->DrawColor = $this->SetDColor($this->ConvertColor(0),true);
899 $this->defFillColor = $this->FillColor = $this->SetFColor($this->ConvertColor(255),true);
900
901 //SVG color names array
902 //http://www.w3schools.com/css/css_colornames.asp
903 $this->SVGcolors = array('antiquewhite'=>'#FAEBD7','aqua'=>'#00FFFF','aquamarine'=>'#7FFFD4','beige'=>'#F5F5DC','black'=>'#000000',
904 'blue'=>'#0000FF','brown'=>'#A52A2A','cadetblue'=>'#5F9EA0','chocolate'=>'#D2691E','cornflowerblue'=>'#6495ED','crimson'=>'#DC143C',
905 'darkblue'=>'#00008B','darkgoldenrod'=>'#B8860B','darkgreen'=>'#006400','darkmagenta'=>'#8B008B','darkorange'=>'#FF8C00',
906 'darkred'=>'#8B0000','darkseagreen'=>'#8FBC8F','darkslategray'=>'#2F4F4F','darkviolet'=>'#9400D3','deepskyblue'=>'#00BFFF',
907 'dodgerblue'=>'#1E90FF','firebrick'=>'#B22222','forestgreen'=>'#228B22','fuchsia'=>'#FF00FF','gainsboro'=>'#DCDCDC','gold'=>'#FFD700',
908 'gray'=>'#808080','green'=>'#008000','greenyellow'=>'#ADFF2F','hotpink'=>'#FF69B4','indigo'=>'#4B0082','khaki'=>'#F0E68C',
909 'lavenderblush'=>'#FFF0F5','lemonchiffon'=>'#FFFACD','lightcoral'=>'#F08080','lightgoldenrodyellow'=>'#FAFAD2','lightgreen'=>'#90EE90',
910 'lightsalmon'=>'#FFA07A','lightskyblue'=>'#87CEFA','lightslategray'=>'#778899','lightyellow'=>'#FFFFE0','lime'=>'#00FF00','limegreen'=>'#32CD32',
911 'magenta'=>'#FF00FF','maroon'=>'#800000','mediumaquamarine'=>'#66CDAA','mediumorchid'=>'#BA55D3','mediumseagreen'=>'#3CB371',
912 'mediumspringgreen'=>'#00FA9A','mediumvioletred'=>'#C71585','midnightblue'=>'#191970','mintcream'=>'#F5FFFA','moccasin'=>'#FFE4B5','navy'=>'#000080',
913 'olive'=>'#808000','orange'=>'#FFA500','orchid'=>'#DA70D6','palegreen'=>'#98FB98',
914 'palevioletred'=>'#D87093','peachpuff'=>'#FFDAB9','pink'=>'#FFC0CB','powderblue'=>'#B0E0E6','purple'=>'#800080',
915 'red'=>'#FF0000','royalblue'=>'#4169E1','salmon'=>'#FA8072','seagreen'=>'#2E8B57','sienna'=>'#A0522D','silver'=>'#C0C0C0','skyblue'=>'#87CEEB',
916 'slategray'=>'#708090','springgreen'=>'#00FF7F','steelblue'=>'#4682B4','tan'=>'#D2B48C','teal'=>'#008080','thistle'=>'#D8BFD8','turquoise'=>'#40E0D0',
917 'violetred'=>'#D02090','white'=>'#FFFFFF','yellow'=>'#FFFF00',
918 'aliceblue'=>'#f0f8ff', 'azure'=>'#f0ffff', 'bisque'=>'#ffe4c4', 'blanchedalmond'=>'#ffebcd', 'blueviolet'=>'#8a2be2', 'burlywood'=>'#deb887',
919 'chartreuse'=>'#7fff00', 'coral'=>'#ff7f50', 'cornsilk'=>'#fff8dc', 'cyan'=>'#00ffff', 'darkcyan'=>'#008b8b', 'darkgray'=>'#a9a9a9',
920 'darkgrey'=>'#a9a9a9', 'darkkhaki'=>'#bdb76b', 'darkolivegreen'=>'#556b2f', 'darkorchid'=>'#9932cc', 'darksalmon'=>'#e9967a',
921 'darkslateblue'=>'#483d8b', 'darkslategrey'=>'#2f4f4f', 'darkturquoise'=>'#00ced1', 'deeppink'=>'#ff1493', 'dimgray'=>'#696969',
922 'dimgrey'=>'#696969', 'floralwhite'=>'#fffaf0', 'ghostwhite'=>'#f8f8ff', 'goldenrod'=>'#daa520', 'grey'=>'#808080', 'honeydew'=>'#f0fff0',
923 'indianred'=>'#cd5c5c', 'ivory'=>'#fffff0', 'lavender'=>'#e6e6fa', 'lawngreen'=>'#7cfc00', 'lightblue'=>'#add8e6', 'lightcyan'=>'#e0ffff',
924 'lightgray'=>'#d3d3d3', 'lightgrey'=>'#d3d3d3', 'lightpink'=>'#ffb6c1', 'lightseagreen'=>'#20b2aa', 'lightslategrey'=>'#778899',
925 'lightsteelblue'=>'#b0c4de', 'linen'=>'#faf0e6', 'mediumblue'=>'#0000cd', 'mediumpurple'=>'#9370db', 'mediumslateblue'=>'#7b68ee',
926 'mediumturquoise'=>'#48d1cc', 'mistyrose'=>'#ffe4e1', 'navajowhite'=>'#ffdead', 'oldlace'=>'#fdf5e6', 'olivedrab'=>'#6b8e23', 'orangered'=>'#ff4500',
927 'palegoldenrod'=>'#eee8aa', 'paleturquoise'=>'#afeeee', 'papayawhip'=>'#ffefd5', 'peru'=>'#cd853f', 'plum'=>'#dda0dd', 'rosybrown'=>'#bc8f8f',
928 'saddlebrown'=>'#8b4513', 'sandybrown'=>'#f4a460', 'seashell'=>'#fff5ee', 'slateblue'=>'#6a5acd', 'slategrey'=>'#708090', 'snow'=>'#fffafa',
929 'tomato'=>'#ff6347', 'violet'=>'#ee82ee', 'wheat'=>'#f5deb3', 'whitesmoke'=>'#f5f5f5', 'yellowgreen'=>'#9acd32');
930
931 $this->ColorFlag=false;
932 $this->extgstates = array();
933
934 $this->mb_enc='windows-1252';
935 $this->directionality='ltr';
936 $this->defaultAlign = 'L';
937 $this->defaultTableAlign = 'L';
938
939 $this->fixedPosBlockSave = array();
940 $this->extraFontSubsets = 0;
941
942 $this->SHYpatterns = array();
943 $this->loadedSHYdictionary = false;
944 $this->SHYdictionary = array();
945 $this->SHYdictionaryWords = array();
946 $this->blockContext = 1;
947 $this->floatDivs = array();
948 $this->DisplayPreferences='';
949
950 $this->patterns = array(); // Tiling patterns used for backgrounds
951 $this->pageBackgrounds = array();
952 $this->writingHTMLheader = false; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
953 $this->writingHTMLfooter = false; // internal flag - used both for writing HTMLHeaders/Footers and FixedPos block
954 $this->gradients = array();
955
956 $this->kwt_Reference = array();
957 $this->kwt_BMoutlines = array();
958 $this->kwt_toc = array();
959
960 $this->tbrot_Reference = array();
961 $this->tbrot_BMoutlines = array();
962 $this->tbrot_toc = array();
963
964 $this->col_Reference = array();
965 $this->col_BMoutlines = array();
966 $this->col_toc = array();
967 $this->graphs = array();
968
969 $this->pgsIns = array();
970 $this->PDFAXwarnings = array();
971 $this->inlineDisplayOff = false;
972 $this->kerning = false;
973 $this->lSpacingCSS = '';
974 $this->wSpacingCSS = '';
975 $this->fixedlSpacing = false;
976 $this->minwSpacing = 0;
977
978
979 $this->baselineC = 0.35; // Baseline for text
980 $this->noImageFile = str_replace("\\","/",dirname(__FILE__)) . '/includes/no_image.jpg';
981 $this->subPos = 0;
982 $this->forceExactLineheight = false;
983 $this->listOcc = 0;
984 $this->normalLineheight = 1.3;
985 // These are intended as configuration variables, and should be set in config.php - which will override these values;
986 // set here as failsafe as will cause an error if not defined
987 $this->incrementFPR1 = 10;
988 $this->incrementFPR2 = 10;
989 $this->incrementFPR3 = 10;
990 $this->incrementFPR4 = 10;
991
992 $this->fullImageHeight = false;
993 $this->floatbuffer = array();
994 $this->floatmargins = array();
995 $this->autoFontGroups = 0;
996 $this->formobjects=array(); // array of Form Objects for WMF
997 $this->InlineProperties=array();
998 $this->InlineAnnots=array();
999 $this->ktAnnots=array();
1000 $this->tbrot_Annots=array();
1001 $this->kwt_Annots=array();
1002 $this->columnAnnots=array();
1003 $this->pageDim=array();
1004 $this->breakpoints = array(); // used in columnbuffer
1005 $this->tableLevel=0;
1006 $this->tbctr=array(); // counter for nested tables at each level
1007 $this->page_box = array();
1008 $this->show_marks = ''; // crop or cross marks
1009 $this->kwt = false;
1010 $this->kwt_height = 0;
1011 $this->kwt_y0 = 0;
1012 $this->kwt_x0 = 0;
1013 $this->kwt_buffer = array();
1014 $this->kwt_Links = array();
1015 $this->kwt_moved = false;
1016 $this->kwt_saved = false;
1017 $this->PageNumSubstitutions = array();
1018 $this->base_table_properties=array();
1019 $this->borderstyles = array('inset','groove','outset','ridge','dotted','dashed','solid','double');
1020 $this->tbrot_align = 'C';
1021 $this->pageheaders=array();
1022 $this->pagefooters=array();
1023
1024 $this->pageHTMLheaders=array();
1025 $this->pageHTMLfooters=array();
1026 $this->HTMLheaderPageLinks = array();
1027 $this->HTMLheaderPageAnnots = array();
1028
1029 $this->ktForms = array();
1030 $this->HTMLheaderPageForms = array();
1031 $this->columnForms = array();
1032 $this->tbrotForms = array();
1033 $this->useRC128encryption = false;
1034 $this->uniqid = '';
1035
1036 $this->bufferoutput = false;
1037 $this->encrypted=false; //whether document is protected
1038 $this->BMoutlines=array();
1039 $this->ColActive=0; //Flag indicating that columns are on (the index is being processed)
1040 $this->Reference=array(); //Array containing the references
1041 $this->CurrCol=0; //Current column number
1042 $this->ColL = array(0); // Array of Left pos of columns - absolute - needs Margin correction for Odd-Even
1043 $this->ColR = array(0); // Array of Right pos of columns - absolute pos - needs Margin correction for Odd-Even
1044 $this->ChangeColumn = 0;
1045 $this->columnbuffer = array();
1046 $this->ColDetails = array(); // Keeps track of some column details
1047 $this->columnLinks = array(); // Cross references PageLinks
1048 $this->substitute = array(); // Array of substitution strings e.g. <ttz>112</ttz>
1049 $this->entsearch = array(); // Array of HTML entities (>ASCII 127) to substitute
1050 $this->entsubstitute = array(); // Array of substitution decimal unicode for the Hi entities
1051 $this->lastoptionaltag = '';
1052 $this->charset_in = '';
1053 $this->blk = array();
1054 $this->blklvl = 0;
1055 $this->tts = false;
1056 $this->ttz = false;
1057 $this->tta = false;
1058 $this->ispre=false;
1059
1060 $this->checkSIP = false;
1061 $this->checkSMP = false;
1062 $this->checkCJK = false;
1063 $this->tableCJK = false;
1064
1065 $this->headerDetails=array();
1066 $this->footerDetails=array();
1067 $this->page_break_after_avoid = false;
1068 $this->margin_bottom_collapse = false;
1069 $this->tablethead = 0;
1070 $this->tabletfoot = 0;
1071 $this->table_border_attr_set = 0;
1072 $this->table_border_css_set = 0;
1073 $this->shrin_k = 1.0;
1074 $this->shrink_this_table_to_fit = 0;
1075 $this->MarginCorrection = 0;
1076
1077 $this->tabletheadjustfinished = false;
1078 $this->usingCoreFont = false;
1079 $this->charspacing=0;
1080
1081 $this->autoPageBreak = true;
1082
1083 require(_MPDF_PATH.'config.php'); // config data
1084
1085 $this->_setPageSize($format, $orientation);
1086 $this->DefOrientation=$orientation;
1087
1088 $this->margin_header=$mgh;
1089 $this->margin_footer=$mgf;
1090
1091 $bmargin=$mgb;
1092
1093 $this->DeflMargin = $mgl;
1094 $this->DefrMargin = $mgr;
1095
1096 $this->orig_tMargin = $mgt;
1097 $this->orig_bMargin = $bmargin;
1098 $this->orig_lMargin = $this->DeflMargin;
1099 $this->orig_rMargin = $this->DefrMargin;
1100 $this->orig_hMargin = $this->margin_header;
1101 $this->orig_fMargin = $this->margin_footer;
1102
1103 if ($this->setAutoTopMargin=='pad') { $mgt += $this->margin_header; }
1104 if ($this->setAutoBottomMargin=='pad') { $mgb += $this->margin_footer; }
1105 $this->SetMargins($this->DeflMargin,$this->DefrMargin,$mgt); // sets l r t margin
1106 //Automatic page break
1107 $this->SetAutoPageBreak($this->autoPageBreak,$bmargin); // sets $this->bMargin & PageBreakTrigger
1108
1109 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
1110
1111 //Interior cell margin (1 mm) ? not used
1112 $this->cMarginL = 1;
1113 $this->cMarginR = 1;
1114 //Line width (0.2 mm)
1115 $this->LineWidth=.567/_MPDFK;
1116
1117 //To make the function Footer() work - replaces {nb} with page number
1118 $this->AliasNbPages();
1119 $this->AliasNbPageGroups();
1120
1121 $this->aliasNbPgHex = '{nbHEXmarker}';
1122 $this->aliasNbPgGpHex = '{nbpgHEXmarker}';
1123
1124 //Enable all tags as default
1125 $this->DisableTags();
1126 //Full width display mode
1127 $this->SetDisplayMode(100); // fullwidth? 'fullpage'
1128 //Compression
1129 $this->SetCompression(true);
1130 //Set default display preferences
1131 $this->SetDisplayPreferences('');
1132
1133 // Font data
1134 require(_MPDF_PATH.'config_fonts.php');
1135 // Available fonts
1136 $this->available_unifonts = array();
1137 foreach ($this->fontdata AS $f => $fs) {
1138 if (isset($fs['R']) && $fs['R']) { $this->available_unifonts[] = $f; }
1139 if (isset($fs['B']) && $fs['B']) { $this->available_unifonts[] = $f.'B'; }
1140 if (isset($fs['I']) && $fs['I']) { $this->available_unifonts[] = $f.'I'; }
1141 if (isset($fs['BI']) && $fs['BI']) { $this->available_unifonts[] = $f.'BI'; }
1142 }
1143
1144 $this->default_available_fonts = $this->available_unifonts;
1145
1146 $optcore = false;
1147 $onlyCoreFonts = false;
1148 if (preg_match('/([\-+])aCJK/i',$mode, $m)) {
1149 preg_replace('/([\-+])aCJK/i','',$mode);
1150 if ($m[1]=='+') { $this->useAdobeCJK = true; }
1151 else { $this->useAdobeCJK = false; }
1152 }
1153
1154 if (strlen($mode)==1) {
1155 if ($mode=='s') { $this->percentSubset = 100; $mode = ''; }
1156 else if ($mode=='c') { $onlyCoreFonts = true; $mode = ''; }
1157 }
1158 else if (substr($mode,-2)=='-s') {
1159 $this->percentSubset = 100;
1160 $mode = substr($mode,0,strlen($mode)-2);
1161 }
1162 else if (substr($mode,-2)=='-c') {
1163 $onlyCoreFonts = true;
1164 $mode = substr($mode,0,strlen($mode)-2);
1165 }
1166 else if (substr($mode,-2)=='-x') {
1167 $optcore = true;
1168 $mode = substr($mode,0,strlen($mode)-2);
1169 }
1170
1171 // Autodetect if mode is a language_country string (en-GB or en_GB or en)
1172 if ((strlen($mode) == 5 && $mode != 'UTF-8') || strlen($mode) == 2) {
1173 list ($coreSuitable,$mpdf_pdf_unifonts) = GetLangOpts($mode, $this->useAdobeCJK);
1174 if ($coreSuitable && $optcore) { $onlyCoreFonts = true; }
1175 if ($mpdf_pdf_unifonts) {
1176 $this->RestrictUnicodeFonts($mpdf_pdf_unifonts);
1177 $this->default_available_fonts = $mpdf_pdf_unifonts;
1178 }
1179 $this->currentLang = $mode;
1180 $this->default_lang = $mode;
1181 }
1182
1183 $this->onlyCoreFonts = $onlyCoreFonts;
1184
1185 if ($this->onlyCoreFonts) {
1186 $this->setMBencoding('windows-1252'); // sets $this->mb_enc
1187 }
1188 else {
1189 $this->setMBencoding('UTF-8'); // sets $this->mb_enc
1190 }
1191 @mb_regex_encoding('UTF-8'); // required only for mb_ereg... and mb_split functions
1192
1193
1194 // Adobe CJK fonts
1195 $this->available_CJK_fonts = array('gb','big5','sjis','uhc','gbB','big5B','sjisB','uhcB','gbI','big5I','sjisI','uhcI',
1196 'gbBI','big5BI','sjisBI','uhcBI');
1197
1198
1199 //Standard fonts
1200 $this->CoreFonts=array('ccourier'=>'Courier','ccourierB'=>'Courier-Bold','ccourierI'=>'Courier-Oblique','ccourierBI'=>'Courier-BoldOblique',
1201 'chelvetica'=>'Helvetica','chelveticaB'=>'Helvetica-Bold','chelveticaI'=>'Helvetica-Oblique','chelveticaBI'=>'Helvetica-BoldOblique',
1202 'ctimes'=>'Times-Roman','ctimesB'=>'Times-Bold','ctimesI'=>'Times-Italic','ctimesBI'=>'Times-BoldItalic',
1203 'csymbol'=>'Symbol','czapfdingbats'=>'ZapfDingbats');
1204 $this->fontlist=array("ctimes","ccourier","chelvetica","csymbol","czapfdingbats");
1205
1206 // Substitutions
1207 $this->setHiEntitySubstitutions();
1208
1209 if ($this->onlyCoreFonts) {
1210 $this->useSubstitutions = true;
1211 $this->SetSubstitutions();
1212 }
1213 else { $this->useSubstitutions = false; }
1214
1215 /*-- HTML-CSS --*/
1216
1217 if (!class_exists('cssmgr', false)) { include(_MPDF_PATH .'classes/cssmgr.php'); }
1218 $this->cssmgr = new cssmgr($this);
1219 if (file_exists(_MPDF_PATH.'mpdf.css')) {
1220 $css = file_get_contents(_MPDF_PATH.'mpdf.css');
1221 $css2 = $this->cssmgr->ReadDefaultCSS($css);
1222 $this->defaultCSS = $this->cssmgr->array_merge_recursive_unique($this->defaultCSS,$css2);
1223 }
1224 /*-- END HTML-CSS --*/
1225
1226 if ($default_font=='') {
1227 if ($this->onlyCoreFonts) {
1228 if (in_array(strtolower($this->defaultCSS['BODY']['FONT-FAMILY']),$this->mono_fonts)) { $default_font = 'ccourier'; }
1229 else if (in_array(strtolower($this->defaultCSS['BODY']['FONT-FAMILY']),$this->sans_fonts)) { $default_font = 'chelvetica'; }
1230 else { $default_font = 'ctimes'; }
1231 }
1232 else { $default_font = $this->defaultCSS['BODY']['FONT-FAMILY']; }
1233 }
1234 if (!$default_font_size) {
1235 $mmsize = $this->ConvertSize($this->defaultCSS['BODY']['FONT-SIZE']);
1236 $default_font_size = $mmsize*(_MPDFK);
1237 }
1238
1239 if ($default_font) { $this->SetDefaultFont($default_font); }
1240 if ($default_font_size) { $this->SetDefaultFontSize($default_font_size); }
1241
1242 $this->SetLineHeight(); // lineheight is in mm
1243
1244 $this->SetFColor($this->ConvertColor(255));
1245 $this->HREF='';
1246 $this->oldy=-1;
1247 $this->B=0;
1248 $this->U=false;
1249 $this->S=false;
1250 $this->I=0;
1251
1252 $this->listlvl=0;
1253 $this->listnum=0;
1254 $this->listtype='';
1255 $this->listoccur=array();
1256 $this->listlist=array();
1257 $this->listitem=array();
1258
1259 $this->tdbegin=false;
1260 $this->table=array();
1261 $this->cell=array();
1262 $this->col=-1;
1263 $this->row=-1;
1264 $this->cellBorderBuffer = array();
1265
1266 $this->divbegin=false;
1267 $this->divalign='';
1268 $this->divwidth=0;
1269 $this->divheight=0;
1270 $this->spanbgcolor=false;
1271 $this->divrevert=false;
1272 $this->spanborder=false;
1273 $this->spanborddet=array();
1274
1275 $this->blockjustfinished=false;
1276 $this->listjustfinished=false;
1277 $this->ignorefollowingspaces = true; //in order to eliminate exceeding left-side spaces
1278 $this->toupper=false;
1279 $this->tolower=false;
1280 $this->capitalize=false;
1281 $this->dash_on=false;
1282 $this->dotted_on=false;
1283 $this->SUP=false;
1284 $this->SUB=false;
1285 $this->strike=false;
1286 $this->textshadow='';
1287
1288 $this->currentfontfamily='';
1289 $this->currentfontsize='';
1290 $this->currentfontstyle='';
1291 $this->colorarray=array();
1292 $this->spanbgcolorarray=array();
1293 $this->textbuffer=array();
1294 $this->internallink=array();
1295 $this->basepath = "";
1296
1297 $this->SetBasePath('');
1298
1299 $this->textparam = array();
1300
1301 $this->specialcontent = '';
1302 $this->selectoption = array();
1303
1304 /*-- IMPORTS --*/
1305
1306 $this->tpls = array();
1307 $this->tpl = 0;
1308 $this->tplprefix = "/TPL";
1309 $this->res = array();
1310 if ($this->enableImports) {
1311 $this->SetImportUse();
1312 }
1313 /*-- END IMPORTS --*/
1314
1315 if ($this->progressBar) { $this->StartProgressBarOutput($this->progressBar) ; } // *PROGRESS-BAR*
1316 }
1317
1318
1319 function _setPageSize($format, &$orientation) {
1320 //Page format
1321 if(is_string($format))
1322 {
1323 if ($format=='') { $format = 'A4'; }
1324 $pfo = 'P';
1325 if(preg_match('/([0-9a-zA-Z]*)-L/i',$format,$m)) { // e.g. A4-L = A4 landscape
1326 $format=$m[1];
1327 $pfo='L';
1328 }
1329 $format = $this->_getPageFormat($format);
1330 if (!$format) { $this->Error('Unknown page format: '.$format); }
1331 else { $orientation = $pfo; }
1332
1333 $this->fwPt=$format[0];
1334 $this->fhPt=$format[1];
1335 }
1336 else
1337 {
1338 if (!$format[0] || !$format[1]) { $this->Error('Invalid page format: '.$format[0].' '.$format[1]); }
1339 $this->fwPt=$format[0]*_MPDFK;
1340 $this->fhPt=$format[1]*_MPDFK;
1341 }
1342 $this->fw=$this->fwPt/_MPDFK;
1343 $this->fh=$this->fhPt/_MPDFK;
1344 //Page orientation
1345 $orientation=strtolower($orientation);
1346 if($orientation=='p' or $orientation=='portrait')
1347 {
1348 $orientation='P';
1349 $this->wPt=$this->fwPt;
1350 $this->hPt=$this->fhPt;
1351 }
1352 elseif($orientation=='l' or $orientation=='landscape')
1353 {
1354 $orientation='L';
1355 $this->wPt=$this->fhPt;
1356 $this->hPt=$this->fwPt;
1357 }
1358 else $this->Error('Incorrect orientation: '.$orientation);
1359 $this->CurOrientation=$orientation;
1360
1361 $this->w=$this->wPt/_MPDFK;
1362 $this->h=$this->hPt/_MPDFK;
1363 }
1364
1365 function _getPageFormat($format) {
1366 switch (strtoupper($format)) {
1367 case '4A0': {$format = array(4767.87,6740.79); break;}
1368 case '2A0': {$format = array(3370.39,4767.87); break;}
1369 case 'A0': {$format = array(2383.94,3370.39); break;}
1370 case 'A1': {$format = array(1683.78,2383.94); break;}
1371 case 'A2': {$format = array(1190.55,1683.78); break;}
1372 case 'A3': {$format = array(841.89,1190.55); break;}
1373 case 'A4': default: {$format = array(595.28,841.89); break;}
1374 case 'A5': {$format = array(419.53,595.28); break;}
1375 case 'A6': {$format = array(297.64,419.53); break;}
1376 case 'A7': {$format = array(209.76,297.64); break;}
1377 case 'A8': {$format = array(147.40,209.76); break;}
1378 case 'A9': {$format = array(104.88,147.40); break;}
1379 case 'A10': {$format = array(73.70,104.88); break;}
1380 case 'B0': {$format = array(2834.65,4008.19); break;}
1381 case 'B1': {$format = array(2004.09,2834.65); break;}
1382 case 'B2': {$format = array(1417.32,2004.09); break;}
1383 case 'B3': {$format = array(1000.63,1417.32); break;}
1384 case 'B4': {$format = array(708.66,1000.63); break;}
1385 case 'B5': {$format = array(498.90,708.66); break;}
1386 case 'B6': {$format = array(354.33,498.90); break;}
1387 case 'B7': {$format = array(249.45,354.33); break;}
1388 case 'B8': {$format = array(175.75,249.45); break;}
1389 case 'B9': {$format = array(124.72,175.75); break;}
1390 case 'B10': {$format = array(87.87,124.72); break;}
1391 case 'C0': {$format = array(2599.37,3676.54); break;}
1392 case 'C1': {$format = array(1836.85,2599.37); break;}
1393 case 'C2': {$format = array(1298.27,1836.85); break;}
1394 case 'C3': {$format = array(918.43,1298.27); break;}
1395 case 'C4': {$format = array(649.13,918.43); break;}
1396 case 'C5': {$format = array(459.21,649.13); break;}
1397 case 'C6': {$format = array(323.15,459.21); break;}
1398 case 'C7': {$format = array(229.61,323.15); break;}
1399 case 'C8': {$format = array(161.57,229.61); break;}
1400 case 'C9': {$format = array(113.39,161.57); break;}
1401 case 'C10': {$format = array(79.37,113.39); break;}
1402 case 'RA0': {$format = array(2437.80,3458.27); break;}
1403 case 'RA1': {$format = array(1729.13,2437.80); break;}
1404 case 'RA2': {$format = array(1218.90,1729.13); break;}
1405 case 'RA3': {$format = array(864.57,1218.90); break;}
1406 case 'RA4': {$format = array(609.45,864.57); break;}
1407 case 'SRA0': {$format = array(2551.18,3628.35); break;}
1408 case 'SRA1': {$format = array(1814.17,2551.18); break;}
1409 case 'SRA2': {$format = array(1275.59,1814.17); break;}
1410 case 'SRA3': {$format = array(907.09,1275.59); break;}
1411 case 'SRA4': {$format = array(637.80,907.09); break;}
1412 case 'LETTER': {$format = array(612.00,792.00); break;}
1413 case 'LEGAL': {$format = array(612.00,1008.00); break;}
1414 case 'LEDGER': {$format = array(279.00,432.00); break;}
1415 case 'TABLOID': {$format = array(279.00,432.00); break;}
1416 case 'EXECUTIVE': {$format = array(521.86,756.00); break;}
1417 case 'FOLIO': {$format = array(612.00,936.00); break;}
1418 case 'B': {$format=array(362.83,561.26 ); break;} // 'B' format paperback size 128x198mm
1419 case 'A': {$format=array(314.65,504.57 ); break;} // 'A' format paperback size 111x178mm
1420 case 'DEMY': {$format=array(382.68,612.28 ); break;} // 'Demy' format paperback size 135x216mm
1421 case 'ROYAL': {$format=array(433.70,663.30 ); break;} // 'Royal' format paperback size 153x234mm
1422 default: $format = false;
1423 }
1424 return $format;
1425 }
1426
1427
1428 /*-- PROGRESS-BAR --*/
1429 function StartProgressBarOutput($mode=1) {
1430 // must be relative path, or URI (not a file system path)
1431 if (!defined('_MPDF_URI')) {
1432 $this->progressBar = false;
1433 if ($this->debug) { $this->Error("You need to define _MPDF_URI to use the progress bar!"); }
1434 else return false;
1435 }
1436 $this->progressBar = $mode;
1437 if ($this->progbar_altHTML) {
1438 echo $this->progbar_altHTML;
1439 }
1440 else {
1441 echo '<html>
1442 <head>
1443 <title>mPDF File Progress</title>
1444 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1445 <link rel="stylesheet" type="text/css" href="'._MPDF_URI.'progbar.css" />
1446 </head>
1447 <body>
1448 <div class="main">
1449 <div class="heading">'.$this->progbar_heading.'</div>
1450 <div class="demo">
1451 ';
1452 if ($this->progressBar==2) { echo ' <table width="100%"><tr><td style="width: 50%;">
1453 <span class="barheading">Writing HTML code</span> <br/>
1454
1455 <div class="progressBar">
1456 <div id="element1" class="innerBar">&nbsp;</div>
1457 </div>
1458 <span class="code" id="box1"></span>
1459 </td><td style="width: 50%;">
1460 <span class="barheading">Autosizing elements</span> <br/>
1461 <div class="progressBar">
1462 <div id="element4" class="innerBar">&nbsp;</div>
1463 </div>
1464 <span class="code" id="box4"></span>
1465 <br/><br/>
1466 <span class="barheading">Writing Tables</span> <br/>
1467 <div class="progressBar">
1468 <div id="element7" class="innerBar">&nbsp;</div>
1469 </div>
1470 <span class="code" id="box7"></span>
1471 </td></tr>
1472 <tr><td><br /><br /></td><td></td></tr>
1473 <tr><td style="width: 50%;">
1474 '; }
1475 echo ' <span class="barheading">Writing PDF file</span> <br/>
1476 <div class="progressBar">
1477 <div id="element2" class="innerBar">&nbsp;</div>
1478 </div>
1479 <span class="code" id="box2"></span>
1480 ';
1481 if ($this->progressBar==2) { echo '
1482 </td><td style="width: 50%;">
1483 <span class="barheading">Memory usage</span> <br/>
1484 <div class="progressBar">
1485 <div id="element5" class="innerBar">&nbsp;</div>
1486 </div>
1487 <span id="box5">0</span> '.ini_get("memory_limit").'<br />
1488 <br/><br/>
1489 <span class="barheading">Memory usage (peak)</span> <br/>
1490 <div class="progressBar">
1491 <div id="element6" class="innerBar">&nbsp;</div>
1492 </div>
1493 <span id="box6">0</span> '.ini_get("memory_limit").'<br />
1494 </td></tr>
1495 </table>
1496 '; }
1497 echo ' <br/><br/>
1498 <span id="box3"></span>
1499
1500 </div>
1501 ';
1502 }
1503 ob_flush();
1504 flush();
1505 }
1506
1507 function UpdateProgressBar($el,$val,$txt='') {
1508 // $val should be a string - 5 = actual value, +15 = increment
1509
1510 if ($this->progressBar<2) {
1511 if ($el>3) { return; }
1512 else if ($el ==1) { $el = 2; }
1513 }
1514 echo '<script type="text/javascript">';
1515 if ($val) { echo ' document.getElementById(\'element'.$el.'\').style.width=\''.$val.'%\'; '; }
1516 if ($txt) { echo ' document.getElementById(\'box'.$el.'\').innerHTML=\''.$txt.'\'; '; }
1517 if ($this->progressBar==2) {
1518 $m = round(memory_get_usage(true)/1048576);
1519 $m2 = round(memory_get_peak_usage(true)/1048576);
1520 $mem = $m * 100 / (ini_get("memory_limit")+0);
1521 $mem2 = $m2 * 100 / (ini_get("memory_limit")+0);
1522 echo ' document.getElementById(\'element5\').style.width=\''.$mem.'%\'; ';
1523 echo ' document.getElementById(\'element6\').style.width=\''.$mem2.'%\'; ';
1524 echo ' document.getElementById(\'box5\').innerHTML=\''.$m.'MB / \'; ';
1525 echo ' document.getElementById(\'box6\').innerHTML=\''.$m2.'MB / \'; ';
1526 }
1527 echo '</script>'."\n";
1528 ob_flush();
1529 flush();
1530 }
1531 /*-- END PROGRESS-BAR --*/
1532
1533
1534
1535 function RestrictUnicodeFonts($res) {
1536 // $res = array of (Unicode) fonts to restrict to: e.g. norasi|norasiB - language specific
1537 if (count($res)) { // Leave full list of available fonts if passed blank array
1538 $this->available_unifonts = $res;
1539 }
1540 else { $this->available_unifonts = $this->default_available_fonts; }
1541 if (count($this->available_unifonts) == 0) { $this->available_unifonts[] = $this->default_available_fonts[0]; }
1542 $this->available_unifonts = array_values($this->available_unifonts);
1543 }
1544
1545
1546 function setMBencoding($enc) {
1547 if ($this->mb_enc != $enc) {
1548 $this->mb_enc = $enc;
1549 mb_internal_encoding($this->mb_enc);
1550 }
1551 }
1552
1553
1554 function SetMargins($left,$right,$top) {
1555 //Set left, top and right margins
1556 $this->lMargin=$left;
1557 $this->rMargin=$right;
1558 $this->tMargin=$top;
1559 }
1560
1561 function ResetMargins() {
1562 //ReSet left, top margins
1563 if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P' && $this->CurOrientation=='L') {
1564 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
1565 $this->tMargin=$this->orig_rMargin;
1566 $this->bMargin=$this->orig_lMargin;
1567 }
1568 else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS
1569 $this->tMargin=$this->orig_lMargin;
1570 $this->bMargin=$this->orig_rMargin;
1571 }
1572 $this->lMargin=$this->DeflMargin;
1573 $this->rMargin=$this->DefrMargin;
1574 $this->MarginCorrection = 0;
1575 $this->PageBreakTrigger=$this->h-$this->bMargin;
1576 }
1577 else if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
1578 $this->lMargin=$this->DefrMargin;
1579 $this->rMargin=$this->DeflMargin;
1580 $this->MarginCorrection = $this->DefrMargin-$this->DeflMargin;
1581
1582 }
1583 else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS
1584 $this->lMargin=$this->DeflMargin;
1585 $this->rMargin=$this->DefrMargin;
1586 if ($this->mirrorMargins) { $this->MarginCorrection = $this->DeflMargin-$this->DefrMargin; }
1587 }
1588 $this->x=$this->lMargin;
1589
1590 }
1591
1592 function SetLeftMargin($margin) {
1593 //Set left margin
1594 $this->lMargin=$margin;
1595 if($this->page>0 and $this->x<$margin) $this->x=$margin;
1596 }
1597
1598 function SetTopMargin($margin) {
1599 //Set top margin
1600 $this->tMargin=$margin;
1601 }
1602
1603 function SetRightMargin($margin) {
1604 //Set right margin
1605 $this->rMargin=$margin;
1606 }
1607
1608 function SetAutoPageBreak($auto,$margin=0) {
1609 //Set auto page break mode and triggering margin
1610 $this->autoPageBreak=$auto;
1611 $this->bMargin=$margin;
1612 $this->PageBreakTrigger=$this->h-$margin;
1613 }
1614
1615 function SetDisplayMode($zoom,$layout='continuous') {
1616 //Set display mode in viewer
1617 if($zoom=='fullpage' or $zoom=='fullwidth' or $zoom=='real' or $zoom=='default' or !is_string($zoom))
1618 $this->ZoomMode=$zoom;
1619 else
1620 $this->Error('Incorrect zoom display mode: '.$zoom);
1621 if($layout=='single' or $layout=='continuous' or $layout=='two' or $layout=='twoleft' or $layout=='tworight' or $layout=='default')
1622 $this->LayoutMode=$layout;
1623 else
1624 $this->Error('Incorrect layout display mode: '.$layout);
1625 }
1626
1627 function SetCompression($compress) {
1628 //Set page compression
1629 if(function_exists('gzcompress')) $this->compress=$compress;
1630 else $this->compress=false;
1631 }
1632
1633 function SetTitle($title) {
1634 //Title of document // Arrives as UTF-8
1635 $this->title = $title;
1636 }
1637
1638 function SetSubject($subject) {
1639 //Subject of document
1640 $this->subject= $subject;
1641 }
1642
1643 function SetAuthor($author) {
1644 //Author of document
1645 $this->author= $author;
1646 }
1647
1648 function SetKeywords($keywords) {
1649 //Keywords of document
1650 $this->keywords= $keywords;
1651 }
1652
1653 function SetCreator($creator) {
1654 //Creator of document
1655 $this->creator= $creator;
1656 }
1657
1658
1659 function SetAnchor2Bookmark($x) {
1660 $this->anchor2Bookmark = $x;
1661 }
1662
1663 function AliasNbPages($alias='{nb}') {
1664 //Define an alias for total number of pages
1665 $this->aliasNbPg=$alias;
1666 }
1667
1668 function AliasNbPageGroups($alias='{nbpg}') {
1669 //Define an alias for total number of pages in a group
1670 $this->aliasNbPgGp=$alias;
1671 }
1672
1673 function SetAlpha($alpha, $bm='Normal', $return=false, $mode='B') {
1674 // alpha: real value from 0 (transparent) to 1 (opaque)
1675 // bm: blend mode, one of the following:
1676 // Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn,
1677 // HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity
1678 // set alpha for stroking (CA) and non-stroking (ca) operations
1679 // mode determines F (fill) S (stroke) B (both)
1680 if (($this->PDFA || $this->PDFX) && $alpha!=1) {
1681 if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "Image opacity must be 100% (Opacity changed to 100%)"; }
1682 $alpha = 1;
1683 }
1684 $a = array('BM'=>'/'.$bm);
1685 if ($mode=='F' || $mode='B') $a['ca'] = $alpha;
1686 if ($mode=='S' || $mode='B') $a['CA'] = $alpha;
1687 $gs = $this->AddExtGState($a);
1688 if ($return) { return sprintf('/GS%d gs', $gs); }
1689 else { $this->_out(sprintf('/GS%d gs', $gs)); }
1690 }
1691
1692 function AddExtGState($parms) {
1693 $n = count($this->extgstates);
1694 // check if graphics state already exists
1695 for ($i=1; $i<=$n; $i++) {
1696 if (count($this->extgstates[$i]['parms']) == count($parms)) {
1697 $same = true;
1698 foreach($this->extgstates[$i]['parms'] AS $k=>$v) {
1699 if (!isset($parms[$k]) || $parms[$k] != $v) { $same = false; break; }
1700 }
1701 if ($same) { return $i; }
1702 }
1703 }
1704 $n++;
1705 $this->extgstates[$n]['parms'] = $parms;
1706 return $n;
1707 }
1708
1709 function SetVisibility($v) {
1710 if (($this->PDFA || $this->PDFX) && $this->visibility!='visible') { $this->PDFAXwarnings[] = "Cannot set visibility to anything other than full when using PDFA or PDFX"; return ''; }
1711 else if (!$this->PDFA && !$this->PDFX)
1712 $this->pdf_version='1.5';
1713 if($this->visibility!='visible') {
1714 $this->_out('EMC');
1715 $this->hasOC=intval($this->hasOC ); // mPDF 5.6.01
1716 }
1717 if($v=='printonly') {
1718 $this->_out('/OC /OC1 BDC');
1719 $this->hasOC=($this->hasOC | 1); // mPDF 5.6.01
1720 }
1721 elseif($v=='screenonly') {
1722 $this->_out('/OC /OC2 BDC');
1723 $this->hasOC=($this->hasOC | 2); // mPDF 5.6.01
1724 }
1725 elseif($v=='hidden') {
1726 $this->_out('/OC /OC3 BDC');
1727 $this->hasOC=($this->hasOC | 4); // mPDF 5.6.01
1728 }
1729 elseif($v!='visible')
1730 $this->Error('Incorrect visibility: '.$v);
1731 $this->visibility=$v;
1732 }
1733
1734 function Error($msg) {
1735 //Fatal error
1736 header('Content-Type: text/html; charset=utf-8');
1737 die('<B>mPDF error: </B>'.$msg);
1738 }
1739
1740 function Open() {
1741 //Begin document
1742 if($this->state==0) $this->_begindoc();
1743 }
1744
1745 function Close() {
1746 if ($this->progressBar) { $this->UpdateProgressBar(2,'2','Closing last page'); } // *PROGRESS-BAR*
1747 //Terminate document
1748 if($this->state==3) return;
1749 if($this->page==0) $this->AddPage($this->CurOrientation);
1750 if (count($this->cellBorderBuffer)) { $this->printcellbuffer(); } // *TABLES*
1751 if ($this->tablebuffer) { $this->printtablebuffer(); } // *TABLES*
1752 /*-- COLUMNS --*/
1753
1754 if ($this->ColActive) {
1755 $this->SetColumns(0);
1756 $this->ColActive = 0;
1757 if (count($this->columnbuffer)) { $this->printcolumnbuffer(); }
1758 }
1759 /*-- END COLUMNS --*/
1760 if (count($this->divbuffer)) { $this->printdivbuffer(); }
1761
1762 // BODY Backgrounds
1763 $s = '';
1764
1765 $s .= $this->PrintBodyBackgrounds();
1766
1767 $s .= $this->PrintPageBackgrounds();
1768 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', "\n".$s."\n".'\\1', $this->pages[$this->page]);
1769 $this->pageBackgrounds = array();
1770
1771 if($this->visibility!='visible')
1772 $this->SetVisibility('visible');
1773 // mPDF 5.6.01 - LAYERS
1774 $this->EndLayer();
1775
1776 if (!$this->tocontents || !$this->tocontents->TOCmark) { //Page footer
1777 $this->InFooter=true;
1778 $this->Footer();
1779 $this->InFooter=false;
1780 }
1781 if ($this->tocontents && ($this->tocontents->TOCmark || count($this->tocontents->m_TOC))) { $this->tocontents->insertTOC(); } // *TOC*
1782
1783 //Close page
1784 $this->_endpage();
1785
1786 //Close document
1787 $this->_enddoc();
1788 }
1789
1790 /*-- BACKGROUNDS --*/
1791 function _resizeBackgroundImage($imw, $imh, $cw, $ch, $resize=0, $repx, $repy, $pba=array(), $size=array()) { // mPDF 5.6.10
1792 // pba is background positioning area (from CSS background-origin) may not always be set [x,y,w,h]
1793 // size is from CSS3 background-size - takes precendence over old resize
1794 // $w - absolute length or % or auto or cover | contain
1795 // $h - absolute length or % or auto or cover | contain
1796 // mPDF 5.6.10
1797 if (isset($pba['w'])) $cw = $pba['w'];
1798 if (isset($pba['h'])) $ch = $pba['h'];
1799
1800 $cw = $cw*_MPDFK;
1801 $ch = $ch*_MPDFK;
1802 if (empty($size) && !$resize) { return array($imw, $imh, $repx, $repy); }
1803
1804 // mPDF 5.6.10
1805 if (isset($size['w']) && $size['w']) {
1806 if ($size['w']=='contain') {
1807 // 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.
1808 // Same as resize==3
1809 $h = $imh * $cw/$imw;
1810 $w = $cw;
1811 if ($h > $ch) {
1812 $w = $w * $ch/$h;
1813 $h = $ch;
1814 }
1815 }
1816 else if ($size['w']=='cover') {
1817 // 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.
1818 $h = $imh * $cw/$imw;
1819 $w = $cw;
1820 if ($h < $ch) {
1821 $w = $w * $h/$ch;
1822 $h = $ch;
1823 }
1824 }
1825 else {
1826 if (stristr($size['w'] ,'%')) {
1827 $size['w'] += 0;
1828 $size['w'] /= 100;
1829 $size['w'] = ($cw * $size['w']);
1830 }
1831 if (stristr($size['h'] ,'%')) {
1832 $size['h'] += 0;
1833 $size['h'] /= 100;
1834 $size['h'] = ($ch * $size['h']);
1835 }
1836 if ($size['w']=='auto' && $size['h']=='auto') {
1837 $w = $imw;
1838 $h = $imh;
1839 }
1840 else if ($size['w']=='auto' && $size['h']!='auto') {
1841 $w = $imw * $size['h']/$imh;
1842 $h = $size['h'];
1843 }
1844 else if ($size['w']!='auto' && $size['h']=='auto') {
1845 $h = $imh * $size['w']/$imw;
1846 $w = $size['w'];
1847 }
1848 else {
1849 $w = $size['w'];
1850 $h = $size['h'];
1851 }
1852 }
1853 return array($w, $h, $repx, $repy);
1854 }
1855 else if ($resize==1 && $imw > $cw) {
1856 $h = $imh * $cw/$imw;
1857 return array($cw, $h, $repx, $repy);
1858 }
1859 else if ($resize==2 && $imh > $ch) {
1860 $w = $imw * $ch/$imh;
1861 return array($w, $ch, $repx, $repy);
1862 }
1863 else if ($resize==3) {
1864 $w = $imw;
1865 $h = $imh;
1866 if ($w > $cw) {
1867 $h = $h * $cw/$w;
1868 $w = $cw;
1869 }
1870 if ($h > $ch) {
1871 $w = $w * $ch/$h;
1872 $h = $ch;
1873 }
1874 return array($w, $h, $repx, $repy);
1875 }
1876 else if ($resize==4) {
1877 $h = $imh * $cw/$imw;
1878 return array($cw, $h, $repx, $repy);
1879 }
1880 else if ($resize==5) {
1881 $w = $imw * $ch/$imh;
1882 return array($w, $ch, $repx, $repy);
1883 }
1884 else if ($resize==6) {
1885 return array($cw, $ch, $repx, $repy);
1886 }
1887 return array($imw, $imh, $repx, $repy);
1888 }
1889
1890
1891 function SetBackground(&$properties, &$maxwidth) {
1892 // mPDF 5.6.10 5.6.11
1893 if (isset($properties['BACKGROUND-ORIGIN']) && ($properties['BACKGROUND-ORIGIN']=='border-box' || $properties['BACKGROUND-ORIGIN']== 'content-box')) { $origin = $properties['BACKGROUND-ORIGIN']; }
1894 else { $origin = 'padding-box'; }
1895 // mPDF 5.6.10
1896 if (isset($properties['BACKGROUND-SIZE'])) {
1897 if (stristr($properties['BACKGROUND-SIZE'] ,'contain') ) { $bsw = $bsh = 'contain'; }
1898 else if (stristr($properties['BACKGROUND-SIZE'] ,'cover') ) { $bsw = $bsh = 'cover'; }
1899 else {
1900 $bsw = $bsh = 'auto';
1901 $sz = preg_split('/\s+/',trim($properties['BACKGROUND-SIZE']));
1902 if (count($sz)==2) { $bsw = $sz[0]; $bsh = $sz[1]; }
1903 else { $bsw = $sz[0]; }
1904 if (!stristr($bsw ,'%') && !stristr($bsw ,'auto') ) { $bsw = $this->ConvertSize($bsw ,$maxwidth,$this->FontSize); }
1905 if (!stristr($bsh ,'%') && !stristr($bsh ,'auto') ) { $bsh = $this->ConvertSize($bsh ,$maxwidth,$this->FontSize); }
1906 }
1907 $size = array('w'=>$bsw, 'h'=>$bsh);
1908 }
1909 if (preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/',$properties['BACKGROUND-IMAGE'])) {
1910 return array('gradient'=>$properties['BACKGROUND-IMAGE'], 'origin'=>$origin, 'size'=>$size ); // mPDF 5.6.10
1911 }
1912 else {
1913 $file = $properties['BACKGROUND-IMAGE'];
1914 $sizesarray = $this->Image($file,0,0,0,0,'','',false, false, false, false, true);
1915 if (isset($sizesarray['IMAGE_ID'])) {
1916 $image_id = $sizesarray['IMAGE_ID'];
1917 $orig_w = $sizesarray['WIDTH']*_MPDFK; // in user units i.e. mm
1918 $orig_h = $sizesarray['HEIGHT']*_MPDFK; // (using $this->img_dpi)
1919 if (isset($properties['BACKGROUND-IMAGE-RESOLUTION'])) {
1920 if (preg_match('/from-image/i', $properties['BACKGROUND-IMAGE-RESOLUTION']) && isset($sizesarray['set-dpi']) && $sizesarray['set-dpi']>0) {
1921 $orig_w *= $this->img_dpi / $sizesarray['set-dpi'];
1922 $orig_h *= $this->img_dpi / $sizesarray['set-dpi'];
1923 }
1924 else if (preg_match('/(\d+)dpi/i', $properties['BACKGROUND-IMAGE-RESOLUTION'], $m)) {
1925 $dpi = $m[1];
1926 if ($dpi > 0) {
1927 $orig_w *= $this->img_dpi / $dpi;
1928 $orig_h *= $this->img_dpi / $dpi;
1929 }
1930 }
1931 }
1932 $x_repeat = true;
1933 $y_repeat = true;
1934 if (isset($properties['BACKGROUND-REPEAT'])) {
1935 if ($properties['BACKGROUND-REPEAT']=='no-repeat' || $properties['BACKGROUND-REPEAT']=='repeat-x') { $y_repeat = false; }
1936 if ($properties['BACKGROUND-REPEAT']=='no-repeat' || $properties['BACKGROUND-REPEAT']=='repeat-y') { $x_repeat = false; }
1937 }
1938 $x_pos = 0;
1939 $y_pos = 0;
1940 if (isset($properties['BACKGROUND-POSITION'])) {
1941 $ppos = preg_split('/\s+/',$properties['BACKGROUND-POSITION']);
1942 $x_pos = $ppos[0];
1943 $y_pos = $ppos[1];
1944 if (!stristr($x_pos ,'%') ) { $x_pos = $this->ConvertSize($x_pos ,$maxwidth,$this->FontSize); }
1945 if (!stristr($y_pos ,'%') ) { $y_pos = $this->ConvertSize($y_pos ,$maxwidth,$this->FontSize); }
1946 }
1947 if (isset($properties['BACKGROUND-IMAGE-RESIZE'])) { $resize = $properties['BACKGROUND-IMAGE-RESIZE']; }
1948 else { $resize = 0; }
1949 if (isset($properties['BACKGROUND-IMAGE-OPACITY'])) { $opacity = $properties['BACKGROUND-IMAGE-OPACITY']; }
1950 else { $opacity = 1; }
1951 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 );
1952 }
1953 }
1954 return false;
1955 }
1956 /*-- END BACKGROUNDS --*/
1957
1958 function PrintBodyBackgrounds() {
1959 $s = '';
1960 $clx = 0;
1961 $cly = 0;
1962 $clw = $this->w;
1963 $clh = $this->h;
1964 // If using bleed and trim margins in paged media
1965 if ($this->pageDim[$this->page]['outer_width_LR'] || $this->pageDim[$this->page]['outer_width_TB']) {
1966 $clx = $this->pageDim[$this->page]['outer_width_LR'] - $this->pageDim[$this->page]['bleedMargin'];
1967 $cly = $this->pageDim[$this->page]['outer_width_TB'] - $this->pageDim[$this->page]['bleedMargin'];
1968 $clw = $this->w - 2*$clx;
1969 $clh = $this->h - 2*$cly;
1970 }
1971
1972 if ($this->bodyBackgroundColor) {
1973 $s .= 'q ' .$this->SetFColor($this->bodyBackgroundColor, true)."\n";
1974 if ($this->bodyBackgroundColor{0}==5) { // RGBa
1975 $s .= $this->SetAlpha(ord($this->bodyBackgroundColor{4})/100, 'Normal', true, 'F')."\n";
1976 }
1977 else if ($this->bodyBackgroundColor{0}==6) { // CMYKa
1978 $s .= $this->SetAlpha(ord($this->bodyBackgroundColor{5})/100, 'Normal', true, 'F')."\n";
1979 }
1980 $s .= sprintf('%.3F %.3F %.3F %.3F re f Q', ($clx*_MPDFK), ($cly*_MPDFK),$clw*_MPDFK,$clh*_MPDFK)."\n";
1981 }
1982
1983 /*-- BACKGROUNDS --*/
1984 if ($this->bodyBackgroundGradient) {
1985 $g = $this->grad->parseBackgroundGradient($this->bodyBackgroundGradient);
1986 if ($g) {
1987 $s .= $this->grad->Gradient($clx, $cly, $clw, $clh, (isset($g['gradtype']) ? $g['gradtype'] : null), $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true);
1988 }
1989 }
1990 if ($this->bodyBackgroundImage) {
1991 if ( $this->bodyBackgroundImage['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $this->bodyBackgroundImage['gradient'])) {
1992 $g = $this->grad->parseMozGradient( $this->bodyBackgroundImage['gradient']);
1993 if ($g) {
1994 $s .= $this->grad->Gradient($clx, $cly, $clw, $clh, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true);
1995 }
1996 }
1997 else if ($this->bodyBackgroundImage['image_id']) { // Background pattern
1998 $n = count($this->patterns)+1;
1999 // If using resize, uses TrimBox (not including the bleed)
2000 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']);
2001
2002 $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']);
2003 if (($this->bodyBackgroundImage['opacity']>0 || $this->bodyBackgroundImage['opacity']==='0') && $this->bodyBackgroundImage['opacity']<1) { $opac = $this->SetAlpha($this->bodyBackgroundImage['opacity'],'Normal',true); }
2004 else { $opac = ''; }
2005 $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";
2006 }
2007 }
2008 /*-- END BACKGROUNDS --*/
2009 return $s;
2010 }
2011
2012
2013 function PrintPageBackgrounds($adjustmenty=0) {
2014 $s = '';
2015
2016 ksort($this->pageBackgrounds);
2017 foreach($this->pageBackgrounds AS $bl=>$pbs) {
2018 foreach ($pbs AS $pb) {
2019 if ((!isset($pb['image_id']) && !isset($pb['gradient'])) || isset($pb['shadowonly'])) { // Background colour or boxshadow
2020 // mPDF 5.6.01 - LAYERS
2021 if($pb['z-index']>0) {
2022 $this->current_layer = $pb['z-index'];
2023 $s .= "\n".'/OCBZ-index /ZI'.$pb['z-index'].' BDC'."\n";
2024 }
2025
2026 if($pb['visibility']!='visible') {
2027 if($pb['visibility']=='printonly')
2028 $s .= '/OC /OC1 BDC'."\n";
2029 else if($pb['visibility']=='screenonly')
2030 $s .= '/OC /OC2 BDC'."\n";
2031 else if($pb['visibility']=='hidden')
2032 $s .= '/OC /OC3 BDC'."\n";
2033 }
2034 // Box shadow
2035 if (isset($pb['shadow']) && $pb['shadow']) { $s .= $pb['shadow']."\n"; }
2036 if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2037 $s .= 'q '.$this->SetFColor($pb['col'], true)."\n";
2038 if ($pb['col']{0}==5) { // RGBa
2039 $s .= $this->SetAlpha(ord($pb['col']{4})/100, 'Normal', true, 'F')."\n";
2040 }
2041 else if ($pb['col']{0}==6) { // CMYKa
2042 $s .= $this->SetAlpha(ord($pb['col']{5})/100, 'Normal', true, 'F')."\n";
2043 }
2044 $s .= sprintf('%.3F %.3F %.3F %.3F re f Q',$pb['x']*_MPDFK,($this->h-$pb['y'])*_MPDFK,$pb['w']*_MPDFK,-$pb['h']*_MPDFK)."\n";
2045 if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2046 if($pb['visibility']!='visible')
2047 $s .= 'EMC'."\n";
2048
2049 // mPDF 5.6.01 - LAYERS
2050 if($pb['z-index']>0) {
2051 $s .= "\n".'EMCBZ-index'."\n";
2052 $this->current_layer = 0;
2053 }
2054 }
2055 }
2056 /*-- BACKGROUNDS --*/
2057 foreach ($pbs AS $pb) {
2058 // mPDF 5.6.01 - LAYERS
2059 if ((isset($pb['gradient']) && $pb['gradient']) || (isset($pb['image_id']) && $pb['image_id'])) {
2060 if($pb['z-index']>0) {
2061 $this->current_layer = $pb['z-index'];
2062 $s .= "\n".'/OCGZ-index /ZI'.$pb['z-index'].' BDC'."\n";
2063 }
2064 if($pb['visibility']!='visible') {
2065 if($pb['visibility']=='printonly')
2066 $s .= '/OC /OC1 BDC'."\n";
2067 else if($pb['visibility']=='screenonly')
2068 $s .= '/OC /OC2 BDC'."\n";
2069 else if($pb['visibility']=='hidden')
2070 $s .= '/OC /OC3 BDC'."\n";
2071 }
2072 }
2073 if (isset($pb['gradient']) && $pb['gradient']) {
2074 if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2075 $s .= $this->grad->Gradient($pb['x'], $pb['y'], $pb['w'], $pb['h'], $pb['gradtype'], $pb['stops'], $pb['colorspace'], $pb['coords'], $pb['extend'], true);
2076 if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2077 }
2078 else if (isset($pb['image_id']) && $pb['image_id']) { // Background Image
2079 $pb['y'] -= $adjustmenty;
2080 $pb['h'] += $adjustmenty;
2081 $n = count($this->patterns)+1;
2082 list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($pb['orig_w'], $pb['orig_h'], $pb['w'], $pb['h'], $pb['resize'], $pb['x_repeat'], $pb['y_repeat'], $pb['bpa'], $pb['size']); // mPDF 5.6.10
2083 $this->patterns[$n] = array('x'=>$pb['x'], 'y'=>$pb['y'], 'w'=>$pb['w'], 'h'=>$pb['h'], 'pgh'=>$this->h, 'image_id'=>$pb['image_id'], 'orig_w'=>$orig_w, 'orig_h'=>$orig_h, 'x_pos'=>$pb['x_pos'], 'y_pos'=>$pb['y_pos'], 'x_repeat'=>$x_repeat, 'y_repeat'=>$y_repeat, 'itype'=>$pb['itype'], 'bpa'=>$pb['bpa']); // mPDF 5.6.10
2084 $x = $pb['x']*_MPDFK;
2085 $y = ($this->h - $pb['y'])*_MPDFK;
2086 $w = $pb['w']*_MPDFK;
2087 $h = -$pb['h']*_MPDFK;
2088 if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2089 if ($this->writingHTMLfooter || $this->writingHTMLheader) { // Write each (tiles) image rather than use as a pattern
2090 $iw = $pb['orig_w']/_MPDFK;
2091 $ih = $pb['orig_h']/_MPDFK;
2092
2093 $w = $pb['w'];
2094 $h = $pb['h'];
2095 $x0 = $pb['x'];
2096 $y0 = $pb['y'];
2097
2098 // mPDF 5.6.11
2099 if (isset($pb['bpa']) && $pb['bpa']) {
2100 $w = $pb['bpa']['w'];
2101 $h = $pb['bpa']['h'];
2102 $x0 = $pb['bpa']['x'];
2103 $y0 = $pb['bpa']['y'];
2104 }
2105
2106 // mPDF 5.6.11
2107 if (isset($pb['size']['w']) && $pb['size']['w']) {
2108 $size = $pb['size'];
2109
2110 if ($size['w']=='contain') {
2111 // 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.
2112 // Same as resize==3
2113 $ih = $ih * $pb['bpa']['w']/$iw;
2114 $iw = $pb['bpa']['w'];
2115 if ($ih > $pb['bpa']['h']) {
2116 $iw = $iw * $pb['bpa']['h']/$ih;
2117 $ih = $pb['bpa']['h'];
2118 }
2119 }
2120 else if ($size['w']=='cover') {
2121 // 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.
2122 $ih = $ih * $pb['bpa']['w']/$iw;
2123 $iw = $pb['bpa']['w'];
2124 if ($ih < $pb['bpa']['h']) {
2125 $iw = $iw * $ih/$pb['bpa']['h'];
2126 $ih = $pb['bpa']['h'];
2127 }
2128 }
2129 else {
2130 if (stristr($size['w'] ,'%')) {
2131 $size['w'] += 0;
2132 $size['w'] /= 100;
2133 $size['w'] = ($pb['bpa']['w'] * $size['w']);
2134 }
2135 if (stristr($size['h'] ,'%')) {
2136 $size['h'] += 0;
2137 $size['h'] /= 100;
2138 $size['h'] = ($pb['bpa']['h'] * $size['h']);
2139 }
2140 if ($size['w']=='auto' && $size['h']=='auto') {
2141 $iw = $iw;
2142 $ih = $ih;
2143 }
2144 else if ($size['w']=='auto' && $size['h']!='auto') {
2145 $iw = $iw * $size['h']/$ih;
2146 $ih = $size['h'];
2147 }
2148 else if ($size['w']!='auto' && $size['h']=='auto') {
2149 $ih = $ih * $size['w']/$iw;
2150 $iw = $size['w'];
2151 }
2152 else {
2153 $iw = $size['w'];
2154 $ih = $size['h'];
2155 }
2156 }
2157 }
2158
2159 // Number to repeat
2160 if ($pb['x_repeat']) { $nx = ceil($pb['w']/$iw)+1; } // mPDF 5.6.11
2161 else { $nx = 1; }
2162 if ($pb['y_repeat']) { $ny = ceil($pb['h']/$ih)+1; } // mPDF 5.6.11
2163 else { $ny = 1; }
2164
2165 $x_pos = $pb['x_pos'];
2166 if (stristr($x_pos ,'%') ) {
2167 $x_pos += 0;
2168 $x_pos /= 100;
2169 $x_pos = ($pb['bpa']['w'] * $x_pos) - ($iw * $x_pos); // mPDF 5.6.11
2170 }
2171 $y_pos = $pb['y_pos'];
2172 if (stristr($y_pos ,'%') ) {
2173 $y_pos += 0;
2174 $y_pos /= 100;
2175 $y_pos = ($pb['bpa']['h'] * $y_pos) - ($ih * $y_pos); // mPDF 5.6.11
2176 }
2177 if ($nx>1) {
2178 while($x_pos>($pb['x']-$pb['bpa']['x'])) { $x_pos -= $iw; } // mPDF 5.6.11
2179 }
2180 if ($ny>1) {
2181 while($y_pos>($pb['y']-$pb['bpa']['y'])) { $y_pos -= $ih; } // mPDF 5.6.11
2182 }
2183 for($xi=0;$xi<$nx;$xi++) {
2184 for($yi=0;$yi<$ny;$yi++) {
2185 $x = $x0 + $x_pos + ($iw*$xi);
2186 $y = $y0 + $y_pos + ($ih*$yi);
2187 if ($pb['opacity']>0 && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
2188 else { $opac = ''; }
2189 $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";
2190 }
2191 }
2192 }
2193 else {
2194 if (($pb['opacity']>0 || $pb['opacity']==='0') && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
2195 else { $opac = ''; }
2196 $s .= sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $x, $y, $w, $h) ."\n";
2197 }
2198 if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2199 }
2200 if ((isset($pb['gradient']) && $pb['gradient']) || (isset($pb['image_id']) && $pb['image_id'])) {
2201 if($pb['visibility']!='visible')
2202 $s .= 'EMC'."\n";
2203
2204 // mPDF 5.6.01 - LAYERS
2205 if($pb['z-index']>0) {
2206 $s .= "\n".'EMCGZ-index'."\n";
2207 $this->current_layer = 0;
2208 }
2209 }
2210
2211 }
2212 /*-- END BACKGROUNDS --*/
2213 }
2214 return $s;
2215 }
2216
2217 function PrintTableBackgrounds($adjustmenty=0) {
2218 $s = '';
2219 /*-- BACKGROUNDS --*/
2220 ksort($this->tableBackgrounds);
2221 foreach($this->tableBackgrounds AS $bl=>$pbs) {
2222 foreach ($pbs AS $pb) {
2223 if ((!isset($pb['gradient']) || !$pb['gradient']) && (!isset($pb['image_id']) || !$pb['image_id'])) {
2224 $s .= 'q '.$this->SetFColor($pb['col'], true)."\n";
2225 if ($pb['col']{0}==5) { // RGBa
2226 $s .= $this->SetAlpha(ord($pb['col']{4})/100, 'Normal', true, 'F')."\n";
2227 }
2228 else if ($pb['col']{0}==6) { // CMYKa
2229 $s .= $this->SetAlpha(ord($pb['col']{5})/100, 'Normal', true, 'F')."\n";
2230 }
2231 $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";
2232 }
2233 if (isset($pb['gradient']) && $pb['gradient']) {
2234 if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2235 $s .= $this->grad->Gradient($pb['x'], $pb['y'], $pb['w'], $pb['h'], $pb['gradtype'], $pb['stops'], $pb['colorspace'], $pb['coords'], $pb['extend'], true);
2236 if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2237 }
2238 if (isset($pb['image_id']) && $pb['image_id']) { // Background pattern
2239 $pb['y'] -= $adjustmenty;
2240 $pb['h'] += $adjustmenty;
2241 $n = count($this->patterns)+1;
2242 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']);
2243 $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']);
2244 $x = $pb['x']*_MPDFK;
2245 $y = ($this->h - $pb['y'])*_MPDFK;
2246 $w = $pb['w']*_MPDFK;
2247 $h = -$pb['h']*_MPDFK;
2248 if (isset($pb['clippath']) && $pb['clippath']) { $s .= $pb['clippath']."\n"; }
2249 if ($pb['opacity']>0 && $pb['opacity']<1) { $opac = $this->SetAlpha($pb['opacity'],'Normal',true); }
2250 else { $opac = ''; }
2251 $s .= sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $x, $y, $w, $h) ."\n";
2252 if (isset($pb['clippath']) && $pb['clippath']) { $s .= 'Q'."\n"; }
2253 }
2254 }
2255 }
2256 /*-- END BACKGROUNDS --*/
2257 return $s;
2258 }
2259
2260 // mPDF 5.6.01 - LAYERS
2261 function BeginLayer($id) {
2262 if($this->current_layer>0) $this->EndLayer();
2263 if ($id < 1) { return false; }
2264 if (!isset($this->layers[$id])) {
2265 $this->layers[$id] = array('name'=>'Layer '.($id) );
2266 if (($this->PDFA || $this->PDFX)) { $this->PDFAXwarnings[] = "Cannot use layers when using PDFA or PDFX"; return ''; }
2267 else if (!$this->PDFA && !$this->PDFX) { $this->pdf_version='1.5'; }
2268 }
2269 $this->current_layer = $id;
2270 $this->_out('/OCZ-index /ZI'.$id.' BDC');
2271
2272 $this->pageoutput[$this->page] = array();
2273 }
2274
2275 function EndLayer() {
2276 if($this->current_layer>0) {
2277 $this->_out('EMCZ-index');
2278 $this->current_layer = 0;
2279 }
2280 }
2281
2282
2283
2284 // Depracated - can use AddPage for all
2285 function AddPages($orientation='',$condition='', $resetpagenum='', $pagenumstyle='', $suppress='',$mgl='',$mgr='',$mgt='',$mgb='',$mgh='',$mgf='',$ohname='',$ehname='',$ofname='',$efname='',$ohvalue=0,$ehvalue=0,$ofvalue=0,$efvalue=0,$pagesel='',$newformat='')
2286 {
2287 $this->AddPage($orientation,$condition,$resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue,$pagesel,$newformat);
2288 }
2289
2290
2291 function AddPageByArray($a) {
2292 if (!is_array($a)) { $a = array(); }
2293 $orientation = (isset($a['orientation']) ? $a['orientation'] : '');
2294 $condition = (isset($a['condition']) ? $a['condition'] : (isset($a['type']) ? $a['type'] : ''));
2295 $resetpagenum = (isset($a['resetpagenum']) ? $a['resetpagenum'] : '');
2296 $pagenumstyle = (isset($a['pagenumstyle']) ? $a['pagenumstyle'] : '');
2297 $suppress = (isset($a['suppress']) ? $a['suppress'] : '');
2298 $mgl = (isset($a['mgl']) ? $a['mgl'] : (isset($a['margin-left']) ? $a['margin-left'] : ''));
2299 $mgr = (isset($a['mgr']) ? $a['mgr'] : (isset($a['margin-right']) ? $a['margin-right'] : ''));
2300 $mgt = (isset($a['mgt']) ? $a['mgt'] : (isset($a['margin-top']) ? $a['margin-top'] : ''));
2301 $mgb = (isset($a['mgb']) ? $a['mgb'] : (isset($a['margin-bottom']) ? $a['margin-bottom'] : ''));
2302 $mgh = (isset($a['mgh']) ? $a['mgh'] : (isset($a['margin-header']) ? $a['margin-header'] : ''));
2303 $mgf = (isset($a['mgf']) ? $a['mgf'] : (isset($a['margin-footer']) ? $a['margin-footer'] : ''));
2304 $ohname = (isset($a['ohname']) ? $a['ohname'] : (isset($a['odd-header-name']) ? $a['odd-header-name'] : ''));
2305 $ehname = (isset($a['ehname']) ? $a['ehname'] : (isset($a['even-header-name']) ? $a['even-header-name'] : ''));
2306 $ofname = (isset($a['ofname']) ? $a['ofname'] : (isset($a['odd-footer-name']) ? $a['odd-footer-name'] : ''));
2307 $efname = (isset($a['efname']) ? $a['efname'] : (isset($a['even-footer-name']) ? $a['even-footer-name'] : ''));
2308 $ohvalue = (isset($a['ohvalue']) ? $a['ohvalue'] : (isset($a['odd-header-value']) ? $a['odd-header-value'] : 0));
2309 $ehvalue = (isset($a['ehvalue']) ? $a['ehvalue'] : (isset($a['even-header-value']) ? $a['even-header-value'] : 0));
2310 $ofvalue = (isset($a['ofvalue']) ? $a['ofvalue'] : (isset($a['odd-footer-value']) ? $a['odd-footer-value'] : 0));
2311 $efvalue = (isset($a['efvalue']) ? $a['efvalue'] : (isset($a['even-footer-value']) ? $a['even-footer-value'] : 0));
2312 $pagesel = (isset($a['pagesel']) ? $a['pagesel'] : (isset($a['pageselector']) ? $a['pageselector'] : ''));
2313 $newformat = (isset($a['newformat']) ? $a['newformat'] : (isset($a['sheet-size']) ? $a['sheet-size'] : ''));
2314
2315 $this->AddPage($orientation,$condition,$resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue,$pagesel,$newformat);
2316
2317 }
2318
2319
2320 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='')
2321 {
2322 /*-- CSS-FLOAT --*/
2323 // Float DIV
2324 // Cannot do with columns on, or if any change in page orientation/margins etc.
2325 // If next page already exists - i.e background /headers and footers already written
2326 if ($this->state > 0 && $this->page < count($this->pages)) {
2327 $bak_cml = $this->cMarginL;
2328 $bak_cmr = $this->cMarginR;
2329 $bak_dw = $this->divwidth;
2330 // Paint Div Border if necessary
2331 if ($this->blklvl > 0) {
2332 $save_tr = $this->table_rotate; // *TABLES*
2333 $this->table_rotate = 0; // *TABLES*
2334 if ($this->y == $this->blk[$this->blklvl]['y0']) { $this->blk[$this->blklvl]['startpage']++; }
2335 if (($this->y > $this->blk[$this->blklvl]['y0']) || $this->flowingBlockAttr['is_table'] ) { $toplvl = $this->blklvl; }
2336 else { $toplvl = $this->blklvl-1; }
2337 $sy = $this->y;
2338 for ($bl=1;$bl<=$toplvl;$bl++) {
2339 $this->PaintDivBB('pagebottom',0,$bl);
2340 }
2341 $this->y = $sy;
2342 $this->table_rotate = $save_tr; // *TABLES*
2343 }
2344 $s = $this->PrintPageBackgrounds();
2345
2346 // Writes after the marker so not overwritten later by page background etc.
2347 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
2348 $this->pageBackgrounds = array();
2349 $family=$this->FontFamily;
2350 $style=$this->FontStyle.($this->U ? 'U' : '').($this->S ? 'S' : '');
2351 $size=$this->FontSizePt;
2352 $lw=$this->LineWidth;
2353 $dc=$this->DrawColor;
2354 $fc=$this->FillColor;
2355 $tc=$this->TextColor;
2356 $cf=$this->ColorFlag;
2357
2358 $this->printfloatbuffer();
2359
2360 //Move to next page
2361 $this->page++;
2362 $this->ResetMargins();
2363 $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
2364 $this->x=$this->lMargin;
2365 $this->y=$this->tMargin;
2366 $this->FontFamily='';
2367 $this->_out('2 J');
2368 $this->LineWidth=$lw;
2369 $this->_out(sprintf('%.3F w',$lw*_MPDFK));
2370 if($family) $this->SetFont($family,$style,$size,true,true);
2371 $this->DrawColor=$dc;
2372 if($dc!=$this->defDrawColor) $this->_out($dc);
2373 $this->FillColor=$fc;
2374 if($fc!=$this->defFillColor) $this->_out($fc);
2375 $this->TextColor=$tc;
2376 $this->ColorFlag=$cf;
2377 for($bl=1;$bl<=$this->blklvl;$bl++) {
2378 $this->blk[$bl]['y0'] = $this->y;
2379 // Don't correct more than once for background DIV containing a Float
2380 if (!isset($this->blk[$bl]['marginCorrected'][$this->page])) { $this->blk[$bl]['x0'] += $this->MarginCorrection; }
2381 $this->blk[$bl]['marginCorrected'][$this->page] = true;
2382 }
2383 $this->cMarginL = $bak_cml;
2384 $this->cMarginR = $bak_cmr;
2385 $this->divwidth = $bak_dw;
2386 return '';
2387 }
2388 /*-- END CSS-FLOAT --*/
2389
2390 //Start a new page
2391 if($this->state==0) $this->Open();
2392
2393 $bak_cml = $this->cMarginL;
2394 $bak_cmr = $this->cMarginR;
2395 $bak_dw = $this->divwidth;
2396
2397
2398 $bak_lh = $this->lineheight;
2399
2400 $orientation = substr(strtoupper($orientation),0,1);
2401 $condition = strtoupper($condition);
2402
2403
2404 if ($condition == 'NEXT-EVEN') { // always adds at least one new page to create an Even page
2405 if (!$this->mirrorMargins) { $condition = ''; }
2406 else {
2407 if ($pagesel) { $pbch = $pagesel; $pagesel = ''; } // *CSS-PAGE*
2408 else { $pbch = false; } // *CSS-PAGE*
2409 $this->AddPage($this->CurOrientation,'O');
2410 if ($pbch ) { $pagesel = $pbch; } // *CSS-PAGE*
2411 $condition = '';
2412 }
2413 }
2414 if ($condition == 'NEXT-ODD') { // always adds at least one new page to create an Odd page
2415 if (!$this->mirrorMargins) { $condition = ''; }
2416 else {
2417 if ($pagesel) { $pbch = $pagesel; $pagesel = ''; } // *CSS-PAGE*
2418 else { $pbch = false; } // *CSS-PAGE*
2419 $this->AddPage($this->CurOrientation,'E');
2420 if ($pbch ) { $pagesel = $pbch; } // *CSS-PAGE*
2421 $condition = '';
2422 }
2423 }
2424
2425
2426 if ($condition == 'E') { // only adds new page if needed to create an Even page
2427 if (!$this->mirrorMargins || ($this->page)%2==0) { return false; }
2428 }
2429 if ($condition == 'O') { // only adds new page if needed to create an Odd page
2430 if (!$this->mirrorMargins || ($this->page)%2==1) { return false; }
2431 }
2432
2433 if ($resetpagenum || $pagenumstyle || $suppress) {
2434 $this->PageNumSubstitutions[] = array('from'=>($this->page+1), 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=>$suppress);
2435 }
2436
2437
2438 $save_tr = $this->table_rotate; // *TABLES*
2439 $this->table_rotate = 0; // *TABLES*
2440 $save_kwt = $this->kwt;
2441 $this->kwt = 0;
2442 // mPDF 5.6.01 - LAYERS
2443 $save_layer = $this->current_layer;
2444 $save_vis = $this->visibility;
2445
2446 if($this->visibility!='visible')
2447 $this->SetVisibility('visible');
2448 // mPDF 5.6.01 - LAYERS
2449 $this->EndLayer();
2450
2451 // Paint Div Border if necessary
2452 //PAINTS BACKGROUND COLOUR OR BORDERS for DIV - DISABLED FOR COLUMNS (cf. AcceptPageBreak) AT PRESENT in ->PaintDivBB
2453 if (!$this->ColActive && $this->blklvl > 0) {
2454 if (isset($this->blk[$this->blklvl]['y0']) && $this->y == $this->blk[$this->blklvl]['y0']) {
2455 if (isset($this->blk[$this->blklvl]['startpage'])) { $this->blk[$this->blklvl]['startpage']++; }
2456 else { $this->blk[$this->blklvl]['startpage'] = 1; }
2457 }
2458 if ((isset($this->blk[$this->blklvl]['y0']) && $this->y > $this->blk[$this->blklvl]['y0']) || $this->flowingBlockAttr['is_table'] ) { $toplvl = $this->blklvl; }
2459 else { $toplvl = $this->blklvl-1; }
2460 $sy = $this->y;
2461 for ($bl=1;$bl<=$toplvl;$bl++) {
2462
2463 // mPDF 5.6.01 - LAYERS
2464 if ($this->blk[$bl]['z-index']>0) {
2465 $this->BeginLayer($this->blk[$bl]['z-index']);
2466 }
2467 if (isset($this->blk[$bl]['visibility']) && $this->blk[$bl]['visibility'] && $this->blk[$bl]['visibility']!='visible') {
2468 $this->SetVisibility($this->blk[$bl]['visibility']);
2469 }
2470
2471 $this->PaintDivBB('pagebottom',0,$bl);
2472 }
2473 $this->y = $sy;
2474 // RESET block y0 and x0 - see below
2475 }
2476
2477 if($this->visibility!='visible')
2478 $this->SetVisibility('visible');
2479 // mPDF 5.6.01 - LAYERS
2480 $this->EndLayer();
2481
2482 // BODY Backgrounds
2483 if ($this->page > 0) {
2484 $s = '';
2485 $s .= $this->PrintBodyBackgrounds();
2486
2487 $s .= $this->PrintPageBackgrounds();
2488 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', "\n".$s."\n".'\\1', $this->pages[$this->page]);
2489 $this->pageBackgrounds = array();
2490 }
2491
2492 $save_kt = $this->keep_block_together;
2493 $this->keep_block_together = 0;
2494
2495 $save_cols = false;
2496 /*-- COLUMNS --*/
2497 if ($this->ColActive) {
2498 $save_cols = true;
2499 $save_nbcol = $this->NbCol; // other values of gap and vAlign will not change by setting Columns off
2500 $this->SetColumns(0);
2501 }
2502 /*-- END COLUMNS --*/
2503
2504
2505 $family=$this->FontFamily;
2506 $style=$this->FontStyle.($this->U ? 'U' : '').($this->S ? 'S' : '');
2507 $size=$this->FontSizePt;
2508 $this->ColumnAdjust = true; // enables column height adjustment for the page
2509 $lw=$this->LineWidth;
2510 $dc=$this->DrawColor;
2511 $fc=$this->FillColor;
2512 $tc=$this->TextColor;
2513 $cf=$this->ColorFlag;
2514 if($this->page>0)
2515 {
2516 //Page footer
2517 $this->InFooter=true;
2518
2519 $this->Reset();
2520 $this->pageoutput[$this->page] = array();
2521
2522 $this->Footer();
2523 //Close page
2524 $this->_endpage();
2525 }
2526
2527
2528 //Start new page
2529 $this->_beginpage($orientation,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat);
2530 if ($this->docTemplate) {
2531 $pagecount = $this->SetSourceFile($this->docTemplate);
2532 if (($this->page - $this->docTemplateStart) > $pagecount) {
2533 if ($this->docTemplateContinue) {
2534 $tplIdx = $this->ImportPage($pagecount);
2535 $this->UseTemplate($tplIdx);
2536 }
2537 }
2538 else {
2539 $tplIdx = $this->ImportPage(($this->page - $this->docTemplateStart));
2540 $this->UseTemplate($tplIdx);
2541 }
2542 }
2543 if ($this->pageTemplate) {
2544 $this->UseTemplate($this->pageTemplate);
2545 }
2546
2547 // Tiling Patterns
2548 $this->_out('___PAGE___START'.date('jY'));
2549 $this->_out('___BACKGROUND___PATTERNS'.date('jY'));
2550 $this->_out('___HEADER___MARKER'.date('jY'));
2551 $this->pageBackgrounds = array();
2552
2553 //Set line cap style to square
2554 $this->SetLineCap(2);
2555 //Set line width
2556 $this->LineWidth=$lw;
2557 $this->_out(sprintf('%.3F w',$lw*_MPDFK));
2558 //Set font
2559 if($family) $this->SetFont($family,$style,$size,true,true); // forces write
2560 //Set colors
2561 $this->DrawColor=$dc;
2562 if($dc!=$this->defDrawColor) $this->_out($dc);
2563 $this->FillColor=$fc;
2564 if($fc!=$this->defFillColor) $this->_out($fc);
2565 $this->TextColor=$tc;
2566 $this->ColorFlag=$cf;
2567
2568 //Page header
2569 $this->Header();
2570
2571 //Restore line width
2572 if($this->LineWidth!=$lw)
2573 {
2574 $this->LineWidth=$lw;
2575 $this->_out(sprintf('%.3F w',$lw*_MPDFK));
2576 }
2577 //Restore font
2578 if($family) $this->SetFont($family,$style,$size,true,true); // forces write
2579 //Restore colors
2580 if($this->DrawColor!=$dc)
2581 {
2582 $this->DrawColor=$dc;
2583 $this->_out($dc);
2584 }
2585 if($this->FillColor!=$fc)
2586 {
2587 $this->FillColor=$fc;
2588 $this->_out($fc);
2589 }
2590 $this->TextColor=$tc;
2591 $this->ColorFlag=$cf;
2592 $this->InFooter=false;
2593
2594 // mPDF 5.6.01 - LAYERS
2595 if ($save_layer>0)
2596 $this->BeginLayer($save_layer);
2597
2598 if($save_vis!='visible')
2599 $this->SetVisibility($save_vis);
2600
2601 /*-- COLUMNS --*/
2602 if ($save_cols) {
2603 // Restore columns
2604 $this->SetColumns($save_nbcol,$this->colvAlign,$this->ColGap);
2605 }
2606 if ($this->ColActive) { $this->SetCol(0); }
2607 /*-- END COLUMNS --*/
2608
2609
2610 //RESET BLOCK BORDER TOP
2611 if (!$this->ColActive) {
2612 for($bl=1;$bl<=$this->blklvl;$bl++) {
2613 $this->blk[$bl]['y0'] = $this->y;
2614 if (isset($this->blk[$bl]['x0'])) { $this->blk[$bl]['x0'] += $this->MarginCorrection; }
2615 else { $this->blk[$bl]['x0'] = $this->MarginCorrection; }
2616 // Added mPDF 3.0 Float DIV
2617 $this->blk[$bl]['marginCorrected'][$this->page] = true;
2618 }
2619 }
2620
2621
2622 $this->table_rotate = $save_tr; // *TABLES*
2623 $this->kwt = $save_kwt;
2624
2625 $this->keep_block_together = $save_kt ;
2626
2627 $this->cMarginL = $bak_cml;
2628 $this->cMarginR = $bak_cmr;
2629 $this->divwidth = $bak_dw;
2630
2631 $this->lineheight = $bak_lh;
2632 }
2633
2634
2635 function PageNo() {
2636 //Get current page number
2637 return $this->page;
2638 }
2639
2640 function AddSpotColorsFromFile($file) {
2641 $colors = @file($file) or die("Cannot load spot colors file - ".$file);
2642 foreach($colors AS $sc) {
2643 list($name, $c, $m, $y, $k) = preg_split("/\t/",$sc);
2644 $c = intval($c);
2645 $m = intval($m);
2646 $y = intval($y);
2647 $k = intval($k);
2648 $this->AddSpotColor($name, $c, $m, $y, $k);
2649 }
2650 }
2651
2652 function AddSpotColor($name, $c, $m, $y, $k) {
2653 $name = strtoupper(trim($name));
2654 if(!isset($this->spotColors[$name])) {
2655 $i=count($this->spotColors)+1;
2656 $this->spotColors[$name]=array('i'=>$i,'c'=>$c,'m'=>$m,'y'=>$y,'k'=>$k);
2657 $this->spotColorIDs[$i]=$name;
2658 }
2659 }
2660
2661 function SetColor($col, $type='') {
2662 $out = '';
2663 if ($col{0}==3 || $col{0}==5) { // RGB / RGBa
2664 $out = sprintf('%.3F %.3F %.3F rg',ord($col{1})/255,ord($col{2})/255,ord($col{3})/255);
2665 }
2666 else if ($col{0}==1) { // GRAYSCALE
2667 $out = sprintf('%.3F g',ord($col{1})/255);
2668 }
2669 else if ($col{0}==2) { // SPOT COLOR
2670 $out = sprintf('/CS%d cs %.3F scn',ord($col{1}),ord($col{2})/100);
2671 }
2672 else if ($col{0}==4 || $col{0}==6) { // CMYK / CMYKa
2673 $out = sprintf('%.3F %.3F %.3F %.3F k', ord($col{1})/100, ord($col{2})/100, ord($col{3})/100, ord($col{4})/100);
2674 }
2675 if ($type=='Draw') { $out = strtoupper($out); } // e.g. rg => RG
2676 else if ($type=='CodeOnly') { $out = preg_replace('/\s(rg|g|k)/','',$out); }
2677 return $out;
2678 }
2679
2680
2681 function SetDColor($col, $return=false) {
2682 $out = $this->SetColor($col, 'Draw');
2683 if ($return) { return $out; }
2684 if ($out=='') { return ''; }
2685 $this->DrawColor = $out;
2686 if($this->page>0 && ((isset($this->pageoutput[$this->page]['DrawColor']) && $this->pageoutput[$this->page]['DrawColor'] != $this->DrawColor) || !isset($this->pageoutput[$this->page]['DrawColor']) || $this->keep_block_together)) { $this->_out($this->DrawColor); }
2687 $this->pageoutput[$this->page]['DrawColor'] = $this->DrawColor;
2688 }
2689
2690 function SetFColor($col, $return=false) {
2691 $out = $this->SetColor($col, 'Fill');
2692 if ($return) { return $out; }
2693 if ($out=='') { return ''; }
2694 $this->FillColor = $out;
2695 $this->ColorFlag = ($out != $this->TextColor);
2696 if($this->page>0 && ((isset($this->pageoutput[$this->page]['FillColor']) && $this->pageoutput[$this->page]['FillColor'] != $this->FillColor) || !isset($this->pageoutput[$this->page]['FillColor']) || $this->keep_block_together)) { $this->_out($this->FillColor); }
2697 $this->pageoutput[$this->page]['FillColor'] = $this->FillColor;
2698 }
2699
2700 function SetTColor($col, $return=false) {
2701 $out = $this->SetColor($col, 'Text');
2702 if ($return) { return $out; }
2703 if ($out=='') { return ''; }
2704 $this->TextColor = $out;
2705 $this->ColorFlag = ($this->FillColor != $out);
2706 }
2707
2708
2709 function SetDrawColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
2710 //Set color for all stroking operations
2711 $col = array();
2712 if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
2713 else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
2714 else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
2715 $out = $this->SetDColor($col, $return);
2716 return $out;
2717 }
2718
2719 function SetFillColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
2720 //Set color for all filling operations
2721 $col = array();
2722 if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
2723 else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
2724 else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
2725 $out = $this->SetFColor($col, $return);
2726 return $out;
2727 }
2728
2729 function SetTextColor($r,$g=-1,$b=-1,$col4=-1, $return=false) {
2730 //Set color for text
2731 $col = array();
2732 if(($r==0 and $g==0 and $b==0 && $col4 == -1) or $g==-1) { $col = $this->ConvertColor($r); }
2733 else if ($col4 == -1) { $col = $this->ConvertColor('rgb('.$r.','.$g.','.$b.')'); }
2734 else { $col = $this->ConvertColor('cmyk('.$r.','.$g.','.$b.','.$col4.')'); }
2735 $out = $this->SetTColor($col, $return);
2736 return $out;
2737 }
2738
2739 function _getCharWidth(&$cw, $u, $isdef=true) {
2740 if ($u==0) { $w = false; }
2741 else { $w = (ord($cw[$u*2]) << 8) + ord($cw[$u*2+1]); }
2742 if ($w == 65535) { return 0; }
2743 else if ($w) { return $w; }
2744 else if ($isdef) { return false; }
2745 else { return 0; }
2746 }
2747
2748 function _charDefined(&$cw, $u) {
2749 if ($u==0) { return false; }
2750 $w = (ord($cw[$u*2]) << 8) + ord($cw[$u*2+1]);
2751 if ($w) { return true; }
2752 else { return false; }
2753 }
2754
2755 function GetCharWidthCore($c) {
2756 //Get width of a single character in the current Core font
2757 $c = (string)$c;
2758 $w = 0;
2759 // Soft Hyphens chr(173)
2760 if ($c == chr(173) && $this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
2761 return 0;
2762 }
2763 else if ($this->S && isset($this->upperCase[ord($c)])) {
2764 $charw = $this->CurrentFont['cw'][chr($this->upperCase[ord($c)])];
2765 if ($charw!==false) {
2766 $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
2767 $w+=$charw;
2768 }
2769 }
2770 else if (isset($this->CurrentFont['cw'][$c])) {
2771 $w += $this->CurrentFont['cw'][$c];
2772 }
2773 else if (isset($this->CurrentFont['cw'][ord($c)])) {
2774 $w += $this->CurrentFont['cw'][ord($c)];
2775 }
2776 $w *= ($this->FontSize/ 1000);
2777 if ($this->minwSpacing || $this->fixedlSpacing) {
2778 if ($c==' ') $nb_spaces = 1;
2779 else $nb_spaces = 0;
2780 $w += $this->fixedlSpacing + ($nb_spaces * $this->minwSpacing);
2781 }
2782 return ($w);
2783 }
2784
2785 function GetCharWidthNonCore($c, $addSubset=true) {
2786 //Get width of a single character in the current Non-Core font
2787 $c = (string)$c;
2788 $w = 0;
2789 $unicode = $this->UTF8StringToArray($c, $addSubset);
2790 $char = $unicode[0];
2791 /*-- CJK-FONTS --*/
2792 if ($this->CurrentFont['type'] == 'Type0') { // CJK Adobe fonts
2793 if ($char == 173) { return 0; } // Soft Hyphens
2794 elseif (isset($this->CurrentFont['cw'][$char])) { $w+=$this->CurrentFont['cw'][$char]; }
2795 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
2796 else { $w += 500; }
2797 }
2798 else {
2799 /*-- END CJK-FONTS --*/
2800 if ($char == 173) { return 0; } // Soft Hyphens
2801 else if ($this->S && isset($this->upperCase[$char])) {
2802 $charw = $this->_getCharWidth($this->CurrentFont['cw'],$this->upperCase[$char]);
2803 if ($charw!==false) {
2804 $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
2805 $w+=$charw;
2806 }
2807 elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
2808 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
2809 else { $w += 500; }
2810 }
2811 else {
2812 $charw = $this->_getCharWidth($this->CurrentFont['cw'],$char);
2813 if ($charw!==false) { $w+=$charw; }
2814 elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
2815 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
2816 else { $w += 500; }
2817 }
2818 } // *CJK-FONTS*
2819 $w *= ($this->FontSize/ 1000);
2820 if ($this->minwSpacing || $this->fixedlSpacing) {
2821 if ($c==' ') $nb_spaces = 1;
2822 else $nb_spaces = 0;
2823 $w += $this->fixedlSpacing + ($nb_spaces * $this->minwSpacing);
2824 }
2825 return ($w);
2826 }
2827
2828
2829 function GetCharWidth($c, $addSubset=true) {
2830 if (!$this->usingCoreFont) {
2831 return $this->GetCharWidthNonCore($c, $addSubset);
2832 }
2833 else {
2834 return $this->GetCharWidthCore($c);
2835 }
2836 }
2837
2838 function GetStringWidth($s, $addSubset=true) {
2839 //Get width of a string in the current font
2840 $s = (string)$s;
2841 $cw = &$this->CurrentFont['cw'];
2842 $w = 0;
2843 $kerning = 0;
2844 $lastchar = 0;
2845 $nb_carac = 0;
2846 $nb_spaces = 0;
2847 // mPDF ITERATION
2848 if ($this->iterationCounter) $s = preg_replace('/{iteration ([a-zA-Z0-9_]+)}/', '\\1', $s);
2849
2850 if (!$this->usingCoreFont) {
2851 $s = str_replace("\xc2\xad",'',$s );
2852 $unicode = $this->UTF8StringToArray($s, $addSubset);
2853 if ($this->minwSpacing || $this->fixedlSpacing) {
2854 $nb_carac = count($unicode);
2855 $nb_spaces = mb_substr_count($s,' ', $this->mb_enc);
2856 }
2857 /*-- CJK-FONTS --*/
2858 if ($this->CurrentFont['type'] == 'Type0') { // CJK Adobe fonts
2859 foreach($unicode as $char) {
2860 if (isset($cw[$char])) { $w+=$cw[$char]; }
2861 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
2862 else { $w += 500; }
2863 }
2864 }
2865 else {
2866 /*-- END CJK-FONTS --*/
2867 foreach($unicode as $char) {
2868 if ($this->S && isset($this->upperCase[$char])) {
2869 $charw = $this->_getCharWidth($cw,$this->upperCase[$char]);
2870 if ($charw!==false) {
2871 $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
2872 $w+=$charw;
2873 }
2874 elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
2875 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
2876 else { $w += 500; }
2877 }
2878 else {
2879 $charw = $this->_getCharWidth($cw,$char);
2880 if ($charw!==false) { $w+=$charw; }
2881 elseif(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; }
2882 elseif(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; }
2883 else { $w += 500; }
2884 if ($this->kerning && $this->useKerning && $lastchar) {
2885 if (isset($this->CurrentFont['kerninfo'][$lastchar][$char])) {
2886 $kerning += $this->CurrentFont['kerninfo'][$lastchar][$char];
2887 }
2888 }
2889 $lastchar = $char;
2890 }
2891 }
2892 } // *CJK-FONTS*
2893
2894 }
2895 else {
2896 if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
2897 $s = str_replace(chr(173),'',$s );
2898 }
2899 $nb_carac = $l = strlen($s);
2900 if ($this->minwSpacing || $this->fixedlSpacing) {
2901 $nb_spaces = substr_count($s,' ');
2902 }
2903 for($i=0; $i<$l; $i++) {
2904 if ($this->S && isset($this->upperCase[ord($s[$i])])) {
2905 $charw = $cw[chr($this->upperCase[ord($s[$i])])];
2906 if ($charw!==false) {
2907 $charw = $charw*$this->smCapsScale * $this->smCapsStretch/100;
2908 $w+=$charw;
2909 }
2910 }
2911 else if (isset($cw[$s[$i]])) {
2912 $w += $cw[$s[$i]];
2913 }
2914 else if (isset($cw[ord($s[$i])])) {
2915 $w += $cw[ord($s[$i])];
2916 }
2917 if ($this->kerning && $this->useKerning && $i>0) {
2918 if (isset($this->CurrentFont['kerninfo'][$s[($i-1)]][$s[$i]])) {
2919 $kerning += $this->CurrentFont['kerninfo'][$s[($i-1)]][$s[$i]];
2920 }
2921 }
2922 }
2923 }
2924 unset($cw);
2925 if ($this->kerning && $this->useKerning) { $w += $kerning; }
2926 $w *= ($this->FontSize/ 1000);
2927 $w += (($nb_carac + $nb_spaces) * $this->fixedlSpacing) + ($nb_spaces * $this->minwSpacing);
2928 return ($w);
2929 }
2930
2931 function SetLineWidth($width) {
2932 //Set line width
2933 $this->LineWidth=$width;
2934 $lwout = (sprintf('%.3F w',$width*_MPDFK));
2935 if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineWidth']) && $this->pageoutput[$this->page]['LineWidth'] != $lwout) || !isset($this->pageoutput[$this->page]['LineWidth']) || $this->keep_block_together)) {
2936 $this->_out($lwout);
2937 }
2938 $this->pageoutput[$this->page]['LineWidth'] = $lwout;
2939 }
2940
2941 function Line($x1,$y1,$x2,$y2) {
2942 //Draw a line
2943 $this->_out(sprintf('%.3F %.3F m %.3F %.3F l S',$x1*_MPDFK,($this->h-$y1)*_MPDFK,$x2*_MPDFK,($this->h-$y2)*_MPDFK));
2944 }
2945
2946 function Arrow($x1,$y1,$x2,$y2,$headsize=3,$fill='B',$angle=25) {
2947 //F == fill //S == stroke //B == stroke and fill
2948 // angle = splay of arrowhead - 1 - 89 degrees
2949 if($fill=='F') $fill='f';
2950 elseif($fill=='FD' or $fill=='DF' or $fill=='B') $fill='B';
2951 else $fill='S';
2952 $a = atan2(($y2-$y1),($x2-$x1));
2953 $b = $a + deg2rad($angle);
2954 $c = $a - deg2rad($angle);
2955 $x3 = $x2 - ($headsize* cos($b));
2956 $y3 = $this->h-($y2 - ($headsize* sin($b)));
2957 $x4 = $x2 - ($headsize* cos($c));
2958 $y4 = $this->h-($y2 - ($headsize* sin($c)));
2959
2960 $x5 = $x3-($x3-$x4)/2; // mid point of base of arrowhead - to join arrow line to
2961 $y5 = $y3-($y3-$y4)/2;
2962
2963 $s = '';
2964 $s.=sprintf('%.3F %.3F m %.3F %.3F l S',$x1*_MPDFK,($this->h-$y1)*_MPDFK,$x5*_MPDFK,$y5*_MPDFK);
2965 $this->_out($s);
2966
2967 $s = '';
2968 $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);
2969 $s.=$fill;
2970 $this->_out($s);
2971 }
2972
2973
2974 function Rect($x,$y,$w,$h,$style='') {
2975 //Draw a rectangle
2976 if($style=='F') $op='f';
2977 elseif($style=='FD' or $style=='DF') $op='B';
2978 else $op='S';
2979 $this->_out(sprintf('%.3F %.3F %.3F %.3F re %s',$x*_MPDFK,($this->h-$y)*_MPDFK,$w*_MPDFK,-$h*_MPDFK,$op));
2980 }
2981
2982 function AddFont($family,$style='') {
2983 if(empty($family)) { return; }
2984 $family = strtolower($family);
2985 $style=strtoupper($style);
2986 $style=str_replace('U','',$style);
2987 if($style=='IB') $style='BI';
2988 $fontkey = $family.$style;
2989 // check if the font has been already added
2990 if(isset($this->fonts[$fontkey])) {
2991 return;
2992 }
2993
2994 /*-- CJK-FONTS --*/
2995 if (in_array($family,$this->available_CJK_fonts)) {
2996 if (empty($this->Big5_widths)) { require(_MPDF_PATH . 'includes/CJKdata.php'); }
2997 $this->AddCJKFont($family); // don't need to add style
2998 return;
2999 }
3000 /*-- END CJK-FONTS --*/
3001
3002 if ($this->usingCoreFont) { die("mPDF Error - problem with Font management"); }
3003
3004 $stylekey = $style;
3005 if (!$style) { $stylekey = 'R'; }
3006
3007 if (!isset($this->fontdata[$family][$stylekey]) || !$this->fontdata[$family][$stylekey]) {
3008 die('mPDF Error - Font is not supported - '.$family.' '.$style);
3009 }
3010
3011 $name = '';
3012 $originalsize = 0;
3013 $sip = false;
3014 $smp = false;
3015 $unAGlyphs = false; // mPDF 5.4.05
3016 $haskerninfo = false;
3017 $BMPselected = false;
3018 @include(_MPDF_TTFONTDATAPATH.$fontkey.'.mtx.php');
3019
3020 $ttffile = '';
3021 if (defined('_MPDF_SYSTEM_TTFONTS')) {
3022 $ttffile = _MPDF_SYSTEM_TTFONTS.$this->fontdata[$family][$stylekey];
3023 if (!file_exists($ttffile)) { $ttffile = ''; }
3024 }
3025 if (!$ttffile) {
3026 $ttffile = _MPDF_TTFONTPATH.$this->fontdata[$family][$stylekey];
3027 if (!file_exists($ttffile)) { die("mPDF Error - cannot find TTF TrueType font file - ".$ttffile); }
3028 }
3029 $ttfstat = stat($ttffile);
3030
3031 if (isset($this->fontdata[$family]['TTCfontID'][$stylekey])) { $TTCfontID = $this->fontdata[$family]['TTCfontID'][$stylekey]; }
3032 else { $TTCfontID = 0; }
3033
3034
3035 $BMPonly = false;
3036 if (in_array($family,$this->BMPonly)) { $BMPonly = true; }
3037 $regenerate = false;
3038 if ($BMPonly && !$BMPselected) { $regenerate = true; }
3039 else if (!$BMPonly && $BMPselected) { $regenerate = true; }
3040 if ($this->useKerning && !$haskerninfo) { $regenerate = true; }
3041 // mPDF 5.4.05
3042 if (isset($this->fontdata[$family]['unAGlyphs']) && $this->fontdata[$family]['unAGlyphs'] && !$unAGlyphs) {
3043 $regenerate = true;
3044 $unAGlyphs = true;
3045 }
3046 else if ((!isset($this->fontdata[$family]['unAGlyphs']) || !$this->fontdata[$family]['unAGlyphs']) && $unAGlyphs) {
3047 $regenerate = true;
3048 $unAGlyphs = false;
3049 }
3050 if (!isset($name) || $originalsize != $ttfstat['size'] || $regenerate) {
3051 if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
3052 $ttf = new TTFontFile();
3053 $ttf->getMetrics($ttffile, $TTCfontID, $this->debugfonts, $BMPonly, $this->useKerning, $unAGlyphs); // mPDF 5.4.05
3054 $cw = $ttf->charWidths;
3055 $kerninfo = $ttf->kerninfo;
3056 $haskerninfo = true;
3057 $name = preg_replace('/[ ()]/','',$ttf->fullName);
3058 $sip = $ttf->sipset;
3059 $smp = $ttf->smpset;
3060
3061 $desc= array('Ascent'=>round($ttf->ascent),
3062 'Descent'=>round($ttf->descent),
3063 'CapHeight'=>round($ttf->capHeight),
3064 'Flags'=>$ttf->flags,
3065 'FontBBox'=>'['.round($ttf->bbox[0])." ".round($ttf->bbox[1])." ".round($ttf->bbox[2])." ".round($ttf->bbox[3]).']',
3066 'ItalicAngle'=>$ttf->italicAngle,
3067 'StemV'=>round($ttf->stemV),
3068 'MissingWidth'=>round($ttf->defaultWidth));
3069 $panose = '';
3070 // mPDF 5.5.19
3071 if (count($ttf->panose)) {
3072 $panoseArray = array_merge(array($ttf->sFamilyClass, $ttf->sFamilySubClass), $ttf->panose);
3073 foreach($panoseArray as $value)
3074 $panose .= ' '.dechex($value);
3075 }
3076 $up = round($ttf->underlinePosition);
3077 $ut = round($ttf->underlineThickness);
3078 $originalsize = $ttfstat['size']+0;
3079 $type = 'TTF';
3080 //Generate metrics .php file
3081 $s='<?php'."\n";
3082 $s.='$name=\''.$name."';\n";
3083 $s.='$type=\''.$type."';\n";
3084 $s.='$desc='.var_export($desc,true).";\n";
3085 $s.='$up='.$up.";\n";
3086 $s.='$ut='.$ut.";\n";
3087 $s.='$ttffile=\''.$ttffile."';\n";
3088 $s.='$TTCfontID=\''.$TTCfontID."';\n";
3089 $s.='$originalsize='.$originalsize.";\n";
3090 if ($sip) $s.='$sip=true;'."\n";
3091 else $s.='$sip=false;'."\n";
3092 if ($smp) $s.='$smp=true;'."\n";
3093 else $s.='$smp=false;'."\n";
3094 if ($BMPonly) $s.='$BMPselected=true;'."\n";
3095 else $s.='$BMPselected=false;'."\n";
3096 $s.='$fontkey=\''.$fontkey."';\n";
3097 $s.='$panose=\''.$panose."';\n";
3098 if ($this->useKerning) {
3099 $s.='$kerninfo='.var_export($kerninfo,true).";\n";
3100 $s.='$haskerninfo=true;'."\n";
3101 }
3102 else $s.='$haskerninfo=false;'."\n";
3103 // mPDF 5.4.05
3104 if ($this->fontdata[$family]['unAGlyphs']) {
3105 $s.='$unAGlyphs=true;'."\n";
3106 }
3107 else $s.='$unAGlyphs=false;'."\n";
3108 $s.="?>";
3109 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
3110 $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.mtx.php',"w");
3111 fwrite($fh,$s,strlen($s));
3112 fclose($fh);
3113 $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.cw.dat',"wb");
3114 fwrite($fh,$cw,strlen($cw));
3115 fclose($fh);
3116 @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cgm');
3117 @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.z');
3118 @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cw127.php');
3119 @unlink(_MPDF_TTFONTDATAPATH.$fontkey.'.cw');
3120 }
3121 else if ($this->debugfonts) { $this->Error('Cannot write to the font caching directory - '._MPDF_TTFONTDATAPATH); }
3122 unset($ttf);
3123 }
3124 else {
3125 $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$fontkey.'.cw.dat');
3126 }
3127
3128 if (isset($this->fontdata[$family]['indic']) && $this->fontdata[$family]['indic']) { $indic = true; }
3129 else { $indic = false; }
3130 if (isset($this->fontdata[$family]['sip-ext']) && $this->fontdata[$family]['sip-ext']) { $sipext = $this->fontdata[$family]['sip-ext']; }
3131 else { $sipext = ''; }
3132
3133
3134 $i = count($this->fonts)+$this->extraFontSubsets+1;
3135 if ($sip || $smp) {
3136 $this->fonts[$fontkey] = array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'panose'=>$panose, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'ttffile'=>$ttffile, 'fontkey'=>$fontkey, 'subsets'=>array(0=>range(0,127)), 'subsetfontids'=>array($i), 'used'=>false, 'indic'=>$indic, 'sip'=>$sip, 'sipext'=>$sipext, 'smp'=>$smp, 'TTCfontID' => $TTCfontID, 'unAGlyphs' => false); // mPDF 5.4.05
3137 }
3138 else {
3139 $ss = array();
3140 for ($s=32; $s<128; $s++) { $ss[$s] = $s; }
3141 $this->fonts[$fontkey] = array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'panose'=>$panose, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'ttffile'=>$ttffile, 'fontkey'=>$fontkey, 'subset'=>$ss, 'used'=>false, 'indic'=>$indic, 'sip'=>$sip, 'sipext'=>$sipext, 'smp'=>$smp, 'TTCfontID' => $TTCfontID, 'unAGlyphs' => $unAGlyphs); // mPDF 5.4.05
3142 }
3143 if ($this->useKerning && $haskerninfo) { $this->fonts[$fontkey]['kerninfo'] = $kerninfo; }
3144 $this->FontFiles[$fontkey]=array('length1'=>$originalsize, 'type'=>"TTF", 'ttffile'=>$ttffile, 'sip'=>$sip, 'smp'=>$smp);
3145 unset($cw);
3146 }
3147
3148
3149
3150 function SetFont($family,$style='',$size=0, $write=true, $forcewrite=false) {
3151 $family=strtolower($family);
3152 if (!$this->onlyCoreFonts) {
3153 if ($family == 'sans' || $family == 'sans-serif') { $family = $this->sans_fonts[0]; }
3154 if ($family == 'serif') { $family = $this->serif_fonts[0]; }
3155 if ($family == 'mono' || $family == 'monospace') { $family = $this->mono_fonts[0]; }
3156 }
3157 if (isset($this->fonttrans[$family]) && $this->fonttrans[$family]) { $family = $this->fonttrans[$family]; }
3158 if($family=='') {
3159 if ($this->FontFamily) { $family=$this->FontFamily; }
3160 else if ($this->default_font) { $family=$this->default_font; }
3161 else { $this->Error("No font or default font set!"); }
3162 }
3163 $this->ReqFontStyle = $style; // required or requested style - used later for artificial bold/italic
3164
3165 if (($family == 'csymbol') || ($family == 'czapfdingbats') || ($family == 'ctimes') || ($family == 'ccourier') || ($family == 'chelvetica')) {
3166 if ($this->PDFA || $this->PDFX) {
3167 if ($family == 'csymbol' || $family == 'czapfdingbats') {
3168 $this->Error("Symbol and Zapfdingbats cannot be embedded in mPDF (required for PDFA1-b or PDFX/1-a).");
3169 }
3170 if ($family == 'ctimes' || $family == 'ccourier' || $family == 'chelvetica') {
3171 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.)"; }
3172 if ($family == 'chelvetica') { $family = 'sans'; }
3173 if ($family == 'ctimes') { $family = 'serif'; }
3174 if ($family == 'ccourier') { $family = 'mono'; }
3175 }
3176 $this->usingCoreFont = false;
3177 }
3178 else { $this->usingCoreFont = true; }
3179 if($family=='csymbol' || $family=='czapfdingbats') { $style=''; }
3180 }
3181 else { $this->usingCoreFont = false; }
3182
3183 $this->U=false;
3184 $this->S=false;
3185 if ($style) {
3186 $style=strtoupper($style);
3187 if(strpos($style,'U')!==false) {
3188 $this->U=true;
3189 $style=str_replace('U','',$style);
3190 }
3191 if(strpos($style,'S')!==false) {
3192 $this->S=true;
3193 // Small Caps
3194 if (empty($this->upperCase)) { @include(_MPDF_PATH.'includes/upperCase.php'); }
3195 $style=str_replace('S','',$style);
3196 }
3197 if ($style=='IB') $style='BI';
3198 }
3199 if ($size==0) $size=$this->FontSizePt;
3200
3201 $fontkey=$family.$style;
3202
3203 $stylekey = $style;
3204 if (!$stylekey) { $stylekey = "R"; }
3205
3206 if (!$this->onlyCoreFonts && !$this->usingCoreFont) {
3207 if(!isset($this->fonts[$fontkey]) || count($this->default_available_fonts) != count($this->available_unifonts) ) { // not already added
3208 /*-- CJK-FONTS --*/
3209 // CJK fonts
3210 if (in_array($fontkey,$this->available_CJK_fonts)) {
3211 if(!isset($this->fonts[$fontkey])) { // already added
3212 if (empty($this->Big5_widths)) { require(_MPDF_PATH . 'includes/CJKdata.php'); }
3213 $this->AddCJKFont($family); // don't need to add style
3214 }
3215 }
3216 // Test to see if requested font/style is available - or substitute
3217 else
3218 /*-- END CJK-FONTS --*/
3219 if (!in_array($fontkey,$this->available_unifonts)) {
3220 // If font[nostyle] exists - set it
3221 if (in_array($family,$this->available_unifonts)) {
3222 $style = '';
3223 }
3224
3225 // Else if only one font available - set it (assumes if only one font available it will not have a style)
3226 else if (count($this->available_unifonts) == 1) {
3227 $family = $this->available_unifonts[0];
3228 $style = '';
3229 }
3230
3231 else {
3232 $found = 0;
3233 // else substitute font of similar type
3234 if (in_array($family,$this->sans_fonts)) {
3235 $i = array_intersect($this->sans_fonts,$this->available_unifonts);
3236 if (count($i)) {
3237 $i = array_values($i);
3238 // with requested style if possible
3239 if (!in_array(($i[0].$style),$this->available_unifonts)) {
3240 $style = '';
3241 }
3242 $family = $i[0];
3243 $found = 1;
3244 }
3245 }
3246 else if (in_array($family,$this->serif_fonts)) {
3247 $i = array_intersect($this->serif_fonts,$this->available_unifonts);
3248 if (count($i)) {
3249 $i = array_values($i);
3250 // with requested style if possible
3251 if (!in_array(($i[0].$style),$this->available_unifonts)) {
3252 $style = '';
3253 }
3254 $family = $i[0];
3255 $found = 1;
3256 }
3257 }
3258 else if (in_array($family,$this->mono_fonts)) {
3259 $i = array_intersect($this->mono_fonts,$this->available_unifonts);
3260 if (count($i)) {
3261 $i = array_values($i);
3262 // with requested style if possible
3263 if (!in_array(($i[0].$style),$this->available_unifonts)) {
3264 $style = '';
3265 }
3266 $family = $i[0];
3267 $found = 1;
3268 }
3269 }
3270
3271 if (!$found) {
3272 // set first available font
3273 $fs = $this->available_unifonts[0];
3274 preg_match('/^([a-z_0-9\-]+)([BI]{0,2})$/',$fs,$fas); // Allow "-"
3275 // with requested style if possible
3276 $ws = $fas[1].$style;
3277 if (in_array($ws,$this->available_unifonts)) {
3278 $family = $fas[1]; // leave $style as is
3279 }
3280 else if (in_array($fas[1],$this->available_unifonts)) {
3281 // or without style
3282 $family = $fas[1];
3283 $style = '';
3284 }
3285 else {
3286 // or with the style specified
3287 $family = $fas[1];
3288 $style = $fas[2];
3289 }
3290 }
3291 }
3292 $fontkey = $family.$style;
3293 }
3294 }
3295 // try to add font (if not already added)
3296 $this->AddFont($family, $style);
3297
3298 //Test if font is already selected
3299 if($this->FontFamily == $family && $this->FontFamily == $this->currentfontfamily && $this->FontStyle == $style && $this->FontStyle == $this->currentfontstyle && $this->FontSizePt == $size && $this->FontSizePt == $this->currentfontsize && !$forcewrite) {
3300 return $family;
3301 }
3302
3303 $fontkey = $family.$style;
3304
3305 //Select it
3306 $this->FontFamily = $family;
3307 $this->FontStyle = $style;
3308 $this->FontSizePt = $size;
3309 $this->FontSize = $size / _MPDFK;
3310 $this->CurrentFont = &$this->fonts[$fontkey];
3311 if ($write) {
3312 $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
3313 if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
3314 $this->pageoutput[$this->page]['Font'] = $fontout;
3315 }
3316
3317
3318
3319 // Added - currentfont (lowercase) used in HTML2PDF
3320 $this->currentfontfamily=$family;
3321 $this->currentfontsize=$size;
3322 $this->currentfontstyle=$style.($this->U ? 'U' : '').($this->S ? 'S' : '');
3323 $this->setMBencoding('UTF-8');
3324 }
3325
3326 else { // if using core fonts
3327
3328
3329 if ($this->PDFA || $this->PDFX) {
3330 $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.');
3331 }
3332 $this->setMBencoding('windows-1252');
3333
3334 //Test if font is already selected
3335 if(($this->FontFamily == $family) AND ($this->FontStyle == $style) AND ($this->FontSizePt == $size) && !$forcewrite) {
3336 return $family;
3337 }
3338
3339 if (!isset($this->CoreFonts[$fontkey])) {
3340 if (in_array($family,$this->serif_fonts)) { $family = 'ctimes'; }
3341 else if (in_array($family,$this->mono_fonts)) { $family = 'ccourier'; }
3342 else { $family = 'chelvetica'; }
3343 $this->usingCoreFont = true;
3344 $fontkey = $family.$style;
3345 }
3346
3347 if(!isset($this->fonts[$fontkey])) {
3348 // STANDARD CORE FONTS
3349 if (isset($this->CoreFonts[$fontkey])) {
3350 //Load metric file
3351 $file=$family;
3352 if($family=='ctimes' || $family=='chelvetica' || $family=='ccourier') { $file.=strtolower($style); }
3353 $file.='.php';
3354 include(_MPDF_PATH.'font/'.$file);
3355 if(!isset($cw)) { $this->Error('Could not include font metric file'); }
3356 $i=count($this->fonts)+$this->extraFontSubsets+1;
3357 $this->fonts[$fontkey]=array('i'=>$i,'type'=>'core','name'=>$this->CoreFonts[$fontkey],'desc'=>$desc,'up'=>$up,'ut'=>$ut,'cw'=>$cw);
3358 if ($this->useKerning) { $this->fonts[$fontkey]['kerninfo'] = $kerninfo; }
3359 }
3360 else {
3361 die('mPDF error - Font not defined');
3362 }
3363 }
3364 //Test if font is already selected
3365 if(($this->FontFamily == $family) AND ($this->FontStyle == $style) AND ($this->FontSizePt == $size) && !$forcewrite) {
3366 return $family;
3367 }
3368 //Select it
3369 $this->FontFamily=$family;
3370 $this->FontStyle=$style;
3371 $this->FontSizePt=$size;
3372 $this->FontSize=$size/_MPDFK;
3373 $this->CurrentFont=&$this->fonts[$fontkey];
3374 if ($write) {
3375 $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
3376 if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
3377 $this->pageoutput[$this->page]['Font'] = $fontout;
3378 }
3379 // Added - currentfont (lowercase) used in HTML2PDF
3380 $this->currentfontfamily=$family;
3381 $this->currentfontsize=$size;
3382 $this->currentfontstyle=$style.($this->U ? 'U' : '').($this->S ? 'S' : '');
3383
3384 }
3385
3386 return $family;
3387 }
3388
3389 function SetFontSize($size,$write=true) {
3390 //Set font size in points
3391 if($this->FontSizePt==$size) return;
3392 $this->FontSizePt=$size;
3393 $this->FontSize=$size/_MPDFK;
3394 $this->currentfontsize=$size;
3395 if ($write) {
3396 $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
3397 // Edited mPDF 3.0
3398 if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
3399 $this->pageoutput[$this->page]['Font'] = $fontout;
3400 }
3401 }
3402
3403 function AddLink() {
3404 //Create a new internal link
3405 $n=count($this->links)+1;
3406 $this->links[$n]=array(0,0);
3407 return $n;
3408 }
3409
3410 function SetLink($link,$y=0,$page=-1) {
3411 //Set destination of internal link
3412 if($y==-1) $y=$this->y;
3413 if($page==-1) $page=$this->page;
3414 $this->links[$link]=array($page,$y);
3415 }
3416
3417 function Link($x,$y,$w,$h,$link) {
3418 $l = array($x*_MPDFK,$this->hPt-$y*_MPDFK,$w*_MPDFK,$h*_MPDFK,$link);
3419 if ($this->keep_block_together) { // Save to array - don't write yet
3420 $this->ktLinks[$this->page][]= $l;
3421 return;
3422 }
3423 else if ($this->table_rotate) { // *TABLES*
3424 $this->tbrot_Links[$this->page][]= $l; // *TABLES*
3425 return; // *TABLES*
3426 } // *TABLES*
3427 else if ($this->kwt) {
3428 $this->kwt_Links[$this->page][]= $l;
3429 return;
3430 }
3431
3432 if ($this->writingHTMLheader || $this->writingHTMLfooter) {
3433 $this->HTMLheaderPageLinks[]= $l;
3434 return;
3435 }
3436 //Put a link on the page
3437 $this->PageLinks[$this->page][]= $l;
3438 // Save cross-reference to Column buffer
3439 $ref = count($this->PageLinks[$this->page])-1; // *COLUMNS*
3440 $this->columnLinks[$this->CurrCol][INTVAL($this->x)][INTVAL($this->y)] = $ref; // *COLUMNS*
3441
3442 }
3443
3444 function Text($x,$y,$txt) {
3445 // Output a string
3446 // Called (internally) by Watermark and _tableWrite [rotated cells]
3447 // Expects input to be mb_encoded if necessary and RTL reversed
3448
3449 // ARTIFICIAL BOLD AND ITALIC
3450 $s = 'q ';
3451 if ($this->falseBoldWeight && strpos($this->ReqFontStyle,"B") !== false && strpos($this->FontStyle,"B") === false) {
3452 $s .= '2 Tr 1 J 1 j ';
3453 $s .= sprintf('%.3F w ',($this->FontSize/130)*_MPDFK*$this->falseBoldWeight);
3454 $tc = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3455 if($this->FillColor!=$tc) { $s .= $tc.' '; } // stroke (outline) = same colour as text(fill)
3456 }
3457 if (strpos($this->ReqFontStyle,"I") !== false && strpos($this->FontStyle,"I") === false) {
3458 $aix = '1 0 0.261799 1 %.3F %.3F Tm';
3459 }
3460 else { $aix = '%.3F %.3F Td'; }
3461
3462 if($this->ColorFlag) $s.=$this->TextColor.' ';
3463
3464 $this->CurrentFont['used']= true;
3465 if ($this->CurrentFont['type']=='TTF' && ($this->CurrentFont['sip'] || $this->CurrentFont['smp'])) {
3466 $txt2 = str_replace(chr(194).chr(160),chr(32),$txt);
3467 $txt2 = $this->UTF8toSubset($txt2);
3468 $s.=sprintf('BT '.$aix.' %s Tj ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$txt2);
3469 }
3470 else if (!$this->usingCoreFont) {
3471 $txt2 = str_replace(chr(194).chr(160),chr(32),$txt);
3472 $this->UTF8StringToArray($txt2); // this is just to add chars to subset list
3473 if ($this->kerning && $this->useKerning) { $s .= $this->_kern($txt2, '', $aix, $x, $y); }
3474 else {
3475 //Convert string to UTF-16BE without BOM
3476 $txt2= $this->UTF8ToUTF16BE($txt2, false);
3477 $s.=sprintf('BT '.$aix.' (%s) Tj ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$this->_escape($txt2));
3478 }
3479 }
3480 else {
3481 $txt2 = str_replace(chr(160),chr(32),$txt);
3482 if ($this->kerning && $this->useKerning) { $s .= $this->_kern($txt2, '', $aix, $x, $y); }
3483 else {
3484 $s.=sprintf('BT '.$aix.' (%s) Tj ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$this->_escape($txt2));
3485 }
3486 }
3487 if($this->U && $txt!='') {
3488 $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3489 if($this->FillColor!=$c) { $s.= ' '.$c.' '; }
3490 if (isset($this->CurrentFont['up'])) { $up=$this->CurrentFont['up']; }
3491 else { $up = -100; }
3492 $adjusty = (-$up/1000* $this->FontSize);
3493 if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
3494 else { $ut = 60/1000* $this->FontSize; }
3495 $olw = $this->LineWidth;
3496 $s.=' '.(sprintf(' %.3F w',$ut*_MPDFK));
3497 $s.=' '.$this->_dounderline($x,$y + $adjusty,$txt);
3498 $s.=' '.(sprintf(' %.3F w',$olw*_MPDFK));
3499 if($this->FillColor!=$c) { $s.= ' '.$this->FillColor.' '; }
3500 }
3501 // STRIKETHROUGH
3502 if($this->strike && $txt!='') {
3503 $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3504 if($this->FillColor!=$c) { $s.= ' '.$c.' '; }
3505 //Superscript and Subscript Y coordinate adjustment (now for striked-through texts)
3506 if (isset($this->CurrentFont['desc']['CapHeight'])) { $ch=$this->CurrentFont['desc']['CapHeight']; }
3507 else { $ch = 700; }
3508 $adjusty = (-$ch/1000* $this->FontSize) * 0.35;
3509 if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
3510 else { $ut = 60/1000* $this->FontSize; }
3511 $olw = $this->LineWidth;
3512 $s.=' '.(sprintf(' %.3F w',$ut*_MPDFK));
3513 $s.=' '.$this->_dounderline($x,$y+$adjusty,$txt);
3514 $s.=' '.(sprintf(' %.3F w',$olw*_MPDFK));
3515 if($this->FillColor!=$c) { $s.= ' '.$this->FillColor.' '; }
3516 }
3517 $s .= 'Q';
3518 $this->_out($s);
3519 }
3520
3521 /*-- DIRECTW --*/
3522 function WriteText($x,$y,$txt) {
3523 // Output a string using Text() but does encoding and text reversing of RTL
3524 $txt = $this->purify_utf8_text($txt);
3525 if ($this->text_input_as_HTML) {
3526 $txt = $this->all_entities_to_utf8($txt);
3527 }
3528 if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
3529 // DIRECTIONALITY
3530 if (preg_match("/([".$this->pregRTLchars."])/u", $txt)) { $this->biDirectional = true; } // *RTL*
3531 $this->magic_reverse_dir($txt, true, $this->directionality); // *RTL*
3532 // Font-specific ligature substitution for Indic fonts
3533 if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($txt); // *INDIC*
3534 $this->Text($x,$y,$txt);
3535 }
3536
3537 function WriteCell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='', $currentx=0) {
3538 //Output a cell using Cell() but does encoding and text reversing of RTL
3539 $txt = $this->purify_utf8_text($txt);
3540 if ($this->text_input_as_HTML) {
3541 $txt = $this->all_entities_to_utf8($txt);
3542 }
3543 if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
3544 // DIRECTIONALITY
3545 if (preg_match("/([".$this->pregRTLchars."])/u", $txt)) { $this->biDirectional = true; } // *RTL*
3546 $this->magic_reverse_dir($txt, true, $this->directionality); // *RTL*
3547 // Font-specific ligature substitution for Indic fonts
3548 if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($txt); // *INDIC*
3549 $this->Cell($w,$h,$txt,$border,$ln,$align,$fill,$link, $currentx);
3550 }
3551 /*-- END DIRECTW --*/
3552
3553
3554 function ResetSpacing() {
3555 if ($this->ws != 0) { $this->_out('BT 0 Tw ET'); }
3556 $this->ws=0;
3557 if ($this->charspacing != 0) { $this->_out('BT 0 Tc ET'); }
3558 $this->charspacing=0;
3559 }
3560
3561
3562 function SetSpacing($cs,$ws) {
3563 if (intval($cs*1000)==0) { $cs = 0; }
3564 if ($cs) { $this->_out(sprintf('BT %.3F Tc ET',$cs)); }
3565 else if ($this->charspacing != 0) { $this->_out('BT 0 Tc ET'); }
3566 $this->charspacing=$cs;
3567 if (intval($ws*1000)==0) { $ws = 0; }
3568 if ($ws) { $this->_out(sprintf('BT %.3F Tw ET',$ws)); }
3569 else if ($this->ws != 0) { $this->_out('BT 0 Tw ET'); }
3570 $this->ws=$ws;
3571 }
3572
3573 // WORD SPACING
3574 function GetJspacing($nc,$ns,$w,$inclCursive) {
3575 $ws = 0;
3576 $charspacing = 0;
3577 $ww = $this->jSWord;
3578 $ncx = $nc-1;
3579 if ($nc == 0) { return array(0,0); }
3580 else if ($nc==1) { $charspacing = $w; }
3581 // Only word spacing allowed / possible
3582 else if ($this->fixedlSpacing !== false || $inclCursive) {
3583 if ($ns) { $ws = $w / $ns; }
3584 }
3585 else if (!$ns) {
3586 $charspacing = $w / ($ncx );
3587 if (($this->jSmaxChar > 0) && ($charspacing > $this->jSmaxChar)) {
3588 $charspacing = $this->jSmaxChar;
3589 }
3590 }
3591 else if ($ns == ($ncx )) {
3592 $charspacing = $w / $ns;
3593 }
3594 else {
3595 if ($this->usingCoreFont) {
3596 $cs = ($w * (1 - $this->jSWord)) / ($ncx );
3597 if (($this->jSmaxChar > 0) && ($cs > $this->jSmaxChar)) {
3598 $cs = $this->jSmaxChar;
3599 $ww = 1 - (($cs * ($ncx ))/$w);
3600 }
3601 $charspacing = $cs;
3602 $ws = ($w * ($ww) ) / $ns;
3603 }
3604 else {
3605 $cs = ($w * (1 - $this->jSWord)) / ($ncx -$ns);
3606 if (($this->jSmaxChar > 0) && ($cs > $this->jSmaxChar)) {
3607 $cs = $this->jSmaxChar;
3608 $ww = 1 - (($cs * ($ncx -$ns))/$w);
3609 }
3610 $charspacing = $cs;
3611 $ws = (($w * ($ww) ) / $ns) - $charspacing;
3612 }
3613 }
3614 return array($charspacing,$ws);
3615 }
3616
3617 function Cell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='', $currentx=0, $lcpaddingL=0, $lcpaddingR=0, $valign='M', $spanfill=0, $abovefont=0, $belowfont=0, $exactWidth=false) {
3618 //Output a cell
3619 // Expects input to be mb_encoded if necessary and RTL reversed
3620 // NON_BREAKING SPACE
3621 if ($this->usingCoreFont) {
3622 $txt = str_replace(chr(160),chr(32),$txt);
3623 }
3624 else {
3625 $txt = str_replace(chr(194).chr(160),chr(32),$txt);
3626 }
3627
3628 $oldcolumn = $this->CurrCol;
3629 // Automatic page break
3630 // Allows PAGE-BREAK-AFTER = avoid to work
3631
3632 if (!$this->tableLevel && (($this->y+$this->divheight>$this->PageBreakTrigger) || ($this->y+$h>$this->PageBreakTrigger) ||
3633 ($this->y+($h*2)>$this->PageBreakTrigger && $this->blk[$this->blklvl]['page_break_after_avoid'])) and !$this->InFooter and $this->AcceptPageBreak()) {
3634 $x=$this->x;//Current X position
3635
3636
3637 // WORD SPACING
3638 $ws=$this->ws;//Word Spacing
3639 $charspacing=$this->charspacing;//Character Spacing
3640 $this->ResetSpacing();
3641
3642 $this->AddPage($this->CurOrientation);
3643 // Added to correct for OddEven Margins
3644 $x += $this->MarginCorrection;
3645 if ($currentx) {
3646 $currentx += $this->MarginCorrection;
3647 }
3648 $this->x=$x;
3649 // WORD SPACING
3650 $this->SetSpacing($charspacing,$ws);
3651 }
3652
3653 // Test: to put line through centre of cell: $this->Line($this->x,$this->y+($h/2),$this->x+50,$this->y+($h/2));
3654
3655 /*-- COLUMNS --*/
3656 // COLS
3657 // COLUMN CHANGE
3658 if ($this->CurrCol != $oldcolumn) {
3659 if ($currentx) {
3660 $currentx += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
3661 }
3662 $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
3663 }
3664
3665 // COLUMNS Update/overwrite the lowest bottom of printing y value for a column
3666 if ($this->ColActive) {
3667 if ($h) { $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y+$h; }
3668 else { $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y+$this->divheight; }
3669 }
3670 /*-- END COLUMNS --*/
3671
3672 // KEEP BLOCK TOGETHER Update/overwrite the lowest bottom of printing y value on first page
3673 if ($this->keep_block_together) {
3674 if ($h) { $this->ktBlock[$this->page]['bottom_margin'] = $this->y+$h; }
3675 // else { $this->ktBlock[$this->page]['bottom_margin'] = $this->y+$this->divheight; }
3676 }
3677
3678 if($w==0) $w = $this->w-$this->rMargin-$this->x;
3679 $s='';
3680 if($fill==1 && $this->FillColor) {
3681 if((isset($this->pageoutput[$this->page]['FillColor']) && $this->pageoutput[$this->page]['FillColor'] != $this->FillColor) || !isset($this->pageoutput[$this->page]['FillColor']) || $this->keep_block_together) { $s .= $this->FillColor.' '; }
3682 $this->pageoutput[$this->page]['FillColor'] = $this->FillColor;
3683 }
3684
3685
3686 $boxtop = $this->y;
3687 $boxheight = $h;
3688 $boxbottom = $this->y+$h;
3689
3690 if($txt!='') {
3691 // FONT SIZE - this determines the baseline caculation
3692 if ($this->linemaxfontsize && !$this->processingHeader) { $bfs = $this->linemaxfontsize; }
3693 else { $bfs = $this->FontSize; }
3694 //Calculate baseline Superscript and Subscript Y coordinate adjustment
3695 $bfx = $this->baselineC;
3696 $baseline = $bfx*$bfs;
3697 if($this->SUP) { $baseline += ($bfx-1.05)*$this->FontSize; }
3698 else if($this->SUB) { $baseline += ($bfx + 0.04)*$this->FontSize; }
3699 else if($this->bullet) { $baseline += ($bfx-0.7)*$this->FontSize; }
3700
3701 // Vertical align (for Images)
3702 if ($abovefont || $belowfont) { // from flowing block - valign always M
3703 $va = $abovefont + (0.5*$bfs);
3704 }
3705 else if ($this->lineheight_correction) {
3706 if ($valign == 'T') { $va = (0.5 * $bfs * $this->lineheight_correction); }
3707 else if ($valign == 'B') { $va = $h-(0.5 * $bfs * $this->lineheight_correction); }
3708 else { $va = 0.5*$h; } // Middle
3709 }
3710 else {
3711 if ($valign == 'T') { $va = (0.5 * $bfs * $this->default_lineheight_correction); }
3712 else if ($valign == 'B') { $va = $h-(0.5 * $bfs * $this->default_lineheight_correction); }
3713 else { $va = 0.5*$h; } // Middle
3714 }
3715
3716 // ONLY SET THESE IF WANT TO CONFINE BORDER +/- FILL TO FIT FONTSIZE - NOT FULL CELL AS IS ORIGINAL FUNCTION
3717 // spanfill or spanborder are set in FlowingBlock functions
3718 if ($spanfill || !empty($this->spanborddet) || $link!='') {
3719 $exth = 0.2; // Add to fontsize to increase height of background / link / border
3720 $boxtop = $this->y+$baseline+$va-($this->FontSize*(1+$exth/2)*(0.5+$bfx));
3721 $boxheight = $this->FontSize * (1+$exth);
3722 $boxbottom = $boxtop + $boxheight;
3723 }
3724 }
3725
3726 $bbw = $tbw = $lbw = $rbw = 0; // Border widths
3727 if (!empty($this->spanborddet)) {
3728 if (!isset($this->spanborddet['B'])) { $this->spanborddet['B'] = array('s' => 0, 'style' => '', 'w' => 0); }
3729 if (!isset($this->spanborddet['T'])) { $this->spanborddet['T'] = array('s' => 0, 'style' => '', 'w' => 0); }
3730 if (!isset($this->spanborddet['L'])) { $this->spanborddet['L'] = array('s' => 0, 'style' => '', 'w' => 0); }
3731 if (!isset($this->spanborddet['R'])) { $this->spanborddet['R'] = array('s' => 0, 'style' => '', 'w' => 0); }
3732 $bbw = $this->spanborddet['B']['w'];
3733 $tbw = $this->spanborddet['T']['w'];
3734 $lbw = $this->spanborddet['L']['w'];
3735 $rbw = $this->spanborddet['R']['w'];
3736 }
3737 if($fill==1 || $border==1 || !empty($this->spanborddet)) {
3738 if (!empty($this->spanborddet)) {
3739 if ($fill==1) {
3740 $s.=sprintf('%.3F %.3F %.3F %.3F re f ',($this->x-$lbw)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($w+$lbw+$rbw)*_MPDFK,(-$boxheight-$tbw-$bbw)*_MPDFK);
3741 }
3742 $s.= ' q ';
3743 $dashon = 3;
3744 $dashoff = 3.5;
3745 $dot = 2.5;
3746 if($tbw) {
3747 $short = 0;
3748 if ($this->spanborddet['T']['style'] == 'dashed') {
3749 $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$tbw*$dashon*_MPDFK,$tbw*$dashoff*_MPDFK);
3750 }
3751 else if ($this->spanborddet['T']['style'] == 'dotted') {
3752 $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$tbw*$dot*_MPDFK,-$tbw/2*_MPDFK);
3753 $short = $tbw/2;
3754 }
3755 else {
3756 $s.=' 0 j 0 J [] 0 d ';
3757 }
3758 $c = $this->SetDColor($this->spanborddet['T']['c'],true);
3759 if ($this->spanborddet['T']['style'] == 'double') {
3760 $s.=sprintf(' %s %.3F w ',$c,$tbw/3*_MPDFK);
3761 $xadj = $xadj2 = 0;
3762 if ($this->spanborddet['L']['style'] == 'double') { $xadj = $this->spanborddet['L']['w']*2/3; }
3763 if ($this->spanborddet['R']['style'] == 'double') { $xadj2 = $this->spanborddet['R']['w']*2/3; }
3764 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxtop+$tbw*5/6)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxtop+$tbw*5/6)*_MPDFK);
3765 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw+$xadj)*_MPDFK,($this->h-$boxtop+$tbw/6)*_MPDFK,($this->x+$w+$rbw-$short-$xadj2)*_MPDFK,($this->h-$boxtop+$tbw/6)*_MPDFK);
3766 }
3767 else {
3768 $s.=sprintf(' %s %.3F w ',$c,$tbw*_MPDFK);
3769 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxtop+$tbw/2)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxtop+$tbw/2)*_MPDFK);
3770 }
3771 }
3772 if($bbw) {
3773 $short = 0;
3774 if ($this->spanborddet['B']['style'] == 'dashed') {
3775 $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$bbw*$dashon*_MPDFK,$bbw*$dashoff*_MPDFK);
3776 }
3777 else if ($this->spanborddet['B']['style'] == 'dotted') {
3778 $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$bbw*$dot*_MPDFK,-$bbw/2*_MPDFK);
3779 $short = $bbw/2;
3780 }
3781 else {
3782 $s.=' 0 j 0 J [] 0 d ';
3783 }
3784 $c = $this->SetDColor($this->spanborddet['B']['c'],true);
3785 if ($this->spanborddet['B']['style'] == 'double') {
3786 $s.=sprintf(' %s %.3F w ',$c,$bbw/3*_MPDFK);
3787 $xadj = $xadj2 = 0;
3788 if ($this->spanborddet['L']['style'] == 'double') { $xadj = $this->spanborddet['L']['w']*2/3; }
3789 if ($this->spanborddet['R']['style'] == 'double') { $xadj2 = $this->spanborddet['R']['w']*2/3; }
3790 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw+$xadj)*_MPDFK,($this->h-$boxbottom-$bbw/6)*_MPDFK,($this->x+$w+$rbw-$short-$xadj2)*_MPDFK,($this->h-$boxbottom-$bbw/6)*_MPDFK);
3791 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxbottom-$bbw*5/6)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxbottom-$bbw*5/6)*_MPDFK);
3792 }
3793 else {
3794 $s.=sprintf(' %s %.3F w ',$c,$bbw*_MPDFK);
3795 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw)*_MPDFK,($this->h-$boxbottom-$bbw/2)*_MPDFK,($this->x+$w+$rbw-$short)*_MPDFK,($this->h-$boxbottom-$bbw/2)*_MPDFK);
3796 }
3797 }
3798 if($lbw) {
3799 $short = 0;
3800 if ($this->spanborddet['L']['style'] == 'dashed') {
3801 $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$lbw*$dashon*_MPDFK,$lbw*$dashoff*_MPDFK);
3802 }
3803 else if ($this->spanborddet['L']['style'] == 'dotted') {
3804 $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$lbw*$dot*_MPDFK,-$lbw/2*_MPDFK);
3805 $short = $lbw/2;
3806 }
3807 else {
3808 $s.=' 0 j 0 J [] 0 d ';
3809 }
3810 $c = $this->SetDColor($this->spanborddet['L']['c'],true);
3811 if ($this->spanborddet['L']['style'] == 'double') {
3812 $s.=sprintf(' %s %.3F w ',$c,$lbw/3*_MPDFK);
3813 $yadj = $yadj2 = 0;
3814 if ($this->spanborddet['T']['style'] == 'double') { $yadj = $this->spanborddet['T']['w']*2/3; }
3815 if ($this->spanborddet['B']['style'] == 'double') { $yadj2 = $this->spanborddet['B']['w']*2/3; }
3816 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw/6)*_MPDFK,($this->h-$boxtop+$tbw-$yadj)*_MPDFK,($this->x-$lbw/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short+$yadj2)*_MPDFK);
3817 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw*5/6)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x-$lbw*5/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
3818 }
3819 else {
3820 $s.=sprintf(' %s %.3F w ',$c,$lbw*_MPDFK);
3821 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x-$lbw/2)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x-$lbw/2)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
3822 }
3823 }
3824 if($rbw) {
3825 $short = 0;
3826 if ($this->spanborddet['R']['style'] == 'dashed') {
3827 $s.=sprintf(' 0 j 0 J [%.3F %.3F] 0 d ',$rbw*$dashon*_MPDFK,$rbw*$dashoff*_MPDFK);
3828 }
3829 else if ($this->spanborddet['R']['style'] == 'dotted') {
3830 $s.=sprintf(' 1 j 1 J [%.3F %.3F] %.3F d ',0.001,$rbw*$dot*_MPDFK,-$rbw/2*_MPDFK);
3831 $short = $rbw/2;
3832 }
3833 else {
3834 $s.=' 0 j 0 J [] 0 d ';
3835 }
3836 $c = $this->SetDColor($this->spanborddet['R']['c'],true);
3837 if ($this->spanborddet['R']['style'] == 'double') {
3838 $s.=sprintf(' %s %.3F w ',$c,$rbw/3*_MPDFK);
3839 $yadj = $yadj2 = 0;
3840 if ($this->spanborddet['T']['style'] == 'double') { $yadj = $this->spanborddet['T']['w']*2/3; }
3841 if ($this->spanborddet['B']['style'] == 'double') { $yadj2 = $this->spanborddet['B']['w']*2/3; }
3842 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw/6)*_MPDFK,($this->h-$boxtop+$tbw-$yadj)*_MPDFK,($this->x+$w+$rbw/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short+$yadj2)*_MPDFK);
3843 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw*5/6)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x+$w+$rbw*5/6)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
3844 }
3845 else {
3846 $s.=sprintf(' %s %.3F w ',$c,$rbw*_MPDFK);
3847 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($this->x+$w+$rbw/2)*_MPDFK,($this->h-$boxtop+$tbw)*_MPDFK,($this->x+$w+$rbw/2)*_MPDFK,($this->h-$boxbottom-$bbw+$short)*_MPDFK);
3848 }
3849 }
3850 $s.= ' Q ';
3851 }
3852 else {
3853 if ($fill==1) $op=($border==1) ? 'B' : 'f';
3854 else $op='S';
3855 $s.=sprintf('%.3F %.3F %.3F %.3F re %s ',$this->x*_MPDFK,($this->h-$boxtop)*_MPDFK,$w*_MPDFK,-$boxheight*_MPDFK,$op);
3856 }
3857 }
3858
3859 if(is_string($border)) {
3860 $x=$this->x;
3861 $y=$this->y;
3862 if(is_int(strpos($border,'L')))
3863 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-$boxtop)*_MPDFK,$x*_MPDFK,($this->h-($boxbottom))*_MPDFK);
3864 if(is_int(strpos($border,'T')))
3865 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-$boxtop)*_MPDFK,($x+$w)*_MPDFK,($this->h-$boxtop)*_MPDFK);
3866 if(is_int(strpos($border,'R')))
3867 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',($x+$w)*_MPDFK,($this->h-$boxtop)*_MPDFK,($x+$w)*_MPDFK,($this->h-($boxbottom))*_MPDFK);
3868 if(is_int(strpos($border,'B')))
3869 $s.=sprintf('%.3F %.3F m %.3F %.3F l S ',$x*_MPDFK,($this->h-($boxbottom))*_MPDFK,($x+$w)*_MPDFK,($this->h-($boxbottom))*_MPDFK);
3870 }
3871
3872 if($txt!='') {
3873 if ($exactWidth)
3874 $stringWidth = $w;
3875 else
3876 $stringWidth = $this->GetStringWidth($txt) + ( $this->charspacing * mb_strlen( $txt, $this->mb_enc ) / _MPDFK )
3877 + ( $this->ws * mb_substr_count( $txt, ' ', $this->mb_enc ) / _MPDFK );
3878
3879 // Set x OFFSET FOR PRINTING
3880 if($align=='R') {
3881 $dx=$w-$this->cMarginR - $stringWidth - $lcpaddingR;
3882 }
3883 elseif($align=='C') {
3884 $dx=(($w - $stringWidth )/2);
3885 }
3886 elseif($align=='L' or $align=='J') $dx=$this->cMarginL + $lcpaddingL;
3887 else $dx = 0;
3888
3889 if($this->ColorFlag) $s .='q '.$this->TextColor.' ';
3890
3891 // OUTLINE
3892 if($this->textparam['outline-s'] && !$this->S) { // mPDF 5.6.07
3893 $s .=' '.sprintf('%.3F w',$this->LineWidth*_MPDFK).' ';
3894 $s .=" $this->DrawColor ";
3895 $s .=" 2 Tr ";
3896 }
3897 else if ($this->falseBoldWeight && strpos($this->ReqFontStyle,"B") !== false && strpos($this->FontStyle,"B") === false && !$this->S) { // can't use together with OUTLINE or Small Caps
3898 $s .= ' 2 Tr 1 J 1 j ';
3899 $s .= ' '.sprintf('%.3F w',($this->FontSize/130)*_MPDFK*$this->falseBoldWeight).' ';
3900 $tc = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3901 if($this->FillColor!=$tc) { $s .= ' '.$tc.' '; } // stroke (outline) = same colour as text(fill)
3902 }
3903 else { $s .=" 0 Tr "; } // mPDF 5.6.07
3904
3905 if (strpos($this->ReqFontStyle,"I") !== false && strpos($this->FontStyle,"I") === false) { // Artificial italic
3906 $aix = '1 0 0.261799 1 %.3F %.3F Tm ';
3907 }
3908 else { $aix = '%.3F %.3F Td '; }
3909
3910 // THE TEXT
3911 $sub = '';
3912 $this->CurrentFont['used']= true;
3913
3914 // WORD SPACING
3915 // IF multibyte - Tw has no effect - need to use alternative method - do word spacing using an adjustment before each space
3916 if ($this->ws && !$this->usingCoreFont && !$this->CurrentFont['sip'] && !$this->CurrentFont['smp'] && !$this->S) {
3917 $sub .= ' BT 0 Tw ET ';
3918 if ($this->kerning && $this->useKerning) { $sub .= $this->_kern($txt, 'MBTw', $aix, ($this->x+$dx), ($this->y+$baseline+$va)); }
3919 else {
3920 $space = " ";
3921 //Convert string to UTF-16BE without BOM
3922 $space= $this->UTF8ToUTF16BE($space , false);
3923 $space=$this->_escape($space );
3924 $sub .=sprintf('BT '.$aix,($this->x+$dx)*_MPDFK,($this->h-($this->y+$baseline+$va))*_MPDFK);
3925 $t = explode(' ',$txt);
3926 $sub .=sprintf(' %.3F Tc [',$this->charspacing);
3927 $numt = count($t);
3928 for($i=0;$i<$numt;$i++) {
3929 $tx = $t[$i];
3930 //Convert string to UTF-16BE without BOM
3931 $tx = $this->UTF8ToUTF16BE($tx , false);
3932 $tx = $this->_escape($tx);
3933 $sub .=sprintf('(%s) ',$tx);
3934 if (($i+1)<$numt) {
3935 $adj = -($this->ws)*1000/$this->FontSizePt;
3936 $sub .=sprintf('%d(%s) ',$adj,$space);
3937 }
3938 }
3939 $sub .='] TJ ';
3940 $sub .=' ET';
3941 }
3942 }
3943 else {
3944 $txt2= $txt;
3945 if ($this->CurrentFont['type']=='TTF' && ($this->CurrentFont['sip'] || $this->CurrentFont['smp'])) {
3946 if ($this->S) { $sub .= $this->_smallCaps($txt2, 'SIPSMP', $aix, $dx, _MPDFK, $baseline, $va); }
3947 else {
3948 $txt2 = $this->UTF8toSubset($txt2);
3949 $sub .=sprintf('BT '.$aix.' %s Tj ET',($this->x+$dx)*_MPDFK,($this->h-($this->y+$baseline+$va))*_MPDFK,$txt2);
3950 }
3951 }
3952 else {
3953 if ($this->S) { $sub .= $this->_smallCaps($txt2, '', $aix, $dx, _MPDFK, $baseline, $va); }
3954 else if ($this->kerning && $this->useKerning) { $sub .= $this->_kern($txt2, '', $aix, ($this->x+$dx), ($this->y+$baseline+$va)); }
3955 else {
3956 if (!$this->usingCoreFont) {
3957 $txt2 = $this->UTF8ToUTF16BE($txt2, false);
3958 }
3959 $txt2=$this->_escape($txt2);
3960 $sub .=sprintf('BT '.$aix.' (%s) Tj ET',($this->x+$dx)*_MPDFK,($this->h-($this->y+$baseline+$va))*_MPDFK,$txt2);
3961 }
3962 }
3963 }
3964 // UNDERLINE
3965 if($this->U) {
3966 $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3967 if($this->FillColor!=$c) { $sub .= ' '.$c.' '; }
3968 if (isset($this->CurrentFont['up'])) { $up=$this->CurrentFont['up']; }
3969 else { $up = -100; }
3970 $adjusty = (-$up/1000* $this->FontSize);
3971 if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
3972 else { $ut = 60/1000* $this->FontSize; }
3973 $olw = $this->LineWidth;
3974 $sub .=' '.(sprintf(' %.3F w 0 j 0 J ',$ut*_MPDFK));
3975 $sub .=' '.$this->_dounderline($this->x+$dx,$this->y+$baseline+$va+$adjusty,$txt);
3976 $sub .=' '.(sprintf(' %.3F w 2 j 2 J ',$olw*_MPDFK));
3977 if($this->FillColor!=$c) { $sub .= ' '.$this->FillColor.' '; }
3978 }
3979
3980 // STRIKETHROUGH
3981 if($this->strike) {
3982 $c = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG
3983 if($this->FillColor!=$c) { $sub .= ' '.$c.' '; }
3984 //Superscript and Subscript Y coordinate adjustment (now for striked-through texts)
3985 if (isset($this->CurrentFont['desc']['CapHeight'])) { $ch=$this->CurrentFont['desc']['CapHeight']; }
3986 else { $ch = 700; }
3987 $adjusty = (-$ch/1000* $this->FontSize) * 0.35;
3988 if (isset($this->CurrentFont['ut'])) { $ut=$this->CurrentFont['ut']/1000* $this->FontSize; }
3989 else { $ut = 60/1000* $this->FontSize; }
3990 $olw = $this->LineWidth;
3991 $sub .=' '.(sprintf(' %.3F w 0 j 0 J ',$ut*_MPDFK));
3992 $sub .=' '.$this->_dounderline($this->x+$dx,$this->y+$baseline+$va+$adjusty,$txt);
3993 $sub .=' '.(sprintf(' %.3F w 2 j 2 J ',$olw*_MPDFK));
3994 if($this->FillColor!=$c) { $sub .= ' '.$this->FillColor.' '; }
3995 }
3996
3997 // TEXT SHADOW
3998 if ($this->textshadow) { // First to process is last in CSS comma separated shadows
3999 foreach($this->textshadow AS $ts) {
4000 $s .= ' q ';
4001 $s .= $this->SetTColor($ts['col'], true)."\n";
4002 if ($ts['col']{0}==5 && ord($ts['col']{4})<100) { // RGBa
4003 $s .= $this->SetAlpha(ord($ts['col']{4})/100, 'Normal', true, 'F')."\n";
4004 }
4005 else if ($ts['col']{0}==6 && ord($ts['col']{5})<100) { // CMYKa
4006 $s .= $this->SetAlpha(ord($ts['col']{5})/100, 'Normal', true, 'F')."\n";
4007 }
4008 else if ($ts['col']{0}==1 && $ts['col']{2}==1 && ord($ts['col']{3})<100) { // Gray
4009 $s .= $this->SetAlpha(ord($ts['col']{3})/100, 'Normal', true, 'F')."\n";
4010 }
4011 $s .= sprintf(' 1 0 0 1 %.4F %.4F cm', $ts['x']*_MPDFK, -$ts['y']*_MPDFK)."\n";
4012 $s .= $sub;
4013 $s .= ' Q ';
4014 }
4015 }
4016
4017 $s .= $sub;
4018
4019 // COLOR
4020 if($this->ColorFlag) $s .=' Q';
4021
4022 // LINK
4023 if($link!='') {
4024 $this->Link($this->x,$boxtop,$w,$boxheight,$link);
4025 }
4026 }
4027 if($s) $this->_out($s);
4028
4029 // WORD SPACING
4030 if ($this->ws && !$this->usingCoreFont) {
4031 $this->_out(sprintf('BT %.3F Tc ET',$this->charspacing));
4032 }
4033 $this->lasth=$h;
4034 if( strpos($txt,"\n") !== false) $ln=1; // cell recognizes \n from <BR> tag
4035 if($ln>0)
4036 {
4037 //Go to next line
4038 $this->y += $h;
4039 if($ln==1) {
4040 //Move to next line
4041 if ($currentx != 0) { $this->x=$currentx; }
4042 else { $this->x=$this->lMargin; }
4043 }
4044 }
4045 else $this->x+=$w;
4046
4047
4048 }
4049
4050
4051 function _kern($txt, $mode, $aix, $x, $y) {
4052 if ($mode == 'MBTw') { // Multibyte requiring word spacing
4053 $space = ' ';
4054 //Convert string to UTF-16BE without BOM
4055 $space= $this->UTF8ToUTF16BE($space , false);
4056 $space=$this->_escape($space );
4057 $s = sprintf(' BT '.$aix,$x*_MPDFK,($this->h-$y)*_MPDFK);
4058 $t = explode(' ',$txt);
4059 for($i=0;$i<count($t);$i++) {
4060 $tx = $t[$i];
4061
4062 $tj = '(';
4063 $unicode = $this->UTF8StringToArray($tx);
4064 for($ti=0;$ti<count($unicode);$ti++) {
4065 if ($ti > 0 && isset($this->CurrentFont['kerninfo'][$unicode[($ti-1)]][$unicode[$ti]])) {
4066 $kern = -$this->CurrentFont['kerninfo'][$unicode[($ti-1)]][$unicode[$ti]];
4067 $tj .= sprintf(')%d(',$kern);
4068 }
4069 $tc = code2utf($unicode[$ti]);
4070 $tc = $this->UTF8ToUTF16BE($tc, false);
4071 $tj .= $this->_escape($tc);
4072 }
4073 $tj .= ')';
4074 $s.=sprintf(' %.3F Tc [%s] TJ',$this->charspacing,$tj);
4075
4076
4077 if (($i+1)<count($t)) {
4078 $s.=sprintf(' %.3F Tc (%s) Tj',$this->ws+$this->charspacing,$space);
4079 }
4080 }
4081 $s.=' ET ';
4082 }
4083 else if (!$this->usingCoreFont) {
4084 $s = '';
4085 $tj = '(';
4086 $unicode = $this->UTF8StringToArray($txt);
4087 for($i=0;$i<count($unicode);$i++) {
4088 if ($i > 0 && isset($this->CurrentFont['kerninfo'][$unicode[($i-1)]][$unicode[$i]])) {
4089 $kern = -$this->CurrentFont['kerninfo'][$unicode[($i-1)]][$unicode[$i]];
4090 $tj .= sprintf(')%d(',$kern);
4091 }
4092 $tx = code2utf($unicode[$i]);
4093 $tx = $this->UTF8ToUTF16BE($tx, false);
4094 $tj .= $this->_escape($tx);
4095 }
4096 $tj .= ')';
4097 $s.=sprintf(' BT '.$aix.' [%s] TJ ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$tj);
4098 }
4099 else { // CORE Font
4100 $s = '';
4101 $tj = '(';
4102 $l = strlen($txt);
4103 for($i=0;$i<$l;$i++) {
4104 if ($i > 0 && isset($this->CurrentFont['kerninfo'][$txt[($i-1)]][$txt[$i]])) {
4105 $kern = -$this->CurrentFont['kerninfo'][$txt[($i-1)]][$txt[$i]];
4106 $tj .= sprintf(')%d(',$kern);
4107 }
4108 $tj .= $this->_escape($txt[$i]);
4109 }
4110 $tj .= ')';
4111 $s.=sprintf(' BT '.$aix.' [%s] TJ ET ',$x*_MPDFK,($this->h-$y)*_MPDFK,$tj);
4112 }
4113
4114 return $s;
4115 }
4116
4117
4118 function _smallCaps($txt, $mode, $aix, $dx, $k, $baseline, $va) {
4119 $upp = false;
4120 $str = array();
4121 $bits = array();
4122 if (!$this->usingCoreFont) {
4123 $unicode = $this->UTF8StringToArray($txt);
4124 foreach($unicode as $char) {
4125 if ($this->ws && $char == 32) { // space
4126 if (count($str)) { $bits[] = array($upp, $str, false); }
4127 $bits[] = array(false, array(32), true);
4128 $str = array();
4129 $upp = false;
4130 }
4131 else if (isset($this->upperCase[$char])) {
4132 if (!$upp) {
4133 if (count($str)) { $bits[] = array($upp, $str, false); }
4134 $str = array();
4135 }
4136 $str[] = $this->upperCase[$char];
4137 if ((!isset($this->CurrentFont['sip']) || !$this->CurrentFont['sip']) && (!isset($this->CurrentFont['smp']) || !$this->CurrentFont['smp'])) {
4138 $this->CurrentFont['subset'][$this->upperCase[$char]] = $this->upperCase[$char];
4139 }
4140 $upp = true;
4141 }
4142 else {
4143 if ($upp) {
4144 if (count($str)) { $bits[] = array($upp, $str, false); }
4145 $str = array();
4146 }
4147 $str[] = $char;
4148 $upp = false;
4149 }
4150 }
4151 }
4152 else {
4153 for($i=0;$i<strlen($txt);$i++) {
4154 if (isset($this->upperCase[ord($txt[$i])]) && $this->upperCase[ord($txt[$i])] < 256) {
4155 if (!$upp) {
4156 if (count($str)) { $bits[] = array($upp, $str, false); }
4157 $str = array();
4158 }
4159 $str[] = $this->upperCase[ord($txt[$i])];
4160 $upp = true;
4161 }
4162 else {
4163 if ($upp) {
4164 if (count($str)) { $bits[] = array($upp, $str, false); }
4165 $str = array();
4166 }
4167 $str[] = ord($txt[$i]);
4168 $upp = false;
4169 }
4170 }
4171 }
4172 if (count($str)) { $bits[] = array($upp, $str, false); }
4173
4174 $fid = $this->CurrentFont['i'];
4175
4176 $s=sprintf(' BT '.$aix,($this->x+$dx)*$k,($this->h-($this->y+$baseline+$va))*$k);
4177 foreach($bits AS $b) {
4178 if ($b[0]) { $upp = true; }
4179 else { $upp = false; }
4180
4181 $size = count ($b[1]);
4182 $txt = '';
4183 for ($i = 0; $i < $size; $i++) {
4184 $txt .= code2utf($b[1][$i]);
4185 }
4186 if ($this->usingCoreFont) {
4187 $txt = utf8_decode($txt);
4188 }
4189 if ($mode == 'SIPSMP') {
4190 $txt = $this->UTF8toSubset($txt);
4191 }
4192 else {
4193 if (!$this->usingCoreFont) {
4194 $txt = $this->UTF8ToUTF16BE($txt, false);
4195 }
4196 $txt=$this->_escape($txt);
4197 $txt = '('.$txt.')';
4198 }
4199 if ($b[2]) { // space
4200 $s.=sprintf(' /F%d %.3F Tf %d Tz', $fid, $this->FontSizePt, 100);
4201 $s.=sprintf(' %.3F Tc', ($this->charspacing+$this->ws));
4202 $s.=sprintf(' %s Tj', $txt);
4203 }
4204 else if ($upp) {
4205 $s.=sprintf(' /F%d %.3F Tf', $fid, $this->FontSizePt*$this->smCapsScale);
4206 $s.=sprintf(' %d Tz', $this->smCapsStretch);
4207 $s.=sprintf(' %.3F Tc', ($this->charspacing*100/$this->smCapsStretch));
4208 $s.=sprintf(' %s Tj', $txt);
4209 }
4210 else {
4211 $s.=sprintf(' /F%d %.3F Tf %d Tz', $fid, $this->FontSizePt, 100);
4212 $s.=sprintf(' %.3F Tc', ($this->charspacing));
4213 $s.=sprintf(' %s Tj', $txt);
4214 }
4215 }
4216 $s.=' ET ';
4217 return $s;
4218 }
4219
4220
4221 function MultiCell($w,$h,$txt,$border=0,$align='',$fill=0,$link='',$directionality='ltr',$encoded=false)
4222 {
4223 // Parameter (pre-)encoded - When called internally from ToC or textarea: mb_encoding already done - but not reverse RTL/Indic
4224 if (!$encoded) {
4225 $txt = $this->purify_utf8_text($txt);
4226 if ($this->text_input_as_HTML) {
4227 $txt = $this->all_entities_to_utf8($txt);
4228 }
4229 if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
4230 // Font-specific ligature substitution for Indic fonts
4231 else if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) { // *INDIC*
4232 $this->ConvertIndic($tmp); // *INDIC*
4233 } // *INDIC*
4234 if (preg_match("/([".$this->pregRTLchars."])/u", $txt)) { $this->biDirectional = true; } // *RTL*
4235 }
4236 if (!$align) { $align = $this->defaultAlign; }
4237
4238 //Output text with automatic or explicit line breaks
4239 $cw=&$this->CurrentFont['cw'];
4240 if($w==0) $w=$this->w-$this->rMargin-$this->x;
4241
4242 $wmax = ($w - ($this->cMarginL+$this->cMarginR));
4243 if ($this->usingCoreFont) {
4244 $s=str_replace("\r",'',$txt);
4245 $nb=strlen($s);
4246 while($nb>0 and $s[$nb-1]=="\n") $nb--;
4247 }
4248 else {
4249 $s=str_replace("\r",'',$txt);
4250 $nb=mb_strlen($s, $this->mb_enc );
4251 while($nb>0 and mb_substr($s,$nb-1,1,$this->mb_enc )=="\n") $nb--;
4252 }
4253 $b=0;
4254 if($border) {
4255 if($border==1) {
4256 $border='LTRB';
4257 $b='LRT';
4258 $b2='LR';
4259 }
4260 else {
4261 $b2='';
4262 if(is_int(strpos($border,'L'))) $b2.='L';
4263 if(is_int(strpos($border,'R'))) $b2.='R';
4264 $b=is_int(strpos($border,'T')) ? $b2.'T' : $b2;
4265 }
4266 }
4267 $sep=-1;
4268 $i=0;
4269 $j=0;
4270 $l=0;
4271 $ns=0;
4272 $nl=1;
4273
4274
4275
4276 if (!$this->usingCoreFont) {
4277 $checkCursive=false;
4278 if ($this->biDirectional) { $checkCursive=true; }
4279 else if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) { $checkCursive=true; } // *INDIC*
4280 while($i<$nb) {
4281 //Get next character
4282 $c = mb_substr($s,$i,1,$this->mb_enc );
4283 if($c == "\n") {
4284 //Explicit line break
4285 // WORD SPACING
4286 $this->ResetSpacing();
4287 $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
4288 // DIRECTIONALITY
4289 $this->magic_reverse_dir($tmp, true, $directionality); // *RTL*
4290
4291 $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
4292 $i++;
4293 $sep=-1;
4294 $j=$i;
4295 $l=0;
4296 $ns=0;
4297 $nl++;
4298 if($border and $nl==2) $b=$b2;
4299 continue;
4300 }
4301 if($c == " ") {
4302 $sep=$i;
4303 $ls=$l;
4304 $ns++;
4305 }
4306
4307 $l += $this->GetCharWidthNonCore($c);
4308
4309 if($l>$wmax) {
4310 //Automatic line break
4311 if($sep==-1) { // Only one word
4312 if($i==$j) $i++;
4313 // WORD SPACING
4314 $this->ResetSpacing();
4315 $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
4316 // DIRECTIONALITY
4317 $this->magic_reverse_dir($tmp, true, $directionality); // *RTL*
4318
4319 $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
4320 }
4321 else {
4322 $tmp = rtrim(mb_substr($s,$j,$sep-$j,$this->mb_enc));
4323 if($align=='J') {
4324 //////////////////////////////////////////
4325 // JUSTIFY J using Unicode fonts (Word spacing doesn't work)
4326 // WORD SPACING UNICODE
4327 // Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
4328 $tmp = str_replace(chr(194).chr(160),chr(32),$tmp );
4329 $len_ligne = $this->GetStringWidth($tmp );
4330 $nb_carac = mb_strlen( $tmp , $this->mb_enc ) ;
4331 $nb_spaces = mb_substr_count( $tmp ,' ', $this->mb_enc ) ;
4332
4333 $inclCursive=false;
4334 if ($checkCursive) {
4335 if (preg_match("/([".$this->pregRTLchars."])/u", $tmp)) { $inclCursive = true; } // *RTL*
4336 if (preg_match("/([".$this->pregHIchars.$this->pregBNchars.$this->pregPAchars."])/u", $tmp)) { $inclCursive = true; } // *INDIC*
4337 }
4338 list($charspacing,$ws) = $this->GetJspacing($nb_carac,$nb_spaces,((($wmax) - $len_ligne) * _MPDFK),$inclCursive);
4339 $this->SetSpacing($charspacing,$ws);
4340 //////////////////////////////////////////
4341 }
4342
4343 // DIRECTIONALITY
4344 $this->magic_reverse_dir($tmp, true, $directionality); // *RTL*
4345
4346 $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
4347 $i=$sep+1;
4348 }
4349 $sep=-1;
4350 $j=$i;
4351 $l=0;
4352 $ns=0;
4353 $nl++;
4354 if($border and $nl==2) $b=$b2;
4355 }
4356 else $i++;
4357 }
4358 //Last chunk
4359 // WORD SPACING
4360
4361 $this->ResetSpacing();
4362
4363 }
4364
4365
4366 else {
4367
4368 while($i<$nb) {
4369 //Get next character
4370 $c=$s[$i];
4371 if($c == "\n") {
4372 //Explicit line break
4373 // WORD SPACING
4374 $this->ResetSpacing();
4375 $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link);
4376 $i++;
4377 $sep=-1;
4378 $j=$i;
4379 $l=0;
4380 $ns=0;
4381 $nl++;
4382 if($border and $nl==2) $b=$b2;
4383 continue;
4384 }
4385 if($c == " ") {
4386 $sep=$i;
4387 $ls=$l;
4388 $ns++;
4389 }
4390
4391 $l += $this->GetCharWidthCore($c);
4392 if($l>$wmax) {
4393 //Automatic line break
4394 if($sep==-1) {
4395 if($i==$j) $i++;
4396 // WORD SPACING
4397 $this->ResetSpacing();
4398 $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link);
4399 }
4400 else {
4401 if($align=='J') {
4402 $tmp = rtrim(substr($s,$j,$sep-$j));
4403 //////////////////////////////////////////
4404 // JUSTIFY J using Unicode fonts (Word spacing doesn't work)
4405 // WORD SPACING NON_UNICDOE/CJK
4406 // Change NON_BREAKING SPACE to spaces so they are 'spaced' properly
4407 $tmp = str_replace(chr(160),chr(32),$tmp);
4408 $len_ligne = $this->GetStringWidth($tmp );
4409 $nb_carac = strlen( $tmp ) ;
4410 $nb_spaces = substr_count( $tmp ,' ' ) ;
4411 list($charspacing,$ws) = $this->GetJspacing($nb_carac,$nb_spaces,((($wmax) - $len_ligne) * _MPDFK),false);
4412 $this->SetSpacing($charspacing,$ws);
4413 //////////////////////////////////////////
4414 }
4415 $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill,$link);
4416 $i=$sep+1;
4417 }
4418 $sep=-1;
4419 $j=$i;
4420 $l=0;
4421 $ns=0;
4422 $nl++;
4423 if($border and $nl==2) $b=$b2;
4424 }
4425 else $i++;
4426 }
4427 //Last chunk
4428 // WORD SPACING
4429
4430 $this->ResetSpacing();
4431
4432 }
4433 //Last chunk
4434 if($border and is_int(strpos($border,'B'))) $b.='B';
4435 if (!$this->usingCoreFont) {
4436 $tmp = rtrim(mb_substr($s,$j,$i-$j,$this->mb_enc));
4437 // DIRECTIONALITY
4438 $this->magic_reverse_dir($tmp, true, $directionality); // *RTL*
4439 $this->Cell($w,$h,$tmp,$b,2,$align,$fill,$link);
4440 }
4441 else { $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill,$link); }
4442 $this->x=$this->lMargin;
4443 }
4444
4445
4446 /*-- DIRECTW --*/
4447 function Write($h,$txt,$currentx=0,$link='',$directionality='ltr',$align='') {
4448 if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
4449 if (empty($this->directw)) { $this->directw = new directw($this); }
4450 $this->directw->Write($h,$txt,$currentx,$link,$directionality,$align);
4451 }
4452 /*-- END DIRECTW --*/
4453
4454
4455 /*-- HTML-CSS --*/
4456 function saveInlineProperties() {
4457 $saved = array();
4458 $saved[ 'family' ] = $this->FontFamily;
4459 $saved[ 'style' ] = $this->FontStyle;
4460 $saved[ 'sizePt' ] = $this->FontSizePt;
4461 $saved[ 'size' ] = $this->FontSize;
4462 $saved[ 'HREF' ] = $this->HREF;
4463 $saved[ 'underline' ] = $this->U;
4464 $saved[ 'smCaps' ] = $this->S;
4465 $saved[ 'strike' ] = $this->strike;
4466 $saved[ 'textshadow' ] = $this->textshadow;
4467 $saved[ 'SUP' ] = $this->SUP;
4468 $saved[ 'SUB' ] = $this->SUB;
4469 $saved[ 'linewidth' ] = $this->LineWidth;
4470 $saved[ 'drawcolor' ] = $this->DrawColor;
4471 $saved[ 'textparam' ] = $this->textparam;
4472 $saved[ 'toupper' ] = $this->toupper;
4473 $saved[ 'tolower' ] = $this->tolower;
4474 $saved[ 'capitalize' ] = $this->capitalize;
4475 $saved[ 'fontkerning' ] = $this->kerning;
4476 $saved[ 'lSpacingCSS' ] = $this->lSpacingCSS;
4477 $saved[ 'wSpacingCSS' ] = $this->wSpacingCSS;
4478 $saved[ 'I' ] = $this->I;
4479 $saved[ 'B' ] = $this->B;
4480 $saved[ 'colorarray' ] = $this->colorarray;
4481 $saved[ 'bgcolorarray' ] = $this->spanbgcolorarray;
4482 $saved[ 'border' ] = $this->spanborddet;
4483 $saved[ 'color' ] = $this->TextColor;
4484 $saved[ 'bgcolor' ] = $this->FillColor;
4485 $saved[ 'lang' ] = $this->currentLang;
4486 $saved[ 'display_off' ] = $this->inlineDisplayOff;
4487
4488 return $saved;
4489 }
4490
4491 function restoreInlineProperties( &$saved) {
4492 $FontFamily = $saved[ 'family' ];
4493 $this->FontStyle = $saved[ 'style' ];
4494 $this->FontSizePt = $saved[ 'sizePt' ];
4495 $this->FontSize = $saved[ 'size' ];
4496
4497 $this->currentLang = $saved['lang'];
4498 if ($this->useLang && !$this->usingCoreFont) {
4499 if ($this->currentLang != $this->default_lang && ((strlen($this->currentLang) == 5 && $this->currentLang != 'UTF-8') || strlen($this->currentLang ) == 2)) {
4500 list ($coreSuitable,$mpdf_pdf_unifonts) = GetLangOpts($this->currentLang, $this->useAdobeCJK);
4501 if ($mpdf_pdf_unifonts) { $this->RestrictUnicodeFonts($mpdf_pdf_unifonts); }
4502 else { $this->RestrictUnicodeFonts($this->default_available_fonts ); }
4503 }
4504 else {
4505 $this->RestrictUnicodeFonts($this->default_available_fonts );
4506 }
4507 }
4508
4509 $this->ColorFlag = ($this->FillColor != $this->TextColor); //Restore ColorFlag as well
4510
4511 $this->HREF = $saved[ 'HREF' ];
4512 $this->U = $saved[ 'underline' ];
4513 $this->S = $saved[ 'smCaps' ];
4514 $this->strike = $saved[ 'strike' ];
4515 $this->textshadow = $saved[ 'textshadow' ];
4516 $this->SUP = $saved[ 'SUP' ];
4517 $this->SUB = $saved[ 'SUB' ];
4518 $this->LineWidth = $saved[ 'linewidth' ];
4519 $this->DrawColor = $saved[ 'drawcolor' ];
4520 $this->textparam = $saved[ 'textparam' ];
4521 $this->inlineDisplayOff = $saved['display_off'];
4522
4523 $this->toupper = $saved[ 'toupper' ];
4524 $this->tolower = $saved[ 'tolower' ];
4525 $this->capitalize = $saved[ 'capitalize' ];
4526 $this->kerning = $saved[ 'fontkerning' ];
4527 $this->lSpacingCSS = $saved[ 'lSpacingCSS' ];
4528 if (($this->lSpacingCSS || $this->lSpacingCSS==='0') && strtoupper($this->lSpacingCSS) != 'NORMAL') {
4529 $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize);
4530 }
4531 else { $this->fixedlSpacing = false; }
4532 $this->wSpacingCSS = $saved[ 'wSpacingCSS' ];
4533 if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') {
4534 $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize);
4535 }
4536 else { $this->minwSpacing = 0; }
4537
4538 $this->SetFont($FontFamily, $saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : ''),$saved[ 'sizePt' ],false);
4539
4540 $this->currentfontstyle = $saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : '');
4541 $this->currentfontsize = $saved[ 'sizePt' ];
4542 $this->SetStylesArray(array('S'=>$this->S, 'U'=>$this->U, 'B'=>$saved[ 'B' ], 'I'=>$saved[ 'I' ]));
4543
4544 $this->TextColor = $saved[ 'color' ];
4545 $this->FillColor = $saved[ 'bgcolor' ];
4546 $this->colorarray = $saved[ 'colorarray' ];
4547 $cor = $saved[ 'colorarray' ];
4548 if ($cor) $this->SetTColor($cor);
4549 $this->spanbgcolorarray = $saved[ 'bgcolorarray' ];
4550 $cor = $saved[ 'bgcolorarray' ];
4551 if ($cor) $this->SetFColor($cor);
4552 $this->spanborddet = $saved[ 'border' ];
4553 }
4554
4555
4556
4557 // Used when ColActive for tables - updated to return first block with background fill OR borders
4558 function GetFirstBlockFill() {
4559 // Returns the first blocklevel that uses a bgcolor fill
4560 $startfill = 0;
4561 for ($i=1;$i<=$this->blklvl;$i++) {
4562 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'] ) {
4563 $startfill = $i;
4564 break;
4565 }
4566 }
4567 return $startfill;
4568 }
4569
4570 function SetBlockFill($blvl) {
4571 if ($this->blk[$blvl]['bgcolor']) {
4572 $this->SetFColor($this->blk[$blvl]['bgcolorarray']);
4573 return 1;
4574 }
4575 else {
4576 $this->SetFColor($this->ConvertColor(255));
4577 return 0;
4578 }
4579 }
4580
4581
4582 //-------------------------FLOWING BLOCK------------------------------------//
4583 //The following functions were originally written by Damon Kohler //
4584 //--------------------------------------------------------------------------//
4585
4586 function saveFont() {
4587 $saved = array();
4588 $saved[ 'family' ] = $this->FontFamily;
4589 $saved[ 'style' ] = $this->FontStyle;
4590 $saved[ 'sizePt' ] = $this->FontSizePt;
4591 $saved[ 'size' ] = $this->FontSize;
4592 $saved[ 'curr' ] = &$this->CurrentFont;
4593 $saved[ 'color' ] = $this->TextColor;
4594 $saved[ 'spanbgcolor' ] = $this->spanbgcolor;
4595 $saved[ 'spanbgcolorarray' ] = $this->spanbgcolorarray;
4596 $saved[ 'bord' ] = $this->spanborder;
4597 $saved[ 'border' ] = $this->spanborddet;
4598 $saved[ 'HREF' ] = $this->HREF;
4599 $saved[ 'underline' ] = $this->U;
4600 $saved[ 'smCaps' ] = $this->S;
4601 $saved[ 'strike' ] = $this->strike;
4602 $saved[ 'textshadow' ] = $this->textshadow;
4603 $saved[ 'SUP' ] = $this->SUP;
4604 $saved[ 'SUB' ] = $this->SUB;
4605 $saved[ 'linewidth' ] = $this->LineWidth;
4606 $saved[ 'drawcolor' ] = $this->DrawColor;
4607 $saved[ 'textparam' ] = $this->textparam;
4608 $saved[ 'ReqFontStyle' ] = $this->ReqFontStyle;
4609 $saved[ 'fontkerning' ] = $this->kerning;
4610 $saved[ 'fixedlSpacing' ] = $this->fixedlSpacing;
4611 $saved[ 'minwSpacing' ] = $this->minwSpacing;
4612 return $saved;
4613 }
4614
4615 function restoreFont( &$saved, $write=true) {
4616 if (!isset($saved) || empty($saved)) return;
4617
4618 $this->FontFamily = $saved[ 'family' ];
4619 $this->FontStyle = $saved[ 'style' ];
4620 $this->FontSizePt = $saved[ 'sizePt' ];
4621 $this->FontSize = $saved[ 'size' ];
4622 $this->CurrentFont = &$saved[ 'curr' ];
4623 $this->TextColor = $saved[ 'color' ];
4624 $this->spanbgcolor = $saved[ 'spanbgcolor' ];
4625 $this->spanbgcolorarray = $saved[ 'spanbgcolorarray' ];
4626 $this->spanborder = $saved[ 'bord' ];
4627 $this->spanborddet = $saved[ 'border' ];
4628 $this->ColorFlag = ($this->FillColor != $this->TextColor); //Restore ColorFlag as well
4629 $this->HREF = $saved[ 'HREF' ];
4630 $this->U = $saved[ 'underline' ];
4631 $this->S = $saved[ 'smCaps' ];
4632 $this->kerning = $saved[ 'fontkerning' ];
4633 $this->fixedlSpacing = $saved[ 'fixedlSpacing' ];
4634 $this->minwSpacing = $saved[ 'minwSpacing' ];
4635 $this->strike = $saved[ 'strike' ];
4636 $this->textshadow = $saved[ 'textshadow' ];
4637 $this->SUP = $saved[ 'SUP' ];
4638 $this->SUB = $saved[ 'SUB' ];
4639 $this->LineWidth = $saved[ 'linewidth' ];
4640 $this->DrawColor = $saved[ 'drawcolor' ];
4641 $this->textparam = $saved[ 'textparam' ];
4642 if ($write) {
4643 $this->SetFont($saved[ 'family' ],$saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : ''),$saved[ 'sizePt' ],true,true); // force output
4644 $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
4645 if($this->page>0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']) || $this->keep_block_together)) { $this->_out($fontout); }
4646 $this->pageoutput[$this->page]['Font'] = $fontout;
4647 }
4648 else
4649 $this->SetFont($saved[ 'family' ],$saved[ 'style' ].($this->U ? 'U' : '').($this->S ? 'S' : ''),$saved[ 'sizePt' ]);
4650 $this->ReqFontStyle = $saved[ 'ReqFontStyle' ];
4651 }
4652
4653 function newFlowingBlock( $w, $h, $a = '', $is_table = false, $is_list = false, $blockstate = 0, $newblock=true, $blockdir='ltr')
4654 {
4655 if (!$a) {
4656 if ($blockdir=='rtl') { $a = 'R'; }
4657 else { $a = 'L'; }
4658 }
4659 $this->flowingBlockAttr[ 'width' ] = ($w * _MPDFK);
4660 // line height in user units
4661 $this->flowingBlockAttr[ 'is_table' ] = $is_table;
4662 $this->flowingBlockAttr[ 'is_list' ] = $is_list;
4663 $this->flowingBlockAttr[ 'height' ] = $h;
4664 $this->flowingBlockAttr[ 'lineCount' ] = 0;
4665 $this->flowingBlockAttr[ 'align' ] = $a;
4666 $this->flowingBlockAttr[ 'font' ] = array();
4667 $this->flowingBlockAttr[ 'content' ] = array();
4668 $this->flowingBlockAttr[ 'contentB' ] = array();
4669 $this->flowingBlockAttr[ 'contentWidth' ] = 0;
4670 $this->flowingBlockAttr[ 'blockstate' ] = $blockstate;
4671
4672 $this->flowingBlockAttr[ 'newblock' ] = $newblock;
4673 $this->flowingBlockAttr[ 'valign' ] = 'M';
4674 $this->flowingBlockAttr['blockdir'] = $blockdir;
4675
4676 }
4677
4678 function finishFlowingBlock($endofblock=false, $next='') {
4679 $currentx = $this->x;
4680 //prints out the last chunk
4681 $is_table = $this->flowingBlockAttr[ 'is_table' ];
4682 $is_list = $this->flowingBlockAttr[ 'is_list' ];
4683 $maxWidth =& $this->flowingBlockAttr[ 'width' ];
4684 $lineHeight =& $this->flowingBlockAttr[ 'height' ];
4685 $align =& $this->flowingBlockAttr[ 'align' ];
4686 $content =& $this->flowingBlockAttr[ 'content' ];
4687 $contentB =& $this->flowingBlockAttr[ 'contentB' ];
4688 $font =& $this->flowingBlockAttr[ 'font' ];
4689 $contentWidth =& $this->flowingBlockAttr[ 'contentWidth' ];
4690 $lineCount =& $this->flowingBlockAttr[ 'lineCount' ];
4691 $valign =& $this->flowingBlockAttr[ 'valign' ];
4692 $blockstate = $this->flowingBlockAttr[ 'blockstate' ];
4693
4694 $newblock = $this->flowingBlockAttr[ 'newblock' ];
4695 $blockdir = $this->flowingBlockAttr['blockdir'];
4696
4697
4698 // *********** BLOCK BACKGROUND COLOR *****************//
4699 if ($this->blk[$this->blklvl]['bgcolor'] && !$is_table) {
4700 $fill = 0;
4701 }
4702 else {
4703 $this->SetFColor($this->ConvertColor(255));
4704 $fill = 0;
4705 }
4706
4707 $hanger = ''; // mPDF 5.6.40
4708
4709 // Always right trim!
4710 // Right trim content and adjust width if need to justify (later)
4711 if (isset($content[count($content)-1]) && preg_match('/[ ]+$/',$content[count($content)-1], $m)) {
4712 $strip = strlen($m[0]);
4713 $content[count($content)-1] = substr($content[count($content)-1],0,(strlen($content[count($content)-1])-$strip));
4714 $this->restoreFont( $font[ count($content)-1 ],false );
4715 $contentWidth -= $this->GetStringWidth($m[0]) * _MPDFK;
4716 }
4717
4718 // the amount of space taken up so far in user units
4719 $usedWidth = 0;
4720
4721 // COLS
4722 $oldcolumn = $this->CurrCol;
4723
4724 if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
4725
4726 // Print out each chunk
4727
4728 /*-- TABLES --*/
4729 if ($is_table) {
4730 $ipaddingL = 0;
4731 $ipaddingR = 0;
4732 $paddingL = 0;
4733 $paddingR = 0;
4734 }
4735 else {
4736 /*-- END TABLES --*/
4737 $ipaddingL = $this->blk[$this->blklvl]['padding_left'];
4738 $ipaddingR = $this->blk[$this->blklvl]['padding_right'];
4739 $paddingL = ($ipaddingL * _MPDFK);
4740 $paddingR = ($ipaddingR * _MPDFK);
4741 $this->cMarginL = $this->blk[$this->blklvl]['border_left']['w'];
4742 $this->cMarginR = $this->blk[$this->blklvl]['border_right']['w'];
4743
4744 // Added mPDF 3.0 Float DIV
4745 $fpaddingR = 0;
4746 $fpaddingL = 0;
4747 /*-- CSS-FLOAT --*/
4748 if (count($this->floatDivs)) {
4749 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
4750 if ($r_exists) { $fpaddingR = $r_width; }
4751 if ($l_exists) { $fpaddingL = $l_width; }
4752 }
4753 /*-- END CSS-FLOAT --*/
4754
4755 $usey = $this->y + 0.002;
4756 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
4757 $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
4758 }
4759 /*-- CSS-IMAGE-FLOAT --*/
4760 // If float exists at this level
4761 if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
4762 if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
4763 /*-- END CSS-IMAGE-FLOAT --*/
4764 } // *TABLES*
4765
4766 // Set Current lineheight (correction factor)
4767 $lhfixed = false;
4768 /*-- LISTS --*/
4769 if ($is_list) {
4770 if (preg_match('/([0-9.,]+)mm/',$this->list_lineheight[$this->listlvl][$this->listOcc],$am)) {
4771 $lhfixed = true;
4772 $def_fontsize = $this->InlineProperties['LISTITEM'][$this->listlvl][$this->listOcc][$this->listnum]['size'];
4773 $this->lineheight_correction = $am[1] / $def_fontsize ;
4774 }
4775 else {
4776 $this->lineheight_correction = $this->list_lineheight[$this->listlvl][$this->listOcc];
4777 }
4778 }
4779 else
4780 /*-- END LISTS --*/
4781 /*-- TABLES --*/
4782 if ($is_table) {
4783 if (preg_match('/([0-9.,]+)mm/',$this->table_lineheight,$am)) {
4784 $lhfixed = true;
4785 $def_fontsize = $this->FontSize; // needs to be default font-size for block ****
4786 $this->lineheight_correction = $lineHeight / $def_fontsize ;
4787 }
4788 else {
4789 $this->lineheight_correction = $this->table_lineheight;
4790 }
4791 }
4792 else
4793 /*-- END TABLES --*/
4794 if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) {
4795 if (preg_match('/([0-9.,]+)mm/',$this->blk[$this->blklvl]['line_height'],$am)) {
4796 $lhfixed = true;
4797 $def_fontsize = $this->blk[$this->blklvl]['InlineProperties']['size']; // needs to be default font-size for block ****
4798 $this->lineheight_correction = $am[1] / $def_fontsize ;
4799 }
4800 else {
4801 $this->lineheight_correction = $this->blk[$this->blklvl]['line_height'];
4802 }
4803 }
4804 else {
4805 $this->lineheight_correction = $this->normalLineheight;
4806 }
4807
4808 // correct lineheight to maximum fontsize
4809 if ($lhfixed) { $maxlineHeight = $this->lineheight; }
4810 else { $maxlineHeight = 0; }
4811 $this->forceExactLineheight = true;
4812 $maxfontsize = 0;
4813 // While we're at it, check if contains cursive text
4814 $checkCursive=false;
4815 if ($this->biDirectional) { $checkCursive=true; } // *RTL*
4816 foreach ( $content as $k => $chunk )
4817 {
4818 $this->restoreFont( $font[ $k ],false );
4819 if (!isset($this->objectbuffer[$k])) {
4820 // Soft Hyphens chr(173)
4821 if (!$this->usingCoreFont) {
4822 $content[$k] = $chunk = str_replace("\xc2\xad",'',$chunk );
4823 if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) { $checkCursive=true; } // *INDIC*
4824 }
4825 else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
4826 $content[$k] = $chunk = str_replace(chr(173),'',$chunk );
4827 }
4828 // Special case of sub/sup carried over on its own to last line
4829 if (($this->SUB || $this->SUP) && count($content)==1) { $actfs = $this->FontSize*100/55; } // 55% is font change for sub/sup
4830 else { $actfs = $this->FontSize; }
4831 if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$actfs * $this->lineheight_correction ); }
4832 if ($lhfixed && ($actfs > $def_fontsize || ($actfs > ($lineHeight * $this->lineheight_correction) && $is_list))) {
4833 $this->forceExactLineheight = false;
4834 }
4835 $maxfontsize = max($maxfontsize,$actfs);
4836 }
4837 }
4838
4839 if(isset($font[count($font)-1])) {
4840 $lastfontreqstyle = $font[count($font)-1]['ReqFontStyle'];
4841 $lastfontstyle = $font[count($font)-1]['style'];
4842 }
4843 else {
4844 $lastfontreqstyle=null;
4845 $lastfontstyle=null;
4846 }
4847 if ($blockdir == 'ltr' && strpos($lastfontreqstyle,"I") !== false && strpos($lastfontstyle,"I") === false) { // Artificial italic
4848 $lastitalic = $this->FontSize*0.15*_MPDFK;
4849 }
4850 else { $lastitalic = 0; }
4851
4852
4853 /*-- LISTS --*/
4854 if ($is_list && is_array($this->bulletarray) && count($this->bulletarray)) {
4855 $actfs = $this->bulletarray['fontsize'];
4856 if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$actfs * $this->lineheight_correction ); }
4857 if ($lhfixed && $actfs > $def_fontsize) { $this->forceExactLineheight = false; }
4858 $maxfontsize = max($maxfontsize,$actfs);
4859 }
4860 /*-- END LISTS --*/
4861
4862 // when every text item checked i.e. $maxfontsize is set properly
4863
4864 $af = 0; // Above font
4865 $bf = 0; // Below font
4866 $mta = 0; // Maximum top-aligned
4867 $mba = 0; // Maximum bottom-aligned
4868
4869 foreach ( $content as $k => $chunk )
4870 {
4871 if (isset($this->objectbuffer[$k])) {
4872 $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
4873 $va = $this->objectbuffer[$k]['vertical-align']; // = $objattr['vertical-align'] = set as M,T,B,S
4874 if ($lhfixed && $oh > $def_fontsize) { $this->forceExactLineheight = false; }
4875
4876 if ($va == 'BS') { // (BASELINE default)
4877 $af = max($af, ($oh - ($maxfontsize * (0.5 + $this->baselineC))));
4878 }
4879 else if ($va == 'M') {
4880 $af = max($af, ($oh - $maxfontsize)/2);
4881 $bf = max($bf, ($oh - $maxfontsize)/2);
4882 }
4883 else if ($va == 'TT') {
4884 $bf = max($bf, ($oh - $maxfontsize));
4885 }
4886 else if ($va == 'TB') {
4887 $af = max($af, ($oh - $maxfontsize));
4888 }
4889 else if ($va == 'T') {
4890 $mta = max($mta, $oh);
4891 }
4892 else if ($va == 'B') {
4893 $mba = max($mba, $oh);
4894 }
4895 }
4896 }
4897 if ((!$lhfixed || !$this->forceExactLineheight) && ($af > (($maxlineHeight - $maxfontsize)/2) || $bf > (($maxlineHeight - $maxfontsize)/2))) {
4898 $maxlineHeight = $maxfontsize + $af + $bf;
4899 }
4900 else if (!$lhfixed) { $af = $bf = ($maxlineHeight - $maxfontsize)/2; }
4901 if ($mta > $maxlineHeight) {
4902 $bf += ($mta - $maxlineHeight);
4903 $maxlineHeight = $mta;
4904 }
4905 if ($mba > $maxlineHeight) {
4906 $af += ($mba - $maxlineHeight);
4907 $maxlineHeight = $mba;
4908 }
4909
4910 $lineHeight = $maxlineHeight;
4911 // If NOT images, and maxfontsize NOT > lineHeight - this value determines text baseline positioning
4912 if ($lhfixed && $af==0 && $bf==0 && $maxfontsize<=($def_fontsize * $this->lineheight_correction * 0.8 )) {
4913 $this->linemaxfontsize = $def_fontsize;
4914 }
4915 else { $this->linemaxfontsize = $maxfontsize; }
4916
4917 // Get PAGEBREAK TO TEST for height including the bottom border/padding
4918 $check_h = max($this->divheight,$lineHeight);
4919
4920 // This fixes a proven bug...
4921 if ($endofblock && $newblock && $blockstate==0 && !$content) { $check_h = 0; }
4922 // but ? needs to fix potentially more widespread...
4923 // if (!$content) { $check_h = 0; }
4924
4925 if ($this->blklvl > 0 && !$is_table) {
4926 if ($endofblock && $blockstate > 1) {
4927 if ($this->blk[$this->blklvl]['page_break_after_avoid']) { $check_h += $lineHeight; }
4928 $check_h += ($this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w']);
4929 }
4930 // mPDF 5.4.03
4931 if (($newblock && ($blockstate==1 || $blockstate==3) && $lineCount == 0) || ($endofblock && $blockstate ==3 && $lineCount == 0)) {
4932 $check_h += ($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['border_top']['w']);
4933 }
4934 }
4935
4936 // Force PAGE break if column height cannot take check-height
4937 if ($this->ColActive && $check_h > ($this->PageBreakTrigger - $this->y0)) {
4938 $this->SetCol($this->NbCol-1);
4939 }
4940
4941 // mPDF 5.4.04
4942 // Avoid just border/background-color moved on to next page
4943 if ($endofblock && $blockstate > 1 && !$content) { $buff = $this->margBuffer; }
4944 else { $buff = 0; }
4945
4946
4947 // PAGEBREAK
4948 // mPDF 5.4.04
4949 if(!$is_table && ($this->y+$check_h) > ($this->PageBreakTrigger + $buff) and !$this->InFooter and $this->AcceptPageBreak()) {
4950 $bak_x=$this->x;//Current X position
4951 // WORD SPACING
4952 $ws=$this->ws;//Word Spacing
4953 $charspacing=$this->charspacing;//Character Spacing
4954 $this->ResetSpacing();
4955
4956 $this->AddPage($this->CurOrientation);
4957
4958 $this->x=$bak_x;
4959 // Added to correct for OddEven Margins
4960 $currentx += $this->MarginCorrection;
4961 $this->x += $this->MarginCorrection;
4962
4963 // WORD SPACING
4964 $this->SetSpacing($charspacing,$ws);
4965 }
4966
4967 if ($this->keep_block_together && !$is_table && $this->kt_p00 < $this->page && ($this->y+$check_h) > $this->kt_y00) {
4968 $this->printdivbuffer();
4969 $this->keep_block_together = 0;
4970 }
4971
4972 /*-- COLUMNS --*/
4973 // COLS
4974 // COLUMN CHANGE
4975 if ($this->CurrCol != $oldcolumn) {
4976 $currentx += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
4977 $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
4978 $oldcolumn = $this->CurrCol;
4979 }
4980
4981
4982 if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; }
4983 /*-- END COLUMNS --*/
4984
4985 // TOP MARGIN
4986 if ($newblock && ($blockstate==1 || $blockstate==3) && ($this->blk[$this->blklvl]['margin_top']) && $lineCount == 0 && !$is_table && !$is_list) {
4987 $this->DivLn($this->blk[$this->blklvl]['margin_top'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
4988 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
4989 }
4990
4991 if ($newblock && ($blockstate==1 || $blockstate==3) && $lineCount == 0 && !$is_table && !$is_list) {
4992 $this->blk[$this->blklvl]['y0'] = $this->y;
4993 $this->blk[$this->blklvl]['startpage'] = $this->page;
4994 if ($this->blk[$this->blklvl]['float']) { $this->blk[$this->blklvl]['float_start_y'] = $this->y; } // mPDF 5.6.63
4995 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
4996 }
4997
4998 // ADDED for Paragraph_indent
4999 $WidthCorrection = 0;
5000 if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && (!$is_list) && ($align != 'C')) {
5001 $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
5002 $WidthCorrection = ($ti*_MPDFK);
5003 }
5004
5005
5006 // PADDING and BORDER spacing/fill
5007 if (($newblock) && ($blockstate==1 || $blockstate==3) && (($this->blk[$this->blklvl]['padding_top']) || ($this->blk[$this->blklvl]['border_top'])) && ($lineCount == 0) && (!$is_table) && (!$is_list)) {
5008 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
5009 $this->DivLn($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'],-3,true,false,1);
5010 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
5011 $this->x = $currentx;
5012 }
5013
5014
5015 // Added mPDF 3.0 Float DIV
5016 $fpaddingR = 0;
5017 $fpaddingL = 0;
5018 /*-- CSS-FLOAT --*/
5019 if (count($this->floatDivs)) {
5020 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
5021 if ($r_exists) { $fpaddingR = $r_width; }
5022 if ($l_exists) { $fpaddingL = $l_width; }
5023 }
5024 /*-- END CSS-FLOAT --*/
5025
5026 $usey = $this->y + 0.002;
5027 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
5028 $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
5029 }
5030 /*-- CSS-IMAGE-FLOAT --*/
5031 // If float exists at this level
5032 if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
5033 if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
5034 /*-- END CSS-IMAGE-FLOAT --*/
5035
5036 if ($content) {
5037
5038 // In FinishFlowing Block no lines are justified as it is always last line
5039 // but if CJKorphan has allowed content width to go over max width, use J charspacing to compress line
5040 // JUSTIFICATION J - NOT!
5041 $nb_carac = 0;
5042 $nb_spaces = 0;
5043 $jcharspacing = 0;
5044 $jws = 0;
5045 $inclCursive=false;
5046 $dottab = false; // mPDF 5.6.19
5047 foreach ( $content as $k => $chunk ) {
5048 if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
5049 if ($this->usingCoreFont) {
5050 $chunk = str_replace(chr(160),chr(32),$chunk );
5051 }
5052 else {
5053 $chunk = str_replace(chr(194).chr(160),chr(32),$chunk );
5054 }
5055 $nb_carac += mb_strlen( $chunk, $this->mb_enc );
5056 $nb_spaces += mb_substr_count( $chunk,' ', $this->mb_enc );
5057 if ($checkCursive) {
5058 if (preg_match("/([".$this->pregRTLchars."])/u", $chunk)) { $inclCursive = true; } // *RTL*
5059 if (preg_match("/([".$this->pregHIchars.$this->pregBNchars.$this->pregPAchars."])/u", $chunk)) { $inclCursive = true; } // *INDIC*
5060 }
5061 }
5062 else if ($this->objectbuffer[$k]['type']=='dottab') { $dottab = $this->objectbuffer[$k]['outdent']; } // mPDF 5.6.19
5063 }
5064 // 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)
5065 // If "orphans" in fact is just a final space - ignore this
5066 // mPDF 5.6.40
5067 $lastchar = mb_substr($content[(count($content)-1)],mb_strlen($content[(count($content)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
5068 if (preg_match("/[".$this->CJKoverflow."]/u", $lastchar)) { $CJKoverflow = true; }
5069 else {$CJKoverflow = false; }
5070 if ((((($contentWidth + $lastitalic) > $maxWidth) && ($content[count($content)-1] != ' ') ) ||
5071 (!$endofblock && $align=='J' && ($next=='image' || $next=='select' || $next=='input' || $next=='textarea' || ($next=='br' && $this->justifyB4br)))) && !($CJKoverflow && $this->allowCJKoverflow) ) { // mPDF 5.6.40
5072 // WORD SPACING
5073 list($jcharspacing,$jws) = $this->GetJspacing($nb_carac,$nb_spaces,($maxWidth-$lastitalic-$contentWidth-$WidthCorrection-(($this->cMarginL+$this->cMarginR)*_MPDFK)-($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) )),$inclCursive);
5074 }
5075 /*-- CJK-FONTS --*/
5076 // mPDF 5.6.40
5077 else if ($this->checkCJK && $align=='J' && $CJKoverflow && $this->allowCJKoverflow && $this->CJKforceend) {
5078 // force-end overhang
5079 $hanger = mb_substr($content[count($content)-1],mb_strlen($content[count($content)-1],$this->mb_enc)-1,1,$this->mb_enc );
5080 if (preg_match("/[".$this->CJKoverflow."]/u", $hanger)) {
5081 $content[count($content)-1] = mb_substr($content[count($content)-1],0,mb_strlen($content[count($content)-1],$this->mb_enc)-1,$this->mb_enc );
5082 $this->restoreFont( $font[ count($content)-1 ],false );
5083 $contentWidth -= $this->GetStringWidth($hanger) * _MPDFK;
5084 $nb_carac -= 1;
5085 list($jcharspacing,$jws) = $this->GetJspacing($nb_carac,$nb_spaces,($maxWidth-$lastitalic-$contentWidth-$WidthCorrection-(($this->cMarginL+$this->cMarginR)*_MPDFK)-($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) )),$inclCursive);
5086 }
5087 }
5088 /*-- END CJK-FONTS --*/
5089
5090 // Check if will fit at word/char spacing of previous line - if so continue it
5091 // but only allow a maximum of $this->jSmaxWordLast and $this->jSmaxCharLast
5092 else if ($contentWidth < ($maxWidth - $lastitalic-$WidthCorrection - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK))) && !$this->fixedlSpacing) {
5093 if ($this->ws > $this->jSmaxWordLast) {
5094 $jws = $this->jSmaxWordLast;
5095 }
5096 if ($this->charspacing > $this->jSmaxCharLast) {
5097 $jcharspacing = $this->jSmaxCharLast;
5098 }
5099 $check = $maxWidth - $lastitalic-$WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) ) - ( $jcharspacing * $nb_carac) - ( $jws * $nb_spaces);
5100 if ($check <= 0) {
5101 $jcharspacing = 0;
5102 $jws = 0;
5103 }
5104 }
5105
5106 $empty = $maxWidth - $lastitalic-$WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
5107
5108 $empty -= ($jcharspacing * $nb_carac);
5109 $empty -= ($jws * $nb_spaces);
5110
5111 $empty /= _MPDFK;
5112
5113 if (!$is_table) {
5114 $this->maxPosR = max($this->maxPosR , ($this->w - $this->rMargin - $this->blk[$this->blklvl]['outer_right_margin'] - $empty));
5115 $this->maxPosL = min($this->maxPosL , ($this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $empty));
5116 }
5117
5118 $arraysize = count($content);
5119
5120 $margins = ($this->cMarginL+$this->cMarginR) + ($ipaddingL+$ipaddingR + $fpaddingR + $fpaddingR );
5121
5122 if (!$is_table) { $this->DivLn($lineHeight,$this->blklvl,false); } // false -> don't advance y
5123
5124 // DIRECTIONALITY RTL
5125 $all_rtl = false;
5126 $contains_rtl = false;
5127 /*-- RTL --*/
5128 if ($blockdir == 'rtl' || $this->biDirectional) {
5129 $all_rtl = true;
5130 foreach ( $content as $k => $chunk ) {
5131 $reversed = $this->magic_reverse_dir($chunk, false, $blockdir);
5132 if ($reversed > 0) { $contains_rtl = true; }
5133 if ($reversed < 2) { $all_rtl = false; }
5134 $content[$k] = $chunk;
5135 }
5136 if (($blockdir =='rtl' && $contains_rtl) || $all_rtl) {
5137 $content = array_reverse($content,false);
5138 $contentB = array_reverse($contentB,false);
5139 }
5140 }
5141 /*-- END RTL --*/
5142
5143 $this->x = $currentx + $this->cMarginL + $ipaddingL + $fpaddingL;
5144 if ($dottab !== false && $blockdir=='rtl') { $this->x -= $dottab; } // mPDF 5.6.19
5145 else if ($align == 'R') { $this->x += $empty; }
5146 else if ($align == 'J' && $blockdir == 'rtl') { $this->x += $empty; }
5147 else if ($align == 'C') { $this->x += ($empty / 2); }
5148
5149 // Paragraph INDENT
5150 $WidthCorrection = 0;
5151 if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && (!$is_list) && ($align !='C')) {
5152 $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
5153 $this->x += $ti;
5154 }
5155
5156
5157 foreach ( $content as $k => $chunk )
5158 {
5159
5160 // FOR IMAGES
5161 if ((($blockdir == 'rtl') && ($contains_rtl )) || $all_rtl ) { $dirk = $arraysize-1 - $k; } else { $dirk = $k; }
5162
5163 $va = 'M'; // default for text
5164 if (isset($this->objectbuffer[$dirk]) && $this->objectbuffer[$dirk]) {
5165 $xadj = $this->x - $this->objectbuffer[$dirk]['OUTER-X'];
5166 $this->objectbuffer[$dirk]['OUTER-X'] += $xadj;
5167 $this->objectbuffer[$dirk]['BORDER-X'] += $xadj;
5168 $this->objectbuffer[$dirk]['INNER-X'] += $xadj;
5169 $va = $this->objectbuffer[$dirk]['vertical-align'];
5170 $yadj = $this->y - $this->objectbuffer[$dirk]['OUTER-Y'];
5171 if ($va == 'BS') {
5172 $yadj += $af + ($this->linemaxfontsize * (0.5 + $this->baselineC)) - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
5173 }
5174 else if ($va == 'M' || $va == '') {
5175 $yadj += $af + ($this->linemaxfontsize /2) - ($this->objectbuffer[$dirk]['OUTER-HEIGHT']/2);
5176 }
5177 else if ($va == 'TB') {
5178 $yadj += $af + $this->linemaxfontsize - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
5179 }
5180 else if ($va == 'TT') {
5181 $yadj += $af;
5182 }
5183 else if ($va == 'B') {
5184 $yadj += $af + $this->linemaxfontsize + $bf - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
5185 }
5186 else if ($va == 'T') {
5187 $yadj += 0;
5188 }
5189 $this->objectbuffer[$dirk]['OUTER-Y'] += $yadj;
5190 $this->objectbuffer[$dirk]['BORDER-Y'] += $yadj;
5191 $this->objectbuffer[$dirk]['INNER-Y'] += $yadj;
5192 }
5193
5194
5195 // DIRECTIONALITY RTL
5196 if ((($blockdir == 'rtl') && ($contains_rtl )) || $all_rtl ) { $this->restoreFont( $font[ $arraysize-1 - $k ] ); }
5197 else { $this->restoreFont( $font[ $k ] ); }
5198
5199 // mPDF 5.6.13 Decimal alignment - set in _tableWrite
5200 if ($is_table && substr($align,0,1)=='D' && $k==0 ) {
5201 $dp = $this->decimal_align[substr($align,0,2)];
5202 $s = preg_split('/'.preg_quote($dp,'/').'/', $content[0], 2); // ? needs to be /u if not core
5203 $s0 = $this->GetStringWidth($s[0], false);
5204 $this->x += ($this->decimal_offset - $s0);
5205 }
5206
5207 $this->SetSpacing(($this->fixedlSpacing*_MPDFK)+$jcharspacing,($this->fixedlSpacing+$this->minwSpacing)*_MPDFK+$jws);
5208 $this->fixedlSpacing = false;
5209 $this->minwSpacing = 0;
5210
5211 // mPDF 5.6.26
5212 $save_vis = $this->visibility;
5213 if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->textparam['visibility'] != $this->visibility) {
5214 $this->SetVisibility($this->textparam['visibility']);
5215 }
5216
5217 // *********** SPAN BACKGROUND COLOR ***************** //
5218 if (isset($this->spanbgcolor) && $this->spanbgcolor) {
5219 $cor = $this->spanbgcolorarray;
5220 $this->SetFColor($cor);
5221 $save_fill = $fill; $spanfill = 1; $fill = 1;
5222 }
5223 if (!empty($this->spanborddet)) {
5224 if (strpos($contentB[$k],'L')!==false && isset($this->spanborddet['L'])) $this->x += $this->spanborddet['L']['w'];
5225 if (strpos($contentB[$k],'L')===false) $this->spanborddet['L']['s'] = $this->spanborddet['L']['w'] = 0;
5226 if (strpos($contentB[$k],'R')===false) $this->spanborddet['R']['s'] = $this->spanborddet['R']['w'] = 0;
5227 }
5228 // WORD SPACING
5229 $stringWidth = $this->GetStringWidth($chunk ) + ( $this->charspacing * mb_strlen($chunk,$this->mb_enc ) / _MPDFK )
5230 + ( $this->ws * mb_substr_count($chunk,' ',$this->mb_enc ) / _MPDFK );
5231 if (isset($this->objectbuffer[$dirk])) {
5232 if ($this->objectbuffer[$dirk]['type']=='dottab') {
5233 $this->objectbuffer[$dirk]['OUTER-WIDTH'] +=$empty;
5234 $this->objectbuffer[$dirk]['OUTER-WIDTH'] +=$this->objectbuffer[$dirk]['outdent']; // mPDF 5.6.19
5235 }
5236 $stringWidth = $this->objectbuffer[$dirk]['OUTER-WIDTH'];
5237 }
5238
5239 if ($stringWidth==0) { $stringWidth = 0.000001; }
5240 if ($k == $arraysize-1) {
5241 // mPDF 5.6.40
5242 if ($this->checkCJK && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $hanger && $this->CJKforceend) {
5243 // force-end overhang
5244 $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
5245 $this->Cell( $this->GetStringWidth($hanger), $lineHeight, $hanger, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
5246 }
5247 else {
5248 $this->Cell( $stringWidth, $lineHeight, $chunk, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
5249 }
5250 }
5251 else $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, 0, 0,0,'M', $fill, $af, $bf, true );//first or middle part
5252
5253
5254 if (!empty($this->spanborddet)) {
5255 if (strpos($contentB[$k],'R')!==false && $k != $arraysize-1) $this->x += $this->spanborddet['R']['w'];
5256 }
5257 // *********** SPAN BACKGROUND COLOR OFF - RESET BLOCK BGCOLOR ***************** //
5258 if (isset($spanfill) && $spanfill) {
5259 $fill = $save_fill; $spanfill = 0;
5260 if ($fill) { $this->SetFColor($bcor); }
5261 }
5262 // mPDF 5.6.26
5263 if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->visibility != $save_vis) {
5264 $this->SetVisibility($save_vis);
5265 }
5266
5267 }
5268
5269 $this->printobjectbuffer($is_table, $blockdir);
5270
5271 $this->objectbuffer = array();
5272
5273 $this->ResetSpacing();
5274
5275 /*-- LISTS --*/
5276 // LIST BULLETS/NUMBERS
5277 if ($is_list && is_array($this->bulletarray) && ($lineCount == 0) ) {
5278
5279 $savedFont = $this->saveFont();
5280
5281 $bull = $this->bulletarray;
5282 if (isset($bull['level']) && isset($bull['occur']) && isset($this->InlineProperties['LIST'][$bull['level']][$bull['occur']])) {
5283 $this->restoreInlineProperties($this->InlineProperties['LIST'][$bull['level']][$bull['occur']]);
5284 }
5285 if (isset($bull['level']) && isset($bull['occur']) && isset($bull['num']) && isset($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) && $this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) { $this->restoreInlineProperties($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]); }
5286 if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
5287 $this->bullet = true;
5288 $this->SetFont('czapfdingbats','',$this->FontSizePt/2.5);
5289 }
5290 else { $this->SetFont($this->FontFamily,$this->FontStyle,$this->FontSizePt,true,true); } // force output
5291 //Output bullet
5292 $this->x = $currentx;
5293 if (isset($bull['x'])) { $this->x += $bull['x']; }
5294 $this->y -= $lineHeight;
5295 if (isset($bull['col']) && $bull['col']) { $this->SetTColor($bull['col']); } // mPDF 5.6.67
5296
5297 if (isset($bull['txt'])) { $this->Cell($bull['w'], $lineHeight,$bull['txt'],'','',$bull['align'],0,'',0,-$this->cMarginL, -$this->cMarginR ); }
5298 if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
5299 $this->bullet = false;
5300 }
5301 $this->x = $currentx; // Reset
5302 $this->y += $lineHeight;
5303
5304 if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
5305
5306 $this->restoreFont( $savedFont );
5307 // $font = array( $savedFont );
5308
5309 $this->bulletarray = array(); // prevents repeat of bullet/number if <li>....<br />.....</li>
5310 }
5311 /*-- END LISTS --*/
5312
5313
5314 } // END IF CONTENT
5315
5316 /*-- CSS-IMAGE-FLOAT --*/
5317 // Update values if set to skipline
5318 if ($this->floatmargins) { $this->_advanceFloatMargins(); }
5319
5320
5321 if ($endofblock && $blockstate>1) {
5322 // If float exists at this level
5323 if (isset($this->floatmargins['R']['y1'])) { $fry1 = $this->floatmargins['R']['y1']; }
5324 else { $fry1 = 0; }
5325 if (isset($this->floatmargins['L']['y1'])) { $fly1 = $this->floatmargins['L']['y1']; }
5326 else { $fly1 = 0; }
5327 if ($this->y < $fry1 || $this->y < $fly1) {
5328 $drop = max($fry1,$fly1) - $this->y;
5329 $this->DivLn($drop);
5330 $this->x = $currentx;
5331 }
5332 }
5333 /*-- END CSS-IMAGE-FLOAT --*/
5334
5335
5336 // PADDING and BORDER spacing/fill
5337 if ($endofblock && ($blockstate > 1) && ($this->blk[$this->blklvl]['padding_bottom'] || $this->blk[$this->blklvl]['border_bottom'] || $this->blk[$this->blklvl]['css_set_height']) && (!$is_table) && (!$is_list)) {
5338 // If CSS height set, extend bottom - if on same page as block started, and CSS HEIGHT > actual height,
5339 // and does not force pagebreak
5340 $extra = 0;
5341 if ($this->blk[$this->blklvl]['css_set_height'] && $this->blk[$this->blklvl]['startpage']==$this->page) {
5342 // predicted height
5343 $h1 = ($this->y-$this->blk[$this->blklvl]['y0']) + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'];
5344 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; }
5345 if($this->y + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'] + $extra > $this->PageBreakTrigger) {
5346 $extra = $this->PageBreakTrigger - ($this->y + $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w']);
5347 }
5348 }
5349
5350 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
5351 $this->DivLn($this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'] + $extra,-3,true,false,2);
5352 $this->x = $currentx;
5353
5354 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
5355
5356 }
5357
5358 // SET Bottom y1 of block (used for painting borders)
5359 if (($endofblock) && ($blockstate > 1) && (!$is_table) && (!$is_list)) {
5360 $this->blk[$this->blklvl]['y1'] = $this->y;
5361 }
5362
5363 // BOTTOM MARGIN
5364 if (($endofblock) && ($blockstate > 1) && ($this->blk[$this->blklvl]['margin_bottom']) && (!$is_table) && (!$is_list)) {
5365 if($this->y+$this->blk[$this->blklvl]['margin_bottom'] < $this->PageBreakTrigger and !$this->InFooter) {
5366 $this->DivLn($this->blk[$this->blklvl]['margin_bottom'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
5367 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
5368 }
5369 }
5370
5371 // Reset lineheight
5372 $lineHeight = $this->divheight;
5373 }
5374
5375
5376
5377
5378
5379 function printobjectbuffer($is_table=false, $blockdir=false) {
5380 if (!$blockdir) { $blockdir = $this->directionality; }
5381 if ($is_table && $this->shrin_k > 1) { $k = $this->shrin_k; }
5382 else { $k = 1; }
5383 $save_y = $this->y;
5384 $save_x = $this->x;
5385 $save_currentfontfamily = $this->FontFamily;
5386 $save_currentfontsize = $this->FontSizePt;
5387 $save_currentfontstyle = $this->FontStyle.($this->U ? 'U' : '').($this->S ? 'S' : '');
5388 if ($blockdir == 'rtl') { $rtlalign = 'R'; } else { $rtlalign = 'L'; }
5389 foreach ($this->objectbuffer AS $ib => $objattr) {
5390 if ($objattr['type'] == 'bookmark' || $objattr['type'] == 'indexentry' || $objattr['type'] == 'toc') {
5391 $x = $objattr['OUTER-X'];
5392 $y = $objattr['OUTER-Y'];
5393 $this->y = $y - $this->FontSize/2;
5394 $this->x = $x;
5395 if ($objattr['type'] == 'bookmark' ) { $this->Bookmark($objattr['CONTENT'],$objattr['bklevel'] ,$y - $this->FontSize); } // *BOOKMARKS*
5396 if ($objattr['type'] == 'indexentry') { $this->IndexEntry($objattr['CONTENT']); } // *INDEX*
5397 if ($objattr['type'] == 'toc') { $this->TOC_Entry($objattr['CONTENT'], $objattr['toclevel'], $objattr['toc_id']); } // *TOC*
5398 }
5399 /*-- ANNOTATIONS --*/
5400 else if ($objattr['type'] == 'annot') {
5401 if ($objattr['POS-X']) { $x = $objattr['POS-X']; }
5402 else if ($this->annotMargin<>0) { $x = -$objattr['OUTER-X']; }
5403 else { $x = $objattr['OUTER-X']; }
5404 if ($objattr['POS-Y']) { $y = $objattr['POS-Y']; }
5405 else { $y = $objattr['OUTER-Y'] - $this->FontSize/2; }
5406 // Create a dummy entry in the _out/columnBuffer with position sensitive data,
5407 // linking $y-1 in the Columnbuffer with entry in $this->columnAnnots
5408 // and when columns are split in length will not break annotation from current line
5409 $this->y = $y-1;
5410 $this->x = $x-1;
5411 $this->Line($x-1,$y-1,$x-1,$y-1);
5412 $this->Annotation($objattr['CONTENT'], $x , $y , $objattr['ICON'], $objattr['AUTHOR'], $objattr['SUBJECT'], $objattr['OPACITY'], $objattr['COLOR'], $objattr['POPUP'], $objattr['FILE']);
5413 }
5414 /*-- END ANNOTATIONS --*/
5415 else {
5416 $y = $objattr['OUTER-Y'];
5417 $x = $objattr['OUTER-X'];
5418 $w = $objattr['OUTER-WIDTH'];
5419 $h = $objattr['OUTER-HEIGHT'];
5420 if (isset($objattr['text'])) { $texto = $objattr['text']; }
5421 $this->y = $y;
5422 $this->x = $x;
5423 if (isset($objattr['fontfamily'])) { $this->SetFont($objattr['fontfamily'],'',$objattr['fontsize'] ); }
5424 }
5425
5426 // HR
5427 if ($objattr['type'] == 'hr') {
5428 $this->SetDColor($objattr['color']);
5429 switch($objattr['align']) {
5430 case 'C':
5431 $empty = $objattr['OUTER-WIDTH'] - $objattr['INNER-WIDTH'];
5432 $empty /= 2;
5433 $x += $empty;
5434 break;
5435 case 'R':
5436 $empty = $objattr['OUTER-WIDTH'] - $objattr['INNER-WIDTH'];
5437 $x += $empty;
5438 break;
5439 }
5440 $oldlinewidth = $this->LineWidth;
5441 $this->SetLineWidth($objattr['linewidth']/$k );
5442 $this->y += ($objattr['linewidth']/2) + $objattr['margin_top']/$k;
5443 $this->Line($x,$this->y,$x+$objattr['INNER-WIDTH'],$this->y);
5444 $this->SetLineWidth($oldlinewidth);
5445 $this->SetDColor($this->ConvertColor(0));
5446 }
5447 // IMAGE
5448 if ($objattr['type'] == 'image') {
5449 // mPDF 5.6.01 - LAYERS
5450 if (isset($objattr['z-index']) && $objattr['z-index'] > 0 && $this->currentlayer==0) {
5451 $this->BeginLayer($objattr['z-index']);
5452 }
5453 if(isset($objattr['visibility']) && $objattr['visibility']!='visible' && $objattr['visibility']) {
5454 $this->SetVisibility($objattr['visibility']);
5455 }
5456 if (isset($objattr['opacity'])) { $this->SetAlpha($objattr['opacity']); }
5457 $rotate = 0;
5458 $obiw = $objattr['INNER-WIDTH'];
5459 $obih = $objattr['INNER-HEIGHT'];
5460 $sx = $objattr['INNER-WIDTH']*_MPDFK / $objattr['orig_w'];
5461 $sy = abs($objattr['INNER-HEIGHT'])*_MPDFK / abs($objattr['orig_h']);
5462 $sx = ($objattr['INNER-WIDTH']*_MPDFK / $objattr['orig_w']);
5463 $sy = ($objattr['INNER-HEIGHT']*_MPDFK / $objattr['orig_h']);
5464
5465 if (isset($objattr['ROTATE'])) { $rotate = $objattr['ROTATE']; }
5466 if ($rotate==90) {
5467 // Clockwise
5468 $obiw = $objattr['INNER-HEIGHT'];
5469 $obih = $objattr['INNER-WIDTH'];
5470 $tr = $this->transformTranslate(0, -$objattr['INNER-WIDTH'], true) ;
5471 $tr .= ' '. $this->transformRotate(90, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-WIDTH'] ),true) ;
5472 $sx = $obiw*_MPDFK / $objattr['orig_h'];
5473 $sy = $obih*_MPDFK / $objattr['orig_w'];
5474 }
5475 else if ($rotate==-90 || $rotate==270) {
5476 // AntiClockwise
5477 $obiw = $objattr['INNER-HEIGHT'];
5478 $obih = $objattr['INNER-WIDTH'];
5479 $tr = $this->transformTranslate($objattr['INNER-WIDTH'], ($objattr['INNER-HEIGHT']-$objattr['INNER-WIDTH']), true) ;
5480 $tr .= ' '. $this->transformRotate(-90, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-WIDTH'] ),true) ;
5481 $sx = $obiw*_MPDFK / $objattr['orig_h'];
5482 $sy = $obih*_MPDFK / $objattr['orig_w'];
5483 }
5484 else if ($rotate==180) {
5485 // Mirror
5486 $tr = $this->transformTranslate($objattr['INNER-WIDTH'], -$objattr['INNER-HEIGHT'], true) ;
5487 $tr .= ' '. $this->transformRotate(180, $objattr['INNER-X'],($objattr['INNER-Y'] +$objattr['INNER-HEIGHT'] ),true) ;
5488 }
5489 else { $tr = ''; }
5490 $tr = trim($tr);
5491 if ($tr) { $tr .= ' '; }
5492 $gradmask = '';
5493
5494
5495 /*-- BACKGROUNDS --*/
5496 if (isset($objattr['GRADIENT-MASK'])) {
5497 $g = $this->grad->parseMozGradient( $objattr['GRADIENT-MASK'] );
5498 if ($g) {
5499 $dummy = $this->grad->Gradient($objattr['INNER-X'], $objattr['INNER-Y'], $obiw, $obih, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true, true);
5500 $gradmask = '/TGS'.count($this->gradients).' gs ';
5501 // $this->_out("q ".$tr.$this->grad->Gradient($objattr['INNER-X'], $objattr['INNER-Y'], $obiw, $obih, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend'], true)." Q");
5502 }
5503 }
5504 /*-- END BACKGROUNDS --*/
5505 /*-- IMAGES-WMF --*/
5506 if (isset($objattr['itype']) && $objattr['itype']=='wmf') {
5507 $outstring = sprintf('q '.$tr.'%.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $sx, -$sy, $objattr['INNER-X']*_MPDFK-$sx*$objattr['wmf_x'], (($this->h-$objattr['INNER-Y'])*_MPDFK)+$sy*$objattr['wmf_y'], $objattr['ID']);
5508 }
5509 else
5510 /*-- END IMAGES-WMF --*/
5511 if (isset($objattr['itype']) && $objattr['itype']=='svg') {
5512 $outstring = sprintf('q '.$tr.'%.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $sx, -$sy, $objattr['INNER-X']*_MPDFK-$sx*$objattr['wmf_x'], (($this->h-$objattr['INNER-Y'])*_MPDFK)+$sy*$objattr['wmf_y'], $objattr['ID']);
5513 }
5514 else {
5515 $outstring = sprintf("q ".$tr."%.3F 0 0 %.3F %.3F %.3F cm ".$gradmask."/I%d Do Q",$obiw*_MPDFK, $obih*_MPDFK, $objattr['INNER-X'] *_MPDFK, ($this->h-($objattr['INNER-Y'] +$obih ))*_MPDFK,$objattr['ID'] );
5516 }
5517 $this->_out($outstring);
5518 // LINK
5519 if (isset($objattr['link'])) $this->Link($objattr['INNER-X'],$objattr['INNER-Y'],$objattr['INNER-WIDTH'],$objattr['INNER-HEIGHT'],$objattr['link']);
5520 if (isset($objattr['opacity'])) { $this->SetAlpha(1); }
5521 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); }
5522 if(isset($objattr['visibility']) && $objattr['visibility']!='visible' && $objattr['visibility']) {
5523 $this->SetVisibility('visible');
5524 }
5525 // mPDF 5.6.01 - LAYERS
5526 if (isset($objattr['z-index']) && $objattr['z-index'] > 0 && $this->currentlayer==0) {
5527 $this->EndLayer();
5528 }
5529
5530 }
5531
5532 /*-- BARCODES --*/
5533 // BARCODE
5534 if ($objattr['type'] == 'barcode') {
5535 $bgcol = $this->ConvertColor(255);
5536 if (isset($objattr['bgcolor']) && $objattr['bgcolor']) {
5537 $bgcol = $objattr['bgcolor'];
5538 }
5539 $col = $this->ConvertColor(0);
5540 if (isset($objattr['color']) && $objattr['color']) {
5541 $col = $objattr['color'];
5542 }
5543 $this->SetFColor($bgcol);
5544 $this->Rect($objattr['BORDER-X'], $objattr['BORDER-Y'], $objattr['BORDER-WIDTH'], $objattr['BORDER-HEIGHT'], 'F');
5545 $this->SetFColor($this->ConvertColor(255));
5546 if (isset($objattr['BORDER-WIDTH'])) { $this->PaintImgBorder($objattr,$is_table); }
5547 if ($objattr['btype'] == 'EAN13' || $objattr['btype'] == 'ISBN' || $objattr['btype'] == 'ISSN' || $objattr['btype'] == 'UPCA' || $objattr['btype'] == 'UPCE' || $objattr['btype'] == 'EAN8') {
5548 $this->WriteBarcode($objattr['code'], $objattr['showtext'], $objattr['INNER-X'], $objattr['INNER-Y'], $objattr['bsize'], 0, 0, 0, 0, 0, $objattr['bheight'], $bgcol, $col, $objattr['btype'], $objattr['bsupp'], $objattr['bsupp_code'], $k);
5549 }
5550 // QR-code
5551 else if ($objattr['btype']=='QR') {
5552 if (!class_exists('QRcode', false)) {
5553 include(_MPDF_PATH.'qrcode/qrcode.class.php');
5554 }
5555 $this->qrcode = new QRcode($objattr['code'], $objattr['errorlevel']);
5556 $this->qrcode->displayFPDF($this, $objattr['INNER-X'], $objattr['INNER-Y'], $objattr['bsize']*25, array(255,255,255), array(0,0,0));
5557 }
5558 else {
5559 $this->WriteBarcode2($objattr['code'], $objattr['INNER-X'], $objattr['INNER-Y'], $objattr['bsize'], $objattr['bheight'], $bgcol, $col, $objattr['btype'], $objattr['pr_ratio'], $k);
5560 }
5561 }
5562 /*-- END BARCODES --*/
5563
5564 // TEXT CIRCLE
5565 if ($objattr['type'] == 'textcircle') {
5566 $bgcol = ''; // mPDF 5.5.14
5567 if (isset($objattr['bgcolor']) && $objattr['bgcolor']) {
5568 $bgcol = $objattr['bgcolor'];
5569 }
5570 $col = $this->ConvertColor(0);
5571 if (isset($objattr['color']) && $objattr['color']) {
5572 $col = $objattr['color'];
5573 }
5574 $this->SetTColor($col);
5575 $this->SetFColor($bgcol);
5576 if ($bgcol) $this->Rect($objattr['BORDER-X'], $objattr['BORDER-Y'], $objattr['BORDER-WIDTH'], $objattr['BORDER-HEIGHT'], 'F'); // mPDF 5.5.14
5577 $this->SetFColor($this->ConvertColor(255));
5578 if (isset($objattr['BORDER-WIDTH'])) { $this->PaintImgBorder($objattr,$is_table); }
5579 if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
5580 if (empty($this->directw)) { $this->directw = new directw($this); }
5581 $save_lmfs = $this->linemaxfontsize;
5582 $this->linemaxfontsize = 0;
5583 if (isset($objattr['top-text'])) {
5584 $this->directw->CircularText($objattr['INNER-X']+$objattr['INNER-WIDTH']/2, $objattr['INNER-Y']+$objattr['INNER-HEIGHT']/2, $objattr['r']/$k, $objattr['top-text'], 'top', $objattr['fontfamily'], $objattr['fontsize']/$k, $objattr['fontstyle'], $objattr['space-width'], $objattr['char-width'], $objattr['divider']); // mPDF 5.5.23
5585 }
5586 if (isset($objattr['bottom-text'])) {
5587 $this->directw->CircularText($objattr['INNER-X']+$objattr['INNER-WIDTH']/2, $objattr['INNER-Y']+$objattr['INNER-HEIGHT']/2, $objattr['r']/$k, $objattr['bottom-text'], 'bottom', $objattr['fontfamily'], $objattr['fontsize']/$k, $objattr['fontstyle'], $objattr['space-width'], $objattr['char-width'], $objattr['divider']); // mPDF 5.5.23
5588 }
5589 $this->linemaxfontsize = $save_lmfs;
5590 }
5591
5592 $this->ResetSpacing();
5593
5594 // DOT-TAB
5595 if ($objattr['type'] == 'dottab') {
5596 // mPDF 5.6.19
5597 if (isset($objattr['fontfamily'])) { $this->SetFont($objattr['fontfamily'],'',$objattr['fontsize'] ); }
5598 $sp = $this->GetStringWidth(' ');
5599 $nb=floor(($w-2*$sp)/$this->GetStringWidth('.'));
5600 if ($nb>0) { $dots=' '.str_repeat('.',$nb).' '; }
5601 else { $dots=' '; }
5602 $col = $this->ConvertColor(0);
5603 if (isset($objattr['colorarray']) && ($objattr['colorarray'])) { // mPDF 5.6.19
5604 $col = $objattr['colorarray'];
5605 }
5606 $this->SetTColor($col);
5607 $save_dh = $this->divheight; // mPDF 5.6.19
5608 $save_sbd = $this->spanborddet;
5609 $save_u = $this->U;
5610 $save_s = $this->strike;
5611 $this->spanborddet = '';
5612 $this->divheight = 0; // mPDF 5.6.19
5613 $this->U = false;
5614 $this->strike = false;
5615 $this->Cell($w,$h,$dots,0,0,'C');
5616 $this->spanborddet = $save_sbd;
5617 $this->U = $save_u;
5618 $this->strike = $save_s;
5619 $this->divheight = $save_dh; // mPDF 5.6.19
5620 // mPDF 5.0
5621 $this->SetTColor($this->ConvertColor(0));
5622 }
5623
5624 /*-- FORMS --*/
5625 // TEXT/PASSWORD INPUT
5626 if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'TEXT' || $objattr['subtype'] == 'PASSWORD')) {
5627 $this->form->print_ob_text($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
5628 }
5629
5630 // TEXTAREA
5631 if ($objattr['type'] == 'textarea') {
5632 $this->form->print_ob_textarea($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
5633 }
5634
5635 // SELECT
5636 if ($objattr['type'] == 'select') {
5637 $this->form->print_ob_select($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
5638 }
5639
5640
5641 // INPUT/BUTTON as IMAGE
5642 if ($objattr['type'] == 'input' && $objattr['subtype'] == 'IMAGE') {
5643 $this->form->print_ob_imageinput($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
5644 }
5645
5646 // BUTTON
5647 if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'SUBMIT' || $objattr['subtype'] == 'RESET' || $objattr['subtype'] == 'BUTTON')) {
5648 $this->form->print_ob_button($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir);
5649 }
5650
5651 // CHECKBOX
5652 if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'CHECKBOX')) {
5653 $this->form->print_ob_checkbox($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir,$x,$y);
5654 }
5655 // RADIO
5656 if ($objattr['type'] == 'input' && ($objattr['subtype'] == 'RADIO')) {
5657 $this->form->print_ob_radio($objattr,$w,$h,$texto,$rtlalign,$k,$blockdir,$x,$y);
5658 }
5659 /*-- END FORMS --*/
5660 }
5661 $this->SetFont($save_currentfontfamily,$save_currentfontstyle,$save_currentfontsize);
5662 $this->y = $save_y;
5663 $this->x = $save_x;
5664 unset($content);
5665 }
5666
5667
5668 function WriteFlowingBlock( $s)
5669 {
5670 $currentx = $this->x;
5671 $is_table = $this->flowingBlockAttr[ 'is_table' ];
5672 $is_list = $this->flowingBlockAttr[ 'is_list' ];
5673 // width of all the content so far in points
5674 $contentWidth =& $this->flowingBlockAttr[ 'contentWidth' ];
5675 // cell width in points
5676 $maxWidth =& $this->flowingBlockAttr[ 'width' ];
5677 $lineCount =& $this->flowingBlockAttr[ 'lineCount' ];
5678 // line height in user units
5679 $lineHeight =& $this->flowingBlockAttr[ 'height' ];
5680 $align =& $this->flowingBlockAttr[ 'align' ];
5681 $content =& $this->flowingBlockAttr[ 'content' ];
5682 $contentB =& $this->flowingBlockAttr[ 'contentB' ];
5683 $font =& $this->flowingBlockAttr[ 'font' ];
5684 $valign =& $this->flowingBlockAttr[ 'valign' ];
5685 $blockstate = $this->flowingBlockAttr[ 'blockstate' ];
5686
5687 $newblock = $this->flowingBlockAttr[ 'newblock' ];
5688 $blockdir = $this->flowingBlockAttr['blockdir'];
5689 // *********** BLOCK BACKGROUND COLOR ***************** //
5690 if ($this->blk[$this->blklvl]['bgcolor'] && !$is_table) {
5691 $fill = 0;
5692 }
5693 else {
5694 $this->SetFColor($this->ConvertColor(255));
5695 $fill = 0;
5696 }
5697 $font[] = $this->saveFont();
5698 $content[] = '';
5699 $contentB[] = '';
5700 $currContent =& $content[ count( $content ) - 1 ];
5701 // where the line should be cutoff if it is to be justified
5702 $cutoffWidth = $contentWidth;
5703
5704 $CJKoverflow = false;
5705 $hanger = ''; // mPDF 5.6.40
5706
5707 // COLS
5708 $oldcolumn = $this->CurrCol;
5709
5710 if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
5711
5712 /*-- TABLES --*/
5713 if ($is_table) {
5714 $ipaddingL = 0;
5715 $ipaddingR = 0;
5716 $paddingL = 0;
5717 $paddingR = 0;
5718 $cpaddingadjustL = 0;
5719 $cpaddingadjustR = 0;
5720 // Added mPDF 3.0
5721 $fpaddingR = 0;
5722 $fpaddingL = 0;
5723 }
5724 else {
5725 /*-- END TABLES --*/
5726 $ipaddingL = $this->blk[$this->blklvl]['padding_left'];
5727 $ipaddingR = $this->blk[$this->blklvl]['padding_right'];
5728 $paddingL = ($ipaddingL * _MPDFK);
5729 $paddingR = ($ipaddingR * _MPDFK);
5730 $this->cMarginL = $this->blk[$this->blklvl]['border_left']['w'];
5731 $cpaddingadjustL = -$this->cMarginL;
5732 $this->cMarginR = $this->blk[$this->blklvl]['border_right']['w'];
5733 $cpaddingadjustR = -$this->cMarginR;
5734 // Added mPDF 3.0 Float DIV
5735 $fpaddingR = 0;
5736 $fpaddingL = 0;
5737 /*-- CSS-FLOAT --*/
5738 if (count($this->floatDivs)) {
5739 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
5740 if ($r_exists) { $fpaddingR = $r_width; }
5741 if ($l_exists) { $fpaddingL = $l_width; }
5742 }
5743 /*-- END CSS-FLOAT --*/
5744
5745 $usey = $this->y + 0.002;
5746 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
5747 $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
5748 }
5749 /*-- CSS-IMAGE-FLOAT --*/
5750 // If float exists at this level
5751 if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
5752 if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
5753 /*-- END CSS-IMAGE-FLOAT --*/
5754 } // *TABLES*
5755
5756 //OBJECTS - IMAGES & FORM Elements (NB has already skipped line/page if required - in printbuffer)
5757 if (substr($s,0,3) == "\xbb\xa4\xac") { //identifier has been identified!
5758 $objattr = $this->_getObjAttr($s);
5759 $h_corr = 0;
5760 if ($is_table) { // *TABLES*
5761 $maximumW = ($maxWidth/_MPDFK) - ($this->cellPaddingL + $this->cMarginL + $this->cellPaddingR + $this->cMarginR); // *TABLES*
5762 } // *TABLES*
5763 else { // *TABLES*
5764 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']; }
5765 $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 );
5766 } // *TABLES*
5767 $objattr = $this->inlineObject($objattr['type'],$this->lMargin + $fpaddingL + ($contentWidth/_MPDFK),($this->y + $h_corr), $objattr, $this->lMargin,($contentWidth/_MPDFK),$maximumW,$lineHeight,true,$is_table);
5768
5769 // SET LINEHEIGHT for this line ================ RESET AT END
5770 $lineHeight = MAX($lineHeight,$objattr['OUTER-HEIGHT']);
5771 $this->objectbuffer[count($content)-1] = $objattr;
5772 // if (isset($objattr['vertical-align'])) { $valign = $objattr['vertical-align']; }
5773 // else { $valign = ''; }
5774 $contentWidth += ($objattr['OUTER-WIDTH'] * _MPDFK);
5775 return;
5776 }
5777
5778 $lbw = $rbw = 0; // Border widths
5779 if (!empty($this->spanborddet)) {
5780 if (isset($this->spanborddet['L'])) $lbw = $this->spanborddet['L']['w'];
5781 if (isset($this->spanborddet['R'])) $rbw = $this->spanborddet['R']['w'];
5782 }
5783
5784 if ($this->usingCoreFont) {
5785 $tmp = strlen( $s );
5786 }
5787 else {
5788 $tmp = mb_strlen( $s, $this->mb_enc );
5789 }
5790
5791 // for every character in the string
5792 for ( $i = 0; $i < $tmp; $i++ ) {
5793 // extract the current character
5794 // get the width of the character in points
5795 if ($this->usingCoreFont) {
5796 $c = $s[$i];
5797 // Soft Hyphens chr(173)
5798 $cw = ($this->GetCharWidthCore($c) * _MPDFK);
5799 if ($this->kerning && $this->useKerning && $i > 0) {
5800 if (isset($this->CurrentFont['kerninfo'][$s[($i-1)]][$c])) {
5801 $cw += ($this->CurrentFont['kerninfo'][$s[($i-1)]][$c] * $this->FontSizePt / 1000 );
5802 }
5803 }
5804 }
5805 else {
5806 $c = mb_substr($s,$i,1,$this->mb_enc );
5807 $cw = ($this->GetCharWidthNonCore($c, false) * _MPDFK);
5808 if ($this->kerning && $this->useKerning && $i > 0) {
5809 $lastc = mb_substr($s,($i-1),1,$this->mb_enc );
5810 $ulastc = $this->UTF8StringToArray($lastc, false);
5811 $uc = $this->UTF8StringToArray($c, false);
5812 if (isset($this->CurrentFont['kerninfo'][$ulastc[0]][$uc[0]])) {
5813 $cw += ($this->CurrentFont['kerninfo'][$ulastc[0]][$uc[0]] * $this->FontSizePt / 1000 );
5814 }
5815 }
5816 }
5817
5818 if ($i==0) {
5819 $cw += $lbw*_MPDFK;
5820 $contentB[(count($contentB)-1)] .= 'L';
5821 }
5822 if ($i==($tmp-1)) {
5823 $cw += $rbw*_MPDFK;
5824 $contentB[(count($contentB)-1)] .= 'R';
5825 }
5826 // mPDF 5.6.45
5827 if ($c==' ') {
5828 $currContent .= $c;
5829 $cutoffWidth = $contentWidth;
5830 $contentWidth += $cw;
5831 continue;
5832 }
5833
5834 // ADDED for Paragraph_indent
5835 $WidthCorrection = 0;
5836 if (($newblock) && ($blockstate==1 || $blockstate==3) && isset($this->blk[$this->blklvl]['text_indent']) && ($lineCount == 0) && (!$is_table) && (!$is_list) && ($align != 'C')) {
5837 $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
5838 $WidthCorrection = ($ti*_MPDFK);
5839 }
5840
5841 // Added mPDF 3.0 Float DIV
5842 $fpaddingR = 0;
5843 $fpaddingL = 0;
5844 /*-- CSS-FLOAT --*/
5845 if (count($this->floatDivs)) {
5846 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
5847 if ($r_exists) { $fpaddingR = $r_width; }
5848 if ($l_exists) { $fpaddingL = $l_width; }
5849 }
5850 /*-- END CSS-FLOAT --*/
5851
5852 $usey = $this->y + 0.002;
5853 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 0) ) {
5854 $usey += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
5855 }
5856
5857 /*-- CSS-IMAGE-FLOAT --*/
5858 // If float exists at this level
5859 if (isset($this->floatmargins['R']) && $usey <= $this->floatmargins['R']['y1'] && $usey >= $this->floatmargins['R']['y0'] && !$this->floatmargins['R']['skipline']) { $fpaddingR += $this->floatmargins['R']['w']; }
5860 if (isset($this->floatmargins['L']) && $usey <= $this->floatmargins['L']['y1'] && $usey >= $this->floatmargins['L']['y0'] && !$this->floatmargins['L']['skipline']) { $fpaddingL += $this->floatmargins['L']['w']; }
5861 /*-- END CSS-IMAGE-FLOAT --*/
5862
5863
5864
5865 // try adding another char
5866 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
5867 // it won't fit, output what we already have
5868 $lineCount++;
5869
5870 // contains any content that didn't make it into this print
5871 $savedContent = '';
5872 $savedContentB = '';
5873 $savedFont = array();
5874 $savedObj = array();
5875 // mPDF 5.6.20
5876 $savedPreContent = array();
5877 $savedPreContentB = array();
5878 $savedPreFont = array();
5879
5880 // cut off and save any partial words at the end of the string
5881 $words = explode( ' ', $currContent );
5882 ///////////////////
5883 // HYPHENATION
5884 $currWord = $words[count($words)-1] ;
5885 $success = false;
5886
5887 // mPDF 5.6.21 Hard Hyphens -
5888 $hardsuccess = false;
5889 if ($this->textparam['hyphens'] != 2 && preg_match("/\-/",$currWord)) {
5890 $rem = $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
5891 list($hardsuccess,$pre,$post,$prelength) = $this->hardHyphenate($currWord, (($rem-$cutoffWidth)/_MPDFK -$this->GetCharWidth("-", false)) );
5892 if ($hardsuccess) {
5893 $already = array_pop( $words );
5894 $forward = mb_substr($already,$prelength+1,mb_strlen($already, $this->mb_enc), $this->mb_enc);
5895 $words[] = $pre.'-';
5896 $words[] = $forward;
5897 $currContent = mb_substr($currContent,0,mb_strlen($currContent, $this->mb_enc)+1-mb_strlen($post, $this->mb_enc), $this->mb_enc) . '-';
5898 }
5899 }
5900
5901 /*-- HYPHENATION --*/
5902 // Soft Hyphens chr(173)
5903 else if ($this->textparam['hyphens'] != 2 && (!$this->usingCoreFont && preg_match("/\xc2\xad/",$currWord)) || ($this->usingCoreFont && preg_match("/".chr(173)."/",$currWord) && ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats')) ) { // mPDF 5.6.06
5904 $rem = $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
5905 list($success,$pre,$post,$prelength) = $this->softHyphenate($currWord, (($rem-$cutoffWidth)/_MPDFK -$this->GetCharWidth(" ", false)) );
5906 }
5907
5908 if (!$success && !$hardsuccess && $this->textparam['hyphens'] == 1 ) { // mPDF 5.6.06 // mPDF 5.6.21
5909 // Look ahead to get current word
5910 for($ac = $i; $ac<(mb_strlen($s)-1); $ac++) {
5911 $addc = mb_substr($s,$ac,1,$this->mb_enc );
5912 if ($addc == ' ') { break; }
5913 $currWord .= $addc;
5914 }
5915 $rem = $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
5916 list($success,$pre,$post,$prelength) = $this->hyphenateWord($currWord, (($rem-$cutoffWidth)/_MPDFK -$this->GetCharWidth(" ", false)) );
5917 }
5918 if ($success) {
5919 $already = array_pop( $words );
5920 $forward = mb_substr($already,$prelength,mb_strlen($already, $this->mb_enc), $this->mb_enc);
5921 $words[] = $pre.'-';
5922 $words[] = $forward;
5923 $currContent = mb_substr($currContent,0,mb_strlen($currContent, $this->mb_enc)+1-mb_strlen($post, $this->mb_enc), $this->mb_enc) . '-';
5924 }
5925 /*-- END HYPHENATION --*/
5926
5927 // mPDF 5.6.13 Decimal alignment (cancel if wraps to > 1 line)
5928 if ($is_table && substr($align,0,1)=='D' ) { $align=substr($align,2,1); }
5929
5930 /*-- CJK-FONTS --*/
5931 // mPDF 5.6.42
5932 if ($this->checkCJK) {
5933 $lastchar = mb_substr($words[(count($words)-1)],mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
5934 }
5935 // Next character is suitable to add as overhanging or squeezed punctuation
5936 if ($this->checkCJK && preg_match("/[".$this->CJKoverflow."]/u", $c) && $this->allowCJKorphans && !$CJKoverflow) {
5937 // add character onto this line
5938 $currContent .= $c;
5939 $cutoffWidth = $contentWidth;
5940 $contentWidth += $cw;
5941 $CJKoverflow = true;
5942 continue;
5943 }
5944 // Last character that fits is not allowed to end a line - move lastchar(s) to start of next line
5945 else if ($this->checkCJK && preg_match("/[".$this->CJKleading."]/u", $lastchar)) {
5946 //move lastchar(s) to next line
5947 $m0 = $lastchar;
5948 $m1 = $c;
5949 while(preg_match("/[".$this->CJKleading."]/u", $m0) && mb_strlen($words[(count($words)-1)], $this->mb_enc)>2) {
5950 // trim last letter off word[0]
5951 $words[(count($words)-1)] = mb_substr($words[(count($words)-1)],0,mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, $this->mb_enc);
5952 // and add it to savedContent for next line
5953 $savedContent = $m0.$savedContent;
5954 $m1 = $lastchar;
5955 $lastchar = mb_substr($words[(count($words)-1)],mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
5956 $m0 = $lastchar;
5957 }
5958 $lastContent = '';
5959 for ( $w = 0; $w < count( $words ) ; $w++) { $lastContent .= $words[ $w ]." "; }
5960 $savedFont = $this->saveFont();
5961 // replace the current content with the cropped version
5962 $currContent = rtrim( $lastContent );
5963 }
5964 // Next character is not allowed to start a new line
5965 else if ($this->checkCJK && preg_match("/[".$this->CJKfollowing."]/u", $c)) {
5966 // try squeezing another character(s) onto this line = Oikomi
5967 if ($this->allowCJKorphans && !$CJKoverflow) { // mPDF 5.6.40
5968 $lookahead = mb_substr($s,$i+1,1,$this->mb_enc );
5969 //if lookahead is not another following char
5970 if (!$lookahead || ($lookahead && !preg_match("/[".$this->CJKfollowing."]/u", $lookahead))) {
5971 $currContent .= $c;
5972 $cutoffWidth = $contentWidth;
5973 $contentWidth += $cw;
5974 if ($this->allowCJKoverflow && preg_match("/[".$this->CJKoverflow."]/u", $c)) { $CJKoverflow = true; }
5975 continue;
5976 }
5977 }
5978 // or move lastchar(s) to next line to keep $c company = Oidashi
5979 $m0 = $lastchar;
5980 $m1 = $c;
5981 while(preg_match("/[".$this->CJKfollowing."]/u", $m1) && mb_strlen($words[(count($words)-1)], $this->mb_enc)>2) {
5982 // trim last letter off word[0]
5983 $words[(count($words)-1)] = mb_substr($words[(count($words)-1)],0,mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, $this->mb_enc);
5984 // and add it to savedContent for next line
5985 $savedContent = $m0.$savedContent;
5986 $m1 = $lastchar;
5987 $lastchar = mb_substr($words[(count($words)-1)],mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
5988 $m0 = $lastchar;
5989 }
5990 $lastContent = '';
5991 for ( $w = 0; $w < count( $words ) ; $w++) { $lastContent .= $words[ $w ]." "; }
5992 $savedFont = $this->saveFont();
5993 // replace the current content with the cropped version
5994 $currContent = rtrim( $lastContent );
5995 }
5996 // mPDF 5.6.42
5997 else if ($this->checkCJK && preg_match("/([".$this->pregCJKchars."]+[0-9\x{ff10}-\x{ff19}]+$)/u", $words[0])) {
5998 $lookahead = mb_substr($s,$i,16,$this->mb_enc );
5999 //and if lookahead starts with a few numerals
6000 if ($lookahead && (preg_match("/^([0-9\x{ff10}-\x{ff19}]+[".$this->pregCJKchars."]+)/u", $lookahead) || preg_match("/^([0-9\x{ff10}-\x{ff19}]+$)/u", $lookahead)) ) {
6001 // or move lastchar(s) to next line to keep numerals together
6002 $m0 = $lastchar;
6003 while(preg_match("/[0-9\x{ff10}-\x{ff19}]/u", $m0) && mb_strlen($words[(count($words)-1)], $this->mb_enc)>2) {
6004 // trim last letter off word[0]
6005 $words[(count($words)-1)] = mb_substr($words[(count($words)-1)],0,mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, $this->mb_enc);
6006 // and add it to savedContent for next line
6007 $savedContent = $m0.$savedContent;
6008 $lastchar = mb_substr($words[(count($words)-1)],mb_strlen($words[(count($words)-1)], $this->mb_enc)-1, 1, $this->mb_enc);
6009 $m0 = $lastchar;
6010 }
6011 }
6012 $lastContent = '';
6013 for ( $w = 0; $w < count( $words ) ; $w++) { $lastContent .= $words[ $w ]." "; }
6014 $savedFont = $this->saveFont();
6015 // replace the current content with the cropped version
6016 $currContent = rtrim( $lastContent );
6017 }
6018 else
6019 /*-- END CJK-FONTS --*/
6020 // if it looks like we didn't finish any words for this chunk
6021 if ( count( $words ) == 1 ) {
6022 // TO correct for error when word too wide for page - but only when one long word from left to right margin
6023 if (count($content) == 1 && $currContent != ' ') {
6024 $lastchar = mb_substr($words[0],mb_strlen($words[0], $this->mb_enc)-1, 1, $this->mb_enc);
6025 $lastContent = $words[0];
6026 $savedFont = $this->saveFont();
6027 // replace the current content with the cropped version
6028 $currContent = rtrim( $lastContent );
6029 }
6030 // mPDF 5.6.20
6031 else if ( count($content)>1
6032 && (!isset($this->objectbuffer[(count($content)-1)]) && !isset($this->objectbuffer[(count($content)-2)]))
6033 && substr($content[count($content)-2],-1,1) != ' '
6034 && substr($currContent,0,1) != ' '
6035 ) {
6036 // Go back to find a space in a previous chunk of content
6037 $found = false;
6038 for ($ix=count($content)-1;$ix>=0;$ix--) {
6039 // mPDF 5.6.29
6040 if ($this->usingCoreFont && preg_match('/[ '.chr(173).']/',$content[$ix],$m)) { $match = $m[0]; $found = $ix; break; }
6041 else if (!$this->usingCoreFont) {
6042 if (preg_match('/[ ]/',$content[$ix])) { $match = ' '; $found = $ix; break; }
6043 else if (preg_match('/[\x{00AD}]/u',$content[$ix])) {
6044 // even though it is UTF-8 replace it temporarily with chr(173)
6045 $content[$ix] = preg_replace('/[\x{00AD}]/u',chr(173),$content[$ix]);
6046 $match = chr(173); $found = $ix; break;
6047 }
6048 }
6049 }
6050 if ($found !== false) {
6051 $charpos = strrpos($content[$found],$match); // mPDF 5.6.29
6052 for ($ix=count($content)-1;$ix>$found;$ix--) {
6053 // save and crop off any subsequent chunks
6054 $savedPreContent[] = array_pop($content);
6055 $savedPreContentB[] = array_pop($contentB);
6056 $savedPreFont[] = array_pop($font);
6057 }
6058 if (substr($content[count($content)-1],$charpos+1,strlen($content[count($content)-1])-1) != '') {
6059 $savedPreContent[] = substr($content[count($content)-1],$charpos+1,strlen($content[count($content)-1])-1);
6060 $savedPreContentB[] = preg_replace('/L/','',$contentB[count($content)-1]); // ???
6061 $savedPreFont[] = $font[count($content)-1];
6062 }
6063 $savedContent = '';
6064 $savedContentB = '';
6065 $savedFont = array();
6066
6067 $currContent =& $content[ count( $content ) - 1 ];
6068 $currContent = substr($currContent,0,$charpos);
6069 if ($match == chr(173)) { $currContent .= '-'; } // mPDF 5.6.29
6070 if (strpos($contentB[(count($contentB)-1)],'R')!==false) { // ???
6071 $contentB[count($content)-1] = preg_replace('/R/','',$contentB[count($content)-1]); // ???
6072 }
6073
6074 $currContent = rtrim( $currContent );
6075 }
6076 else {
6077 $savedContent = array_pop( $content );
6078 $savedContentB = array_pop($contentB);
6079 $savedFont = array_pop( $font );
6080 $currContent =& $content[ count( $content ) - 1 ];
6081 $currContent = rtrim( $currContent );
6082 }
6083 }
6084 else {
6085 // save and crop off the content currently on the stack
6086 $savedContent = array_pop( $content );
6087 $savedContentB = array_pop($contentB); // mPDF 5.6.20
6088 $savedFont = array_pop( $font );
6089 // trim any trailing spaces off the last bit of content
6090 $currContent =& $content[ count( $content ) - 1 ];
6091 $currContent = rtrim( $currContent );
6092 }
6093 }
6094 else { // otherwise, we need to find which bit to cut off
6095 $lastContent = '';
6096 for ( $w = 0; $w < count( $words ) - 1; $w++) { $lastContent .= $words[ $w ]." "; }
6097 $savedContent = $words[ count( $words ) - 1 ];
6098 $savedFont = $this->saveFont();
6099 // replace the current content with the cropped version
6100 $currContent = rtrim( $lastContent );
6101 }
6102 // CJK - strip CJK space at end of line
6103 // &#x3000; = \xe3\x80\x80 = CJK space
6104 if ($this->checkCJK) { $currContent = preg_replace("/\xe3\x80\x80$/",'',$currContent) ; } // *CJK-FONTS*
6105
6106
6107 if (isset($this->objectbuffer[(count($content)-1)]) && $this->objectbuffer[(count($content)-1)]['type']=='dottab') {
6108 $savedObj = array_pop( $this->objectbuffer );
6109 $contentWidth -= ($this->objectbuffer[(count($content)-1)]['OUTER-WIDTH'] * _MPDFK);
6110 }
6111
6112 // Set Current lineheight (correction factor)
6113 $lhfixed = false;
6114 /*-- LISTS --*/
6115 if ($is_list) {
6116 if (preg_match('/([0-9.,]+)mm/',$this->list_lineheight[$this->listlvl][$this->listOcc],$am)) {
6117 $lhfixed = true;
6118 $def_fontsize = $this->InlineProperties['LISTITEM'][$this->listlvl][$this->listOcc][$this->listnum]['size'];
6119 $this->lineheight_correction = $am[1] / $def_fontsize ;
6120 }
6121 else {
6122 $this->lineheight_correction = $this->list_lineheight[$this->listlvl][$this->listOcc];
6123 }
6124 }
6125 else
6126 /*-- END LISTS --*/
6127 /*-- TABLES --*/
6128 if ($is_table) {
6129 if (preg_match('/([0-9.,]+)mm/',$this->table_lineheight,$am)) {
6130 $lhfixed = true;
6131 $def_fontsize = $this->FontSize; // needs to be default font-size for block ****
6132 $this->lineheight_correction = $lineHeight / $def_fontsize ;
6133 }
6134 else {
6135 $this->lineheight_correction = $this->table_lineheight;
6136 }
6137 }
6138 else
6139 /*-- END TABLES --*/
6140 if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) {
6141 if (preg_match('/([0-9.,]+)mm/',$this->blk[$this->blklvl]['line_height'],$am)) {
6142 $lhfixed = true;
6143 $def_fontsize = $this->blk[$this->blklvl]['InlineProperties']['size']; // needs to be default font-size for block ****
6144 $this->lineheight_correction = $am[1] / $def_fontsize ;
6145 }
6146 else {
6147 $this->lineheight_correction = $this->blk[$this->blklvl]['line_height'];
6148 }
6149 }
6150 else {
6151 $this->lineheight_correction = $this->normalLineheight;
6152 }
6153 // update $contentWidth and $cutoffWidth since they changed with cropping
6154 // Also correct lineheight to maximum fontsize (not for tables)
6155 $contentWidth = 0;
6156 // correct lineheight to maximum fontsize
6157 if ($lhfixed) { $maxlineHeight = $this->lineheight; }
6158 else { $maxlineHeight = 0; }
6159 $this->forceExactLineheight = true;
6160 $maxfontsize = 0;
6161 // While we're at it, check for cursive text
6162 $checkCursive=false;
6163 if ($this->biDirectional) { $checkCursive=true; } // *RTL*
6164 foreach ( $content as $k => $chunk )
6165 {
6166 $this->restoreFont( $font[ $k ]);
6167 if (!isset($this->objectbuffer[$k])) {
6168 // mPDF 5.6.40
6169 if ($this->checkCJK && $k == count($content)-1 && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $this->CJKforceend) {
6170 // force-end overhang
6171 $hanger = mb_substr($chunk,mb_strlen($chunk,$this->mb_enc)-1,1,$this->mb_enc );
6172 $content[$k] = $chunk = mb_substr($chunk,0,mb_strlen($chunk,$this->mb_enc)-1,$this->mb_enc );
6173 }
6174 if (!$this->usingCoreFont) {
6175 $content[$k] = $chunk = str_replace("\xc2\xad",'',$chunk );
6176 if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) { $checkCursive=true; } // *INDIC*
6177 }
6178 // Soft Hyphens chr(173)
6179 else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
6180 $content[$k] = $chunk = str_replace(chr(173),'',$chunk );
6181 }
6182 $contentWidth += $this->GetStringWidth( $chunk ) * _MPDFK;
6183 if (!empty($this->spanborddet)) {
6184 if (strpos($contentB[$k],'L')!==false) $contentWidth += $this->spanborddet['L']['w'] * _MPDFK;
6185 if (strpos($contentB[$k],'R')!==false) $contentWidth += $this->spanborddet['R']['w'] * _MPDFK;
6186 }
6187 if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$this->FontSize * $this->lineheight_correction ); }
6188 if ($lhfixed && ($this->FontSize > $def_fontsize || ($this->FontSize > ($lineHeight * $this->lineheight_correction) && $is_list))) {
6189 $this->forceExactLineheight = false;
6190 }
6191 $maxfontsize = max($maxfontsize,$this->FontSize);
6192 }
6193 }
6194
6195 $lastfontreqstyle = $font[count($font)-1]['ReqFontStyle'];
6196 $lastfontstyle = $font[count($font)-1]['style'];
6197 if ($blockdir == 'ltr' && strpos($lastfontreqstyle,"I") !== false && strpos($lastfontstyle,"I") === false) { // Artificial italic
6198 $lastitalic = $this->FontSize*0.15*_MPDFK;
6199 }
6200 else { $lastitalic = 0; }
6201
6202
6203 /*-- LISTS --*/
6204 if ($is_list && is_array($this->bulletarray) && $this->bulletarray) {
6205 $actfs = $this->bulletarray['fontsize'];
6206 if (!$lhfixed) { $maxlineHeight = max($maxlineHeight,$actfs * $this->lineheight_correction ); }
6207 if ($lhfixed && $actfs > $def_fontsize) { $this->forceExactLineheight = false; }
6208 $maxfontsize = max($maxfontsize,$actfs);
6209 }
6210 /*-- END LISTS --*/
6211
6212 // when every text item checked i.e. $maxfontsize is set properly
6213
6214 $af = 0; // Above font
6215 $bf = 0; // Below font
6216 $mta = 0; // Maximum top-aligned
6217 $mba = 0; // Maximum bottom-aligned
6218
6219 foreach ( $content as $k => $chunk ) {
6220 if (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]) {
6221 $contentWidth += $this->objectbuffer[$k]['OUTER-WIDTH'] * _MPDFK;
6222 $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
6223 $va = $this->objectbuffer[$k]['vertical-align']; // = $objattr['vertical-align'] = set as M,T,B,S
6224 if ($lhfixed && $oh > $def_fontsize) { $this->forceExactLineheight = false; }
6225
6226 if ($va == 'BS') { // (BASELINE default)
6227 $af = max($af, ($oh - ($maxfontsize * (0.5 + $this->baselineC))));
6228 }
6229 else if ($va == 'M') {
6230 $af = max($af, ($oh - $maxfontsize)/2);
6231 $bf = max($bf, ($oh - $maxfontsize)/2);
6232 }
6233 else if ($va == 'TT') {
6234 $bf = max($bf, ($oh - $maxfontsize));
6235 }
6236 else if ($va == 'TB') {
6237 $af = max($af, ($oh - $maxfontsize));
6238 }
6239 else if ($va == 'T') {
6240 $mta = max($mta, $oh);
6241 }
6242 else if ($va == 'B') {
6243 $mba = max($mba, $oh);
6244 }
6245 }
6246 }
6247 if ((!$lhfixed || !$this->forceExactLineheight) && ($af > (($maxlineHeight - $maxfontsize)/2) || $bf > (($maxlineHeight - $maxfontsize)/2))) {
6248 $maxlineHeight = $maxfontsize + $af + $bf;
6249 }
6250 else if (!$lhfixed) { $af = $bf = ($maxlineHeight - $maxfontsize)/2; }
6251
6252 if ($mta > $maxlineHeight) {
6253 $bf += ($mta - $maxlineHeight);
6254 $maxlineHeight = $mta;
6255 }
6256 if ($mba > $maxlineHeight) {
6257 $af += ($mba - $maxlineHeight);
6258 $maxlineHeight = $mba;
6259 }
6260
6261
6262 $lineHeight = $maxlineHeight;
6263 $cutoffWidth = $contentWidth;
6264 // If NOT images, and maxfontsize NOT > lineHeight - this value determines text baseline positioning
6265 if ($lhfixed && $af==0 && $bf==0 && $maxfontsize<=($def_fontsize * $this->lineheight_correction * 0.8 )) {
6266 $this->linemaxfontsize = $def_fontsize;
6267 }
6268 else { $this->linemaxfontsize = $maxfontsize; }
6269
6270
6271 $inclCursive=false;
6272 foreach ( $content as $k => $chunk ) {
6273 if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
6274 if ($this->usingCoreFont) {
6275 $content[$k] = str_replace(chr(160),chr(32),$chunk );
6276 }
6277 else {
6278 $content[$k] = str_replace(chr(194).chr(160),chr(32),$chunk );
6279 if ($checkCursive) {
6280 if (preg_match("/([".$this->pregRTLchars."])/u", $chunk)) { $inclCursive = true; } // *RTL*
6281 if (preg_match("/([".$this->pregHIchars.$this->pregBNchars.$this->pregPAchars."])/u", $chunk)) { $inclCursive = true; } // *INDIC*
6282 }
6283 }
6284 }
6285 }
6286
6287 // JUSTIFICATION J
6288 $jcharspacing = 0;
6289 $jws = 0;
6290 $nb_carac = 0;
6291 $nb_spaces = 0;
6292 // 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)
6293 if ( ($align == 'J' && !$CJKoverflow) || (($cutoffWidth + $lastitalic > $maxWidth - $WidthCorrection - (($this->cMarginL+$this->cMarginR)*_MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) ) + 0.001) && (!$CJKoverflow || ($CJKoverflow && !$this->allowCJKoverflow))) || $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $hanger && $this->CJKforceend) { // 0.001 is to correct for deviations converting mm=>pts // mPDF 5.6.40
6294 // JUSTIFY J (Use character spacing)
6295 // WORD SPACING
6296 foreach ( $content as $k => $chunk ) {
6297 if (!isset($this->objectbuffer[$k]) || (isset($this->objectbuffer[$k]) && !$this->objectbuffer[$k])) {
6298 $nb_carac += mb_strlen( $chunk, $this->mb_enc ) ;
6299 $nb_spaces += mb_substr_count( $chunk,' ', $this->mb_enc ) ;
6300 }
6301 }
6302 list($jcharspacing,$jws) = $this->GetJspacing($nb_carac,$nb_spaces,($maxWidth-$lastitalic-$cutoffWidth-$WidthCorrection-(($this->cMarginL+$this->cMarginR)*_MPDFK)-($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) )),$inclCursive);
6303 }
6304
6305
6306 // WORD SPACING
6307 $empty = $maxWidth - $lastitalic-$WidthCorrection - $contentWidth - (($this->cMarginL+$this->cMarginR)* _MPDFK) - ($paddingL+$paddingR +(($fpaddingL + $fpaddingR) * _MPDFK) );
6308
6309 $empty -= ($jcharspacing * $nb_carac);
6310 $empty -= ($jws * $nb_spaces);
6311
6312 $empty /= _MPDFK;
6313 $b = ''; //do not use borders
6314 // Get PAGEBREAK TO TEST for height including the top border/padding
6315 $check_h = max($this->divheight,$lineHeight);
6316 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($this->blklvl > 0) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
6317 $check_h += ($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['border_top']['w']);
6318 }
6319
6320 if ($this->ColActive && $check_h > ($this->PageBreakTrigger - $this->y0)) {
6321 $this->SetCol($this->NbCol-1);
6322 }
6323
6324 // PAGEBREAK
6325 // 'If' below used in order to fix "first-line of other page with justify on" bug
6326 if(!$is_table && ($this->y+$check_h) > $this->PageBreakTrigger and !$this->InFooter and $this->AcceptPageBreak()) {
6327 $bak_x=$this->x;//Current X position
6328
6329 // WORD SPACING
6330 $ws=$this->ws;//Word Spacing
6331 $charspacing=$this->charspacing;//Character Spacing
6332 $this->ResetSpacing();
6333
6334 $this->AddPage($this->CurOrientation);
6335
6336 $this->x = $bak_x;
6337 // Added to correct for OddEven Margins
6338 $currentx += $this->MarginCorrection;
6339 $this->x += $this->MarginCorrection;
6340
6341 // WORD SPACING
6342 $this->SetSpacing($charspacing,$ws);
6343 }
6344
6345 if ($this->keep_block_together && !$is_table && $this->kt_p00 < $this->page && ($this->y+$check_h) > $this->kt_y00) {
6346 $this->printdivbuffer();
6347 $this->keep_block_together = 0;
6348 }
6349
6350 if ($this->kwt && !$is_table) { // mPDF 5.7+
6351 $this->printkwtbuffer();
6352 $this->kwt = false;
6353 }
6354
6355 /*-- COLUMNS --*/
6356 // COLS
6357 // COLUMN CHANGE
6358 if ($this->CurrCol != $oldcolumn) {
6359 $currentx += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
6360 $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
6361 $oldcolumn = $this->CurrCol;
6362 }
6363
6364 if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
6365 /*-- END COLUMNS --*/
6366
6367 // TOP MARGIN
6368 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($this->blk[$this->blklvl]['margin_top']) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
6369 $this->DivLn($this->blk[$this->blklvl]['margin_top'],$this->blklvl-1,true,$this->blk[$this->blklvl]['margin_collapse']);
6370 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
6371 }
6372
6373
6374 // Update y0 for top of block (used to paint border)
6375 if (($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
6376 $this->blk[$this->blklvl]['y0'] = $this->y;
6377 $this->blk[$this->blklvl]['startpage'] = $this->page;
6378 if ($this->blk[$this->blklvl]['float']) { $this->blk[$this->blklvl]['float_start_y'] = $this->y; } // mPDF 5.6.63
6379 }
6380
6381 // TOP PADDING and BORDER spacing/fill
6382 if (($newblock) && ($blockstate==1 || $blockstate==3) && (($this->blk[$this->blklvl]['padding_top']) || ($this->blk[$this->blklvl]['border_top'])) && ($lineCount == 1) && (!$is_table) && (!$is_list)) {
6383 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
6384 $this->DivLn($this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'],-3,true,false,1);
6385 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
6386 }
6387
6388 $arraysize = count($content);
6389
6390 $margins = ($this->cMarginL+$this->cMarginR) + ($ipaddingL+$ipaddingR + $fpaddingR + $fpaddingR );
6391
6392 // PAINT BACKGROUND FOR THIS LINE
6393 if (!$is_table) { $this->DivLn($lineHeight,$this->blklvl,false); } // false -> don't advance y
6394
6395 $this->x = $currentx + $this->cMarginL + $ipaddingL + $fpaddingL ;
6396 if ($align == 'R') { $this->x += $empty; }
6397 else if ($align == 'C') { $this->x += ($empty / 2); }
6398
6399 // Paragraph INDENT
6400 if (isset($this->blk[$this->blklvl]['text_indent']) && ($newblock) && ($blockstate==1 || $blockstate==3) && ($lineCount == 1) && (!$is_table) && ($blockdir !='rtl') && ($align !='C')) {
6401 $ti = $this->ConvertSize($this->blk[$this->blklvl]['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
6402 $this->x += $ti;
6403 }
6404
6405 // DIRECTIONALITY RTL
6406 $all_rtl = false;
6407 $contains_rtl = false;
6408 /*-- RTL --*/
6409 if ($blockdir == 'rtl' || $this->biDirectional) {
6410 $all_rtl = true;
6411 foreach ( $content as $k => $chunk ) {
6412 $reversed = $this->magic_reverse_dir($chunk, false, $blockdir);
6413
6414 if ($reversed > 0) { $contains_rtl = true; }
6415 if ($reversed < 2) { $all_rtl = false; }
6416 $content[$k] = $chunk;
6417 }
6418 if (($blockdir =='rtl' && $contains_rtl) || $all_rtl) {
6419 $content = array_reverse($content,false);
6420 $contentB = array_reverse($contentB,false);
6421 }
6422 }
6423 /*-- END RTL --*/
6424
6425 foreach ( $content as $k => $chunk ) {
6426
6427 // FOR IMAGES - UPDATE POSITION
6428 if (($blockdir =='rtl' && $contains_rtl) || $all_rtl) { $dirk = $arraysize-1 - $k ; } else { $dirk = $k; }
6429
6430 $va = 'M'; // default for text
6431 if (isset($this->objectbuffer[$dirk]) && $this->objectbuffer[$dirk]) {
6432 $xadj = $this->x - $this->objectbuffer[$dirk]['OUTER-X'] ;
6433 $this->objectbuffer[$dirk]['OUTER-X'] += $xadj;
6434 $this->objectbuffer[$dirk]['BORDER-X'] += $xadj;
6435 $this->objectbuffer[$dirk]['INNER-X'] += $xadj;
6436 $va = $this->objectbuffer[$dirk]['vertical-align'];
6437 $yadj = $this->y - $this->objectbuffer[$dirk]['OUTER-Y'];
6438 if ($va == 'BS') {
6439 $yadj += $af + ($this->linemaxfontsize * (0.5 + $this->baselineC)) - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
6440 }
6441 else if ($va == 'M' || $va == '') {
6442 $yadj += $af + ($this->linemaxfontsize /2) - ($this->objectbuffer[$dirk]['OUTER-HEIGHT']/2);
6443 }
6444 else if ($va == 'TB') {
6445 $yadj += $af + $this->linemaxfontsize - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
6446 }
6447 else if ($va == 'TT') {
6448 $yadj += $af;
6449 }
6450 else if ($va == 'B') {
6451 $yadj += $af + $this->linemaxfontsize + $bf - $this->objectbuffer[$dirk]['OUTER-HEIGHT'];
6452 }
6453 else if ($va == 'T') {
6454 $yadj += 0;
6455 }
6456 $this->objectbuffer[$dirk]['OUTER-Y'] += $yadj;
6457 $this->objectbuffer[$dirk]['BORDER-Y'] += $yadj;
6458 $this->objectbuffer[$dirk]['INNER-Y'] += $yadj;
6459 }
6460
6461 // DIRECTIONALITY RTL
6462 if ((($blockdir == 'rtl') && ($contains_rtl )) || ($all_rtl )) { $this->restoreFont($font[$arraysize-1 - $k]); }
6463 else { $this->restoreFont( $font[ $k ] ); }
6464
6465 $this->SetSpacing(($this->fixedlSpacing*_MPDFK)+$jcharspacing,($this->fixedlSpacing+$this->minwSpacing)*_MPDFK+$jws);
6466 // Now unset these values so they don't influence GetStringwidth below or in fn. Cell
6467 $this->fixedlSpacing = false;
6468 $this->minwSpacing = 0;
6469
6470 // mPDF 5.6.26
6471 $save_vis = $this->visibility;
6472 if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->textparam['visibility'] != $this->visibility) {
6473 $this->SetVisibility($this->textparam['visibility']);
6474 }
6475 // *********** SPAN BACKGROUND COLOR ***************** //
6476 if ($this->spanbgcolor) {
6477 $cor = $this->spanbgcolorarray;
6478 $this->SetFColor($cor);
6479 $save_fill = $fill; $spanfill = 1; $fill = 1;
6480 }
6481 if (!empty($this->spanborddet)) {
6482 if (strpos($contentB[$k],'L')!==false) $this->x += $this->spanborddet['L']['w'];
6483 if (strpos($contentB[$k],'L')===false) $this->spanborddet['L']['s'] = $this->spanborddet['L']['w'] = 0;
6484 if (strpos($contentB[$k],'R')===false) $this->spanborddet['R']['s'] = $this->spanborddet['R']['w'] = 0;
6485 }
6486
6487 // WORD SPACING
6488 $stringWidth = $this->GetStringWidth($chunk );
6489 $stringWidth += ( $this->charspacing * mb_strlen($chunk,$this->mb_enc ) / _MPDFK );
6490 $stringWidth += ( $this->ws * mb_substr_count($chunk,' ',$this->mb_enc ) / _MPDFK );
6491 if (isset($this->objectbuffer[$dirk])) { $stringWidth = $this->objectbuffer[$dirk]['OUTER-WIDTH']; }
6492
6493 if ($stringWidth==0) { $stringWidth = 0.000001; }
6494 if ($k == $arraysize-1) {
6495 $stringWidth -= ( $this->charspacing / _MPDFK );
6496 // mPDF 5.6.40
6497 if ($this->checkCJK && $CJKoverflow && $align=='J' && $this->allowCJKoverflow && $hanger && $this->CJKforceend) {
6498 // force-end overhang
6499 $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
6500 $this->Cell( $this->GetStringWidth($hanger), $lineHeight, $hanger, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true );
6501 }
6502 else {
6503 $this->Cell( $stringWidth, $lineHeight, $chunk, '', 1, '', $fill, $this->HREF, $currentx,0,0,'M', $fill, $af, $bf, true ); //mono-style line or last part (skips line)
6504 }
6505
6506 }
6507 else $this->Cell( $stringWidth, $lineHeight, $chunk, '', 0, '', $fill, $this->HREF, 0, 0,0,'M', $fill, $af, $bf, true );//first or middle part
6508
6509 if (!empty($this->spanborddet)) {
6510 if (strpos($contentB[$k],'R')!==false && $k != $arraysize-1) $this->x += $this->spanborddet['R']['w'];
6511 }
6512 // *********** SPAN BACKGROUND COLOR OFF - RESET BLOCK BGCOLOR ***************** //
6513 if (isset($spanfill) && $spanfill) {
6514 $fill = $save_fill; $spanfill = 0;
6515 if ($fill) { $this->SetFColor($bcor); }
6516 }
6517 // mPDF 5.6.26
6518 if (isset($this->textparam['visibility']) && $this->textparam['visibility'] && $this->visibility != $save_vis) {
6519 $this->SetVisibility($save_vis);
6520 }
6521
6522 }
6523 if (!$is_table) {
6524 $this->maxPosR = max($this->maxPosR , ($this->w - $this->rMargin - $this->blk[$this->blklvl]['outer_right_margin']));
6525 $this->maxPosL = min($this->maxPosL , ($this->lMargin + $this->blk[$this->blklvl]['outer_left_margin']));
6526 }
6527
6528 // move on to the next line, reset variables, tack on saved content and current char
6529
6530 $this->printobjectbuffer($is_table, $blockdir);
6531 $this->objectbuffer = array();
6532
6533 /*-- LISTS --*/
6534 // LIST BULLETS/NUMBERS
6535 if ($is_list && is_array($this->bulletarray) && ($lineCount == 1) ) {
6536
6537 $this->ResetSpacing();
6538
6539 $bull = $this->bulletarray;
6540 if (isset($bull['level']) && isset($bull['occur']) && isset($this->InlineProperties['LIST'][$bull['level']][$bull['occur']])) {
6541 $this->restoreInlineProperties($this->InlineProperties['LIST'][$bull['level']][$bull['occur']]);
6542 }
6543 if (isset($bull['level']) && isset($bull['occur']) && isset($bull['num']) && isset($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) && $this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]) { $this->restoreInlineProperties($this->InlineProperties['LISTITEM'][$bull['level']][$bull['occur']][$bull['num']]); }
6544 if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
6545 $this->bullet = true;
6546 $this->SetFont('czapfdingbats','',$this->FontSizePt/2.5);
6547 }
6548 else { $this->SetFont($this->FontFamily,$this->FontStyle,$this->FontSizePt,true,true); } // force output
6549 //Output bullet
6550 $this->x = $currentx;
6551 if (isset($bull['x'])) { $this->x += $bull['x']; }
6552 $this->y -= $lineHeight;
6553 if (isset($bull['col']) && $bull['col']) { $this->SetTColor($bull['col']); } // mPDF 5.6.67
6554 if (isset($bull['txt'])) { $this->Cell($bull['w'], $lineHeight,$bull['txt'],'','',$bull['align'],0,'',0,-$this->cMarginL, -$this->cMarginR ); }
6555 if (isset($bull['font']) && $bull['font'] == 'czapfdingbats') {
6556 $this->bullet = false;
6557 }
6558 $this->x = $currentx; // Reset
6559 $this->y += $lineHeight;
6560
6561 if ($this->ColActive && !$is_table) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
6562
6563 $this->bulletarray = array(); // prevents repeat of bullet/number if <li>....<br />.....</li>
6564 }
6565 /*-- END LISTS --*/
6566
6567
6568 /*-- CSS-IMAGE-FLOAT --*/
6569 // Update values if set to skipline
6570 if ($this->floatmargins) { $this->_advanceFloatMargins(); }
6571 /*-- END CSS-IMAGE-FLOAT --*/
6572
6573 // Reset lineheight
6574 $lineHeight = $this->divheight;
6575 $valign = 'M';
6576
6577 $font = array();
6578 $content = array();
6579 $contentB = array();
6580 $contentWidth = 0;
6581 if (!empty($savedObj)) {
6582 $this->objectbuffer[] = $savedObj;
6583 $font[] = $savedFont;
6584 $content[] = '';
6585 $contentB[] = '';
6586 $contentWidth += $savedObj['OUTER-WIDTH'] * _MPDFK;
6587 }
6588 // mPDF 5.6.20
6589 if (count($savedPreContent) > 0) {
6590 for($ix=count($savedPreContent)-1;$ix>=0;$ix--) {
6591 $font[] = $savedPreFont[$ix];
6592 $content[] = $savedPreContent[$ix];
6593 $contentB[] = $savedPreContentB[$ix];
6594 $this->restoreFont( $savedPreFont[$ix] );
6595 $lbw = $rbw = 0; // Border widths
6596 if (!empty($this->spanborddet)) {
6597 $lbw = $this->spanborddet['L']['w'];
6598 $rbw = $this->spanborddet['R']['w'];
6599 }
6600 if ($ix>0) {
6601 $contentWidth += $this->GetStringWidth( $savedPreContent[$ix] ) * _MPDFK;
6602 if (strpos($savedPreContentB[$ix],'L')!==false) $contentWidth += $lbw;
6603 if (strpos($savedPreContentB[$ix],'R')!==false) $contentWidth += $rbw;
6604 }
6605 }
6606 $savedPreContent = array();
6607 $savedPreContentB = array();
6608 $savedPreFont = array();
6609 $content[ (count($content)-1) ] .= $c;
6610 }
6611 else {
6612 $font[] = $savedFont;
6613 $content[] = $savedContent . $c;
6614 $contentB[] = $savedContentB ;
6615 }
6616
6617 $currContent =& $content[ (count($content)-1) ];
6618
6619 // CJK - strip CJK space at end of line
6620 // &#x3000; = \xe3\x80\x80 = CJK space
6621 if ($this->checkCJK && $currContent == "\xe3\x80\x80") { $currContent = '' ; } // *CJK-FONTS*
6622
6623 $this->restoreFont( $savedFont );
6624 $lbw = $rbw = 0; // Border widths
6625 if (!empty($this->spanborddet)) {
6626 $lbw = $this->spanborddet['L']['w'];
6627 $rbw = $this->spanborddet['R']['w'];
6628 }
6629 $contentWidth += $this->GetStringWidth( $currContent ) * _MPDFK;
6630 if (strpos($savedContentB,'L')!==false) $contentWidth += $lbw;
6631 $cutoffWidth = $contentWidth;
6632 $CJKoverflow = false;
6633 $hanger = ''; // mPDF 5.6.40
6634 }
6635 // another character will fit, so add it on
6636 else {
6637 $contentWidth += $cw;
6638 $currContent .= $c;
6639 }
6640 }
6641 unset($content);
6642 unset($contentB);
6643 }
6644 //----------------------END OF FLOWING BLOCK------------------------------------//
6645
6646
6647 /*-- CSS-IMAGE-FLOAT --*/
6648 // Update values if set to skipline
6649 function _advanceFloatMargins() {
6650 // Update floatmargins - L
6651 if (isset($this->floatmargins['L']) && $this->floatmargins['L']['skipline'] && $this->floatmargins['L']['y0'] != $this->y) {
6652 $yadj = $this->y - $this->floatmargins['L']['y0'];
6653 $this->floatmargins['L']['y0'] = $this->y;
6654 $this->floatmargins['L']['y1'] += $yadj;
6655
6656 // Update objattr in floatbuffer
6657 if ($this->floatbuffer[$this->floatmargins['L']['id']]['border_left']['w']) {
6658 $this->floatbuffer[$this->floatmargins['L']['id']]['BORDER-Y'] += $yadj;
6659 }
6660 $this->floatbuffer[$this->floatmargins['L']['id']]['INNER-Y'] += $yadj;
6661 $this->floatbuffer[$this->floatmargins['L']['id']]['OUTER-Y'] += $yadj;
6662
6663 // Unset values
6664 $this->floatbuffer[$this->floatmargins['L']['id']]['skipline'] = false;
6665 $this->floatmargins['L']['skipline'] = false;
6666 $this->floatmargins['L']['id'] = '';
6667 }
6668 // Update floatmargins - R
6669 if (isset($this->floatmargins['R']) && $this->floatmargins['R']['skipline'] && $this->floatmargins['R']['y0'] != $this->y) {
6670 $yadj = $this->y - $this->floatmargins['R']['y0'];
6671 $this->floatmargins['R']['y0'] = $this->y;
6672 $this->floatmargins['R']['y1'] += $yadj;
6673
6674 // Update objattr in floatbuffer
6675 if ($this->floatbuffer[$this->floatmargins['R']['id']]['border_left']['w']) {
6676 $this->floatbuffer[$this->floatmargins['R']['id']]['BORDER-Y'] += $yadj;
6677 }
6678 $this->floatbuffer[$this->floatmargins['R']['id']]['INNER-Y'] += $yadj;
6679 $this->floatbuffer[$this->floatmargins['R']['id']]['OUTER-Y'] += $yadj;
6680
6681 // Unset values
6682 $this->floatbuffer[$this->floatmargins['R']['id']]['skipline'] = false;
6683 $this->floatmargins['R']['skipline'] = false;
6684 $this->floatmargins['R']['id'] = '';
6685 }
6686 }
6687 /*-- END CSS-IMAGE-FLOAT --*/
6688
6689
6690
6691 ////////////////////////////////////////////////////////////////////////////////
6692 // ADDED forcewrap - to call from inline OBJECT functions to breakwords if necessary in cell
6693 ////////////////////////////////////////////////////////////////////////////////
6694 function WordWrap(&$text, $maxwidth, $forcewrap = 0) {
6695 $biggestword=0;
6696 $toonarrow=false;
6697
6698 $text = trim($text);
6699
6700 if ($text==='') return 0;
6701 $space = $this->GetCharWidth(' ',false);
6702 $lines = explode("\n", $text);
6703 $text = '';
6704 $count = 0;
6705 foreach ($lines as $line) {
6706 $words = explode(' ', $line);
6707 $width = 0;
6708 foreach ($words as $word) {
6709 $word = trim($word);
6710 $wordwidth = $this->GetStringWidth($word);
6711 //Warn user that maxwidth is insufficient
6712 if ($wordwidth > $maxwidth + 0.0001) {
6713 if ($wordwidth > $biggestword) { $biggestword = $wordwidth; }
6714 $toonarrow=true;
6715 // ADDED
6716 if ($forcewrap) {
6717 while($wordwidth > $maxwidth) {
6718 $chw = 0; // check width
6719 for ( $i = 0; $i < mb_strlen($word, $this->mb_enc ); $i++ ) {
6720 $chw = $this->GetStringWidth(mb_substr($word,0,$i+1,$this->mb_enc ));
6721 if ($chw > $maxwidth ) {
6722 if ($text) {
6723 $text = rtrim($text)."\n".mb_substr($word,0,$i,$this->mb_enc );
6724 $count++;
6725 }
6726 else {
6727 $text = mb_substr($word,0,$i,$this->mb_enc );
6728 }
6729 $word = mb_substr($word,$i,mb_strlen($word, $this->mb_enc )-$i,$this->mb_enc );
6730 $wordwidth = $this->GetStringWidth($word);
6731 $width = $maxwidth;
6732 break;
6733 }
6734 }
6735 }
6736 }
6737 }
6738
6739 if ($width + $wordwidth < $maxwidth - 0.0001) {
6740 $width += $wordwidth + $space;
6741 $text .= $word.' ';
6742 }
6743 else {
6744 $width = $wordwidth + $space;
6745 $text = rtrim($text)."\n".$word.' ';
6746 $count++;
6747 }
6748 }
6749 $text .= "\n";
6750 $count++;
6751 }
6752 $text = rtrim($text);
6753
6754 //Return -(wordsize) if word is bigger than maxwidth
6755
6756 // ADDED
6757 if ($forcewrap) { return $count; }
6758 if (($toonarrow) && ($this->table_error_report)) {
6759 $this->Error("Word is too long to fit in table - ".$this->table_error_report_param);
6760 }
6761 if ($toonarrow) return -$biggestword;
6762 else return $count;
6763 }
6764
6765 /*-- END HTML-CSS --*/
6766
6767 function _SetTextRendering($mode) {
6768 if (!(($mode == 0) || ($mode == 1) || ($mode == 2)))
6769 $this->Error("Text rendering mode should be 0, 1 or 2 (value : $mode)");
6770 $tr = ($mode.' Tr');
6771 if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']) || $this->keep_block_together)) { $this->_out($tr); }
6772 $this->pageoutput[$this->page]['TextRendering'] = $tr;
6773
6774 }
6775
6776 function SetTextOutline($params=array()) { // mPDF 5.6.07
6777 if (isset($params['outline-s']) && $params['outline-s'])
6778 {
6779 $this->SetLineWidth($params['outline-WIDTH']);
6780 $this->SetDColor($params['outline-COLOR']);
6781 $tr = ('2 Tr');
6782 if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']) || $this->keep_block_together)) { $this->_out($tr); }
6783 $this->pageoutput[$this->page]['TextRendering'] = $tr;
6784 }
6785 else //Now resets all values
6786 {
6787 $this->SetLineWidth(0.2);
6788 $this->SetDColor($this->ConvertColor(0));
6789 $this->_SetTextRendering(0);
6790 $tr = ('0 Tr');
6791 if($this->page>0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']) || $this->keep_block_together)) { $this->_out($tr); }
6792 $this->pageoutput[$this->page]['TextRendering'] = $tr;
6793 }
6794 }
6795
6796 function Image($file,$x,$y,$w=0,$h=0,$type='',$link='',$paint=true, $constrain=true, $watermark=false, $shownoimg=true, $allowvector=true) {
6797 $orig_srcpath = $file;
6798 $this->GetFullPath($file);
6799
6800 $info=$this->_getImage($file, true, $allowvector, $orig_srcpath );
6801 if(!$info && $paint) {
6802 $info = $this->_getImage($this->noImageFile);
6803 if ($info) {
6804 $file = $this->noImageFile;
6805 $w = ($info['w'] * (25.4/$this->dpi)); // 14 x 16px
6806 $h = ($info['h'] * (25.4/$this->dpi)); // 14 x 16px
6807 }
6808 }
6809 if(!$info) return false;
6810 //Automatic width and height calculation if needed
6811 if($w==0 and $h==0) {
6812 /*-- IMAGES-WMF --*/
6813 if ($info['type']=='wmf') {
6814 // WMF units are twips (1/20pt)
6815 // divide by 20 to get points
6816 // divide by k to get user units
6817 $w = abs($info['w'])/(20*_MPDFK);
6818 $h = abs($info['h']) / (20*_MPDFK);
6819 }
6820 else
6821 /*-- END IMAGES-WMF --*/
6822 if ($info['type']=='svg') {
6823 // returned SVG units are pts
6824 // divide by k to get user units (mm)
6825 $w = abs($info['w'])/_MPDFK;
6826 $h = abs($info['h']) /_MPDFK;
6827 }
6828 else {
6829 //Put image at default image dpi
6830 $w=($info['w']/_MPDFK) * (72/$this->img_dpi);
6831 $h=($info['h']/_MPDFK) * (72/$this->img_dpi);
6832 }
6833 }
6834 if($w==0) $w=abs($h*$info['w']/$info['h']);
6835 if($h==0) $h=abs($w*$info['h']/$info['w']);
6836
6837 /*-- WATERMARK --*/
6838 if ($watermark) {
6839 $maxw = $this->w;
6840 $maxh = $this->h;
6841 // Size = D PF or array
6842 if (is_array($this->watermark_size)) {
6843 $w = $this->watermark_size[0];
6844 $h = $this->watermark_size[1];
6845 }
6846 else if (!is_string($this->watermark_size)) {
6847 $maxw -= $this->watermark_size*2;
6848 $maxh -= $this->watermark_size*2;
6849 $w = $maxw;
6850 $h=abs($w*$info['h']/$info['w']);
6851 if ($h > $maxh ) {
6852 $h = $maxh ; $w=abs($h*$info['w']/$info['h']);
6853 }
6854 }
6855 else if ($this->watermark_size == 'F') {
6856 if ($this->ColActive) { $maxw = $this->w - ($this->DeflMargin + $this->DefrMargin); }
6857 else { $maxw = $this->pgwidth; }
6858 $maxh = $this->h - ($this->tMargin + $this->bMargin);
6859 $w = $maxw;
6860 $h=abs($w*$info['h']/$info['w']);
6861 if ($h > $maxh ) {
6862 $h = $maxh ; $w=abs($h*$info['w']/$info['h']);
6863 }
6864 }
6865 else if ($this->watermark_size == 'P') { // Default P
6866 $w = $maxw;
6867 $h=abs($w*$info['h']/$info['w']);
6868 if ($h > $maxh ) {
6869 $h = $maxh ; $w=abs($h*$info['w']/$info['h']);
6870 }
6871 }
6872 // Automatically resize to maximum dimensions of page if too large
6873 if ($w > $maxw) {
6874 $w = $maxw;
6875 $h=abs($w*$info['h']/$info['w']);
6876 }
6877 if ($h > $maxh ) {
6878 $h = $maxh ;
6879 $w=abs($h*$info['w']/$info['h']);
6880 }
6881 // Position
6882 if (is_array($this->watermark_pos)) {
6883 $x = $this->watermark_pos[0];
6884 $y = $this->watermark_pos[1];
6885 }
6886 else if ($this->watermark_pos == 'F') { // centred on printable area
6887 if ($this->ColActive) { // *COLUMNS*
6888 if (($this->mirrorMargins) && (($this->page)%2==0)) { $xadj = $this->DeflMargin-$this->DefrMargin; } // *COLUMNS*
6889 else { $xadj = 0; } // *COLUMNS*
6890 $x = ($this->DeflMargin - $xadj + ($this->w - ($this->DeflMargin + $this->DefrMargin))/2) - ($w/2); // *COLUMNS*
6891 } // *COLUMNS*
6892 else { // *COLUMNS*
6893 $x = ($this->lMargin + ($this->pgwidth)/2) - ($w/2);
6894 } // *COLUMNS*
6895 $y = ($this->tMargin + ($this->h - ($this->tMargin + $this->bMargin))/2) - ($h/2);
6896 }
6897 else { // default P - centred on whole page
6898 $x = ($this->w/2) - ($w/2);
6899 $y = ($this->h/2) - ($h/2);
6900 }
6901 /*-- IMAGES-WMF --*/
6902 if ($info['type']=='wmf') {
6903 $sx = $w*_MPDFK / $info['w'];
6904 $sy = -$h*_MPDFK / $info['h'];
6905 $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']);
6906 }
6907 else
6908 /*-- END IMAGES-WMF --*/
6909 if ($info['type']=='svg') {
6910 $sx = $w*_MPDFK / $info['w'];
6911 $sy = -$h*_MPDFK / $info['h'];
6912 $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']);
6913 }
6914 else {
6915 $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']);
6916 }
6917
6918 if ($this->watermarkImgBehind) {
6919 $outstring = $this->watermarkImgAlpha . "\n" . $outstring . "\n" . $this->SetAlpha(1, 'Normal', true) . "\n";
6920 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', "\n".$outstring."\n".'\\1', $this->pages[$this->page]);
6921 }
6922 else { $this->_out($outstring); }
6923
6924 return 0;
6925 } // end of IF watermark
6926 /*-- END WATERMARK --*/
6927
6928 if ($constrain) {
6929 // Automatically resize to maximum dimensions of page if too large
6930 if (isset($this->blk[$this->blklvl]['inner_width']) && $this->blk[$this->blklvl]['inner_width']) { $maxw = $this->blk[$this->blklvl]['inner_width']; }
6931 else { $maxw = $this->pgwidth; }
6932 if ($w > $maxw) {
6933 $w = $maxw;
6934 $h=abs($w*$info['h']/$info['w']);
6935 }
6936 if ($h > $this->h - ($this->tMargin + $this->bMargin + 1)) { // see below - +10 to avoid drawing too close to border of page
6937 $h = $this->h - ($this->tMargin + $this->bMargin + 1) ;
6938 if ($this->fullImageHeight) { $h = $this->fullImageHeight; }
6939 $w=abs($h*$info['w']/$info['h']);
6940 }
6941
6942
6943 //Avoid drawing out of the paper(exceeding width limits).
6944 //if ( ($x + $w) > $this->fw ) {
6945 if ( ($x + $w) > $this->w ) {
6946 $x = $this->lMargin;
6947 $y += 5;
6948 }
6949
6950 $changedpage = false;
6951 $oldcolumn = $this->CurrCol;
6952 //Avoid drawing out of the page.
6953 if($y+$h>$this->PageBreakTrigger and !$this->InFooter and $this->AcceptPageBreak()) {
6954 $this->AddPage($this->CurOrientation);
6955 // Added to correct for OddEven Margins
6956 $x=$x +$this->MarginCorrection;
6957 $y = $tMargin + $this->margin_header;
6958 $changedpage = true;
6959 }
6960 /*-- COLUMNS --*/
6961 // COLS
6962 // COLUMN CHANGE
6963 if ($this->CurrCol != $oldcolumn) {
6964 $y = $this->y0;
6965 $x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
6966 $this->x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
6967 }
6968 /*-- END COLUMNS --*/
6969 } // end of IF constrain
6970
6971 /*-- IMAGES-WMF --*/
6972 if ($info['type']=='wmf') {
6973 $sx = $w*_MPDFK / $info['w'];
6974 $sy = -$h*_MPDFK / $info['h'];
6975 $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']);
6976 }
6977 else
6978 /*-- END IMAGES-WMF --*/
6979 if ($info['type']=='svg') {
6980 $sx = $w*_MPDFK / $info['w'];
6981 $sy = -$h*_MPDFK / $info['h'];
6982 $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']);
6983 }
6984 else {
6985 $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']);
6986 }
6987
6988 if($paint) {
6989 $this->_out($outstring);
6990 if($link) $this->Link($x,$y,$w,$h,$link);
6991
6992 // Avoid writing text on top of the image. // THIS WAS OUTSIDE THE if ($paint) bit!!!!!!!!!!!!!!!!
6993 $this->y = $y + $h;
6994 }
6995
6996 //Return width-height array
6997 $sizesarray['WIDTH'] = $w;
6998 $sizesarray['HEIGHT'] = $h;
6999 $sizesarray['X'] = $x; //Position before painting image
7000 $sizesarray['Y'] = $y; //Position before painting image
7001 $sizesarray['OUTPUT'] = $outstring;
7002
7003 $sizesarray['IMAGE_ID'] = $info['i'];
7004 $sizesarray['itype'] = $info['type'];
7005 $sizesarray['set-dpi'] = $info['set-dpi'];
7006 return $sizesarray;
7007 }
7008
7009
7010
7011 //=============================================================
7012 //=============================================================
7013 //=============================================================
7014 //=============================================================
7015 //=============================================================
7016 /*-- HTML-CSS --*/
7017
7018 function _getObjAttr($t) {
7019 $c = explode("\xbb\xa4\xac",$t,2);
7020 $c = explode(",",$c[1],2);
7021 foreach($c as $v) {
7022 $v = explode("=",$v,2);
7023 $sp[$v[0]] = $v[1];
7024 }
7025 return (unserialize($sp['objattr']));
7026 }
7027
7028
7029 function inlineObject($type,$x,$y,$objattr,$Lmargin,$widthUsed,$maxWidth,$lineHeight,$paint=false,$is_table=false)
7030 {
7031 if ($is_table) { $k = $this->shrin_k; } else { $k = 1; }
7032
7033 // NB $x is only used when paint=true
7034 // Lmargin not used
7035 $w = 0;
7036 if (isset($objattr['width'])) { $w = $objattr['width']/$k; }
7037 $h = 0;
7038 if (isset($objattr['height'])) { $h = abs($objattr['height']/$k); }
7039 $widthLeft = $maxWidth - $widthUsed;
7040 $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 10) ;
7041 if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
7042 // For Images
7043 if (isset($objattr['border_left'])) {
7044 $extraWidth = ($objattr['border_left']['w'] + $objattr['border_right']['w'] + $objattr['margin_left']+ $objattr['margin_right'])/$k;
7045 $extraHeight = ($objattr['border_top']['w'] + $objattr['border_bottom']['w'] + $objattr['margin_top']+ $objattr['margin_bottom'])/$k;
7046
7047 if ($type == 'image' || $type == 'barcode' || $type == 'textcircle') {
7048 $extraWidth += ($objattr['padding_left'] + $objattr['padding_right'])/$k;
7049 $extraHeight += ($objattr['padding_top'] + $objattr['padding_bottom'])/$k;
7050 }
7051 }
7052
7053 if (!isset($objattr['vertical-align'])) { $objattr['vertical-align'] = 'M'; }
7054
7055 if ($type == 'image' || (isset($objattr['subtype']) && $objattr['subtype'] == 'IMAGE')) {
7056 if (isset($objattr['itype']) && ($objattr['itype'] == 'wmf' || $objattr['itype'] == 'svg')) {
7057 $file = $objattr['file'];
7058 $info=$this->formobjects[$file];
7059 }
7060 else if (isset($objattr['file'])) {
7061 $file = $objattr['file'];
7062 $info=$this->images[$file];
7063 }
7064 }
7065 if ($type == 'annot' || $type == 'bookmark' || $type == 'indexentry' || $type == 'toc') {
7066 $w = 0.00001;
7067 $h = 0.00001;
7068 }
7069
7070 // TEST whether need to skipline
7071 if (!$paint) {
7072 if ($type == 'hr') { // always force new line
7073 if (($y + $h + $lineHeight > $this->PageBreakTrigger) && !$this->InFooter && !$is_table) { return array(-2, $w ,$h ); } // New page + new line
7074 else { return array(1, $w ,$h ); } // new line
7075 }
7076 else {
7077 if ($widthUsed > 0 && $w > $widthLeft && (!$is_table || $type != 'image')) { // New line needed
7078 if (($y + $h + $lineHeight > $this->PageBreakTrigger) && !$this->InFooter) { return array(-2,$w ,$h ); } // New page + new line
7079 return array(1,$w ,$h ); // new line
7080 }
7081 else if ($widthUsed > 0 && $w > $widthLeft && $is_table) { // New line needed in TABLE
7082 return array(1,$w ,$h ); // new line
7083 }
7084 // Will fit on line but NEW PAGE REQUIRED
7085 else if (($y + $h > $this->PageBreakTrigger) && !$this->InFooter && !$is_table) { return array(-1,$w ,$h ); }
7086 else { return array(0,$w ,$h ); }
7087 }
7088 }
7089
7090 if ($type == 'annot' || $type == 'bookmark' || $type == 'indexentry' || $type == 'toc') {
7091 $w = 0.00001;
7092 $h = 0.00001;
7093 $objattr['BORDER-WIDTH'] = 0;
7094 $objattr['BORDER-HEIGHT'] = 0;
7095 $objattr['BORDER-X'] = $x;
7096 $objattr['BORDER-Y'] = $y;
7097 $objattr['INNER-WIDTH'] = 0;
7098 $objattr['INNER-HEIGHT'] = 0;
7099 $objattr['INNER-X'] = $x;
7100 $objattr['INNER-Y'] = $y;
7101 }
7102
7103 if ($type == 'image') {
7104 // Automatically resize to width remaining
7105 if ($w > $widthLeft && !$is_table) {
7106 $w = $widthLeft ;
7107 $h=abs($w*$info['h']/$info['w']);
7108 }
7109 $img_w = $w - $extraWidth ;
7110 $img_h = $h - $extraHeight ;
7111
7112 $objattr['BORDER-WIDTH'] = $img_w + $objattr['padding_left']/$k + $objattr['padding_right']/$k + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
7113 $objattr['BORDER-HEIGHT'] = $img_h + $objattr['padding_top']/$k + $objattr['padding_bottom']/$k + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
7114 $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
7115 $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
7116 $objattr['INNER-WIDTH'] = $img_w;
7117 $objattr['INNER-HEIGHT'] = $img_h;
7118 $objattr['INNER-X'] = $x + $objattr['padding_left']/$k + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
7119 $objattr['INNER-Y'] = $y + $objattr['padding_top']/$k + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
7120 $objattr['ID'] = $info['i'];
7121 }
7122
7123 if ($type == 'input' && $objattr['subtype'] == 'IMAGE') {
7124 $img_w = $w - $extraWidth ;
7125 $img_h = $h - $extraHeight ;
7126 $objattr['BORDER-WIDTH'] = $img_w + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
7127 $objattr['BORDER-HEIGHT'] = $img_h + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
7128 $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
7129 $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
7130 $objattr['INNER-WIDTH'] = $img_w;
7131 $objattr['INNER-HEIGHT'] = $img_h;
7132 $objattr['INNER-X'] = $x + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
7133 $objattr['INNER-Y'] = $y + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
7134 $objattr['ID'] = $info['i'];
7135 }
7136
7137 if ($type == 'barcode' || $type == 'textcircle') {
7138 $b_w = $w - $extraWidth ;
7139 $b_h = $h - $extraHeight ;
7140 $objattr['BORDER-WIDTH'] = $b_w + $objattr['padding_left']/$k + $objattr['padding_right']/$k + (($objattr['border_left']['w']/$k + $objattr['border_right']['w']/$k)/2) ;
7141 $objattr['BORDER-HEIGHT'] = $b_h + $objattr['padding_top']/$k + $objattr['padding_bottom']/$k + (($objattr['border_top']['w']/$k + $objattr['border_bottom']['w']/$k)/2) ;
7142 $objattr['BORDER-X'] = $x + $objattr['margin_left']/$k + (($objattr['border_left']['w']/$k)/2) ;
7143 $objattr['BORDER-Y'] = $y + $objattr['margin_top']/$k + (($objattr['border_top']['w']/$k)/2) ;
7144 $objattr['INNER-X'] = $x + $objattr['padding_left']/$k + $objattr['margin_left']/$k + ($objattr['border_left']['w']/$k);
7145 $objattr['INNER-Y'] = $y + $objattr['padding_top']/$k + $objattr['margin_top']/$k + ($objattr['border_top']['w']/$k) ;
7146 $objattr['INNER-WIDTH'] = $b_w;
7147 $objattr['INNER-HEIGHT'] = $b_h;
7148 }
7149
7150
7151 if ($type == 'textarea') {
7152 // Automatically resize to width remaining
7153 if ($w > $widthLeft && !$is_table) {
7154 $w = $widthLeft ;
7155 }
7156 if (($y + $h > $this->PageBreakTrigger) && !$this->InFooter) {
7157 $h=$this->h - $y - $this->bMargin;
7158 }
7159 }
7160
7161 if ($type == 'hr') {
7162 if ($is_table) {
7163 $objattr['INNER-WIDTH'] = $maxWidth * $objattr['W-PERCENT']/100;
7164 $objattr['width'] = $objattr['INNER-WIDTH'];
7165 $w = $maxWidth;
7166 }
7167 else {
7168 if ($w>$maxWidth) { $w = $maxWidth; }
7169 $objattr['INNER-WIDTH'] = $w;
7170 $w = $maxWidth;
7171 }
7172 }
7173
7174
7175
7176 if (($type == 'select') || ($type == 'input' && ($objattr['subtype'] == 'TEXT' || $objattr['subtype'] == 'PASSWORD'))) {
7177 // Automatically resize to width remaining
7178 if ($w > $widthLeft && !$is_table) {
7179 $w = $widthLeft;
7180 }
7181 }
7182
7183 if ($type == 'textarea' || $type == 'select' || $type == 'input') {
7184 if (isset($objattr['fontsize'])) $objattr['fontsize'] /= $k;
7185 if (isset($objattr['linewidth'])) $objattr['linewidth'] /= $k;
7186 }
7187
7188 if (!isset($objattr['BORDER-Y'])) { $objattr['BORDER-Y'] = 0; }
7189 if (!isset($objattr['BORDER-X'])) { $objattr['BORDER-X'] = 0; }
7190 if (!isset($objattr['INNER-Y'])) { $objattr['INNER-Y'] = 0; }
7191 if (!isset($objattr['INNER-X'])) { $objattr['INNER-X'] = 0; }
7192
7193 //Return width-height array
7194 $objattr['OUTER-WIDTH'] = $w;
7195 $objattr['OUTER-HEIGHT'] = $h;
7196 $objattr['OUTER-X'] = $x;
7197 $objattr['OUTER-Y'] = $y;
7198 return $objattr;
7199 }
7200
7201 /*-- END HTML-CSS --*/
7202
7203 //=============================================================
7204 //=============================================================
7205 //=============================================================
7206 //=============================================================
7207 //=============================================================
7208
7209 function SetLineJoin($mode=0)
7210 {
7211 $s=sprintf('%d j',$mode);
7212 if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineJoin']) && $this->pageoutput[$this->page]['LineJoin'] != $s) || !isset($this->pageoutput[$this->page]['LineJoin']) || $this->keep_block_together)) { $this->_out($s); }
7213 $this->pageoutput[$this->page]['LineJoin'] = $s;
7214
7215 }
7216 function SetLineCap($mode=2) {
7217 $s=sprintf('%d J',$mode);
7218 if($this->page>0 && ((isset($this->pageoutput[$this->page]['LineCap']) && $this->pageoutput[$this->page]['LineCap'] != $s) || !isset($this->pageoutput[$this->page]['LineCap']) || $this->keep_block_together)) { $this->_out($s); }
7219 $this->pageoutput[$this->page]['LineCap'] = $s;
7220
7221 }
7222
7223 function SetDash($black=false,$white=false)
7224 {
7225 if($black and $white) $s=sprintf('[%.3F %.3F] 0 d',$black*_MPDFK,$white*_MPDFK);
7226 else $s='[] 0 d';
7227 if($this->page>0 && ((isset($this->pageoutput[$this->page]['Dash']) && $this->pageoutput[$this->page]['Dash'] != $s) || !isset($this->pageoutput[$this->page]['Dash']) || $this->keep_block_together)) { $this->_out($s); }
7228 $this->pageoutput[$this->page]['Dash'] = $s;
7229
7230 }
7231
7232 function SetDisplayPreferences($preferences) {
7233 // String containing any or none of /HideMenubar/HideToolbar/HideWindowUI/DisplayDocTitle/CenterWindow/FitWindow
7234 $this->DisplayPreferences .= $preferences;
7235 }
7236
7237
7238 function Ln($h='',$collapsible=0)
7239 {
7240 // Added collapsible to allow collapsible top-margin on new page
7241 //Line feed; default value is last cell height
7242 $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
7243 if ($collapsible && ($this->y==$this->tMargin) && (!$this->ColActive)) { $h = 0; }
7244 if(is_string($h)) $this->y+=$this->lasth;
7245 else $this->y+=$h;
7246 }
7247
7248 /*-- HTML-CSS --*/
7249 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
7250 function DivLn($h,$level=-3,$move_y=true,$collapsible=false,$state=0) {
7251 // this->x is returned as it was
7252 // adds lines (y) where DIV bgcolors are filled in
7253 // allows .00001 as nominal height used for bookmarks/annotations etc.
7254 if ($collapsible && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->tMargin)) && (!$this->ColActive)) { return; }
7255 if ($collapsible && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->y0)) && ($this->ColActive) && $this->CurrCol == 0) { return; } // *COLUMNS*
7256
7257 // Still use this method if columns or page-break-inside: avoid, as it allows repositioning later
7258 // otherwise, now uses PaintDivBB()
7259 if (!$this->ColActive && !$this->keep_block_together && !$this->kwt) {
7260 if ($move_y && !$this->ColActive) { $this->y += $h; }
7261 return;
7262 }
7263
7264 if ($level == -3) { $level = $this->blklvl; }
7265 $firstblockfill = $this->GetFirstBlockFill();
7266 if ($firstblockfill && $this->blklvl > 0 && $this->blklvl >= $firstblockfill) {
7267 $last_x = 0;
7268 $last_w = 0;
7269 $last_fc = $this->FillColor;
7270 $bak_x = $this->x;
7271 $bak_h = $this->divheight;
7272 $this->divheight = 0; // Temporarily turn off divheight - as Cell() uses it to check for PageBreak
7273 for ($blvl=$firstblockfill;$blvl<=$level;$blvl++) {
7274 $this->SetBlockFill($blvl);
7275 $this->x = $this->lMargin + $this->blk[$blvl]['outer_left_margin'];
7276 if ($last_x != $this->lMargin + $this->blk[$blvl]['outer_left_margin'] || $last_w != $this->blk[$blvl]['width'] || $last_fc != $this->FillColor || $this->blk[$blvl]['border_top']['s'] || $this->blk[$blvl]['border_bottom']['s'] || $this->blk[$blvl]['border_left']['s'] || $this->blk[$blvl]['border_right']['s']) { // mPDF 5.6.55
7277 $x = $this->x;
7278 $this->Cell( ($this->blk[$blvl]['width']), $h, '', '', 0, '', 1);
7279 if (!$this->keep_block_together && !$this->writingHTMLheader && !$this->writingHTMLfooter) {
7280 $this->x = $x;
7281 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
7282 if ($blvl == $this->blklvl) { $this->PaintDivLnBorder($state,$blvl,$h); }
7283 else { $this->PaintDivLnBorder(0,$blvl,$h); }
7284 }
7285 }
7286 $last_x = $this->lMargin + $this->blk[$blvl]['outer_left_margin'];
7287 $last_w = $this->blk[$blvl]['width'];
7288 $last_fc = $this->FillColor;
7289 }
7290 // Reset current block fill
7291 if (isset($this->blk[$this->blklvl]['bgcolorarray'])) {
7292 $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
7293 $this->SetFColor($bcor);
7294 }
7295 $this->x = $bak_x;
7296 $this->divheight = $bak_h;
7297 }
7298 if ($move_y) { $this->y += $h; }
7299 }
7300 /*-- END HTML-CSS --*/
7301
7302
7303 function SetX($x)
7304 {
7305 //Set x position
7306 if($x >= 0) $this->x=$x;
7307 else $this->x = $this->w + $x;
7308 }
7309
7310 function SetY($y)
7311 {
7312 //Set y position and reset x
7313 $this->x=$this->lMargin;
7314 if($y>=0)
7315 $this->y=$y;
7316 else
7317 $this->y=$this->h+$y;
7318 }
7319
7320 function SetXY($x,$y)
7321 {
7322 //Set x and y positions
7323 $this->SetY($y);
7324 $this->SetX($x);
7325 }
7326
7327
7328 function Output($name='',$dest='')
7329 {
7330 //Output PDF to some destination
7331 if ($this->showStats) {
7332 echo '<div>Generated in '.sprintf('%.2F',(microtime(true) - $this->time0)).' seconds</div>';
7333 }
7334 //Finish document if necessary
7335 if ($this->progressBar) { $this->UpdateProgressBar(1,'100','Finished'); } // *PROGRESS-BAR*
7336 if($this->state < 3) $this->Close();
7337 if ($this->progressBar) { $this->UpdateProgressBar(2,'100','Finished'); } // *PROGRESS-BAR*
7338 // fn. error_get_last is only in PHP>=5.2
7339 if ($this->debug && function_exists('error_get_last') && error_get_last()) {
7340 $e = error_get_last();
7341 if (($e['type'] < 2048 && $e['type'] != 8) || (intval($e['type']) & intval(ini_get("error_reporting")))) {
7342 echo "<p>Error message detected - PDF file generation aborted.</p>";
7343 echo $e['message'].'<br />';
7344 echo 'File: '.$e['file'].'<br />';
7345 echo 'Line: '.$e['line'].'<br />';
7346 exit;
7347 }
7348 }
7349
7350
7351 if (($this->PDFA || $this->PDFX) && $this->encrypted) { $this->Error("PDFA1-b or PDFX/1-a does not permit encryption of documents."); }
7352 if (count($this->PDFAXwarnings) && (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto))) {
7353 if ($this->PDFA) {
7354 echo '<div>WARNING - This file could not be generated as it stands as a PDFA1-b compliant file.</div>';
7355 echo '<div>These issues can be automatically fixed by mPDF using <i>$mpdf-&gt;PDFAauto=true;</i></div>';
7356 echo '<div>Action that mPDF will take to automatically force PDFA1-b compliance are shown in brackets.</div>';
7357 }
7358 else {
7359 echo '<div>WARNING - This file could not be generated as it stands as a PDFX/1-a compliant file.</div>';
7360 echo '<div>These issues can be automatically fixed by mPDF using <i>$mpdf-&gt;PDFXauto=true;</i></div>';
7361 echo '<div>Action that mPDF will take to automatically force PDFX/1-a compliance are shown in brackets.</div>';
7362 }
7363 echo '<div>Warning(s) generated:</div><ul>';
7364 $this->PDFAXwarnings = array_unique($this->PDFAXwarnings);
7365 foreach($this->PDFAXwarnings AS $w) {
7366 echo '<li>'.$w.'</li>';
7367 }
7368 echo '</ul>';
7369 exit;
7370 }
7371
7372 if ($this->showStats) {
7373 echo '<div>Compiled in '.sprintf('%.2F',(microtime(true) - $this->time0)).' seconds (total)</div>';
7374 echo '<div>Peak Memory usage '.number_format((memory_get_peak_usage(true)/(1024*1024)),2).' MB</div>';
7375 echo '<div>PDF file size '.number_format((strlen($this->buffer)/1024)).' kB</div>';
7376 echo '<div>Number of fonts '.count($this->fonts).'</div>';
7377 exit;
7378 }
7379
7380
7381 if(is_bool($dest)) $dest=$dest ? 'D' : 'F';
7382 $dest=strtoupper($dest);
7383 if($dest=='') {
7384 if($name=='') {
7385 $name='mpdf.pdf';
7386 $dest='I';
7387 }
7388 else { $dest='F'; }
7389 }
7390
7391 /*-- PROGRESS-BAR --*/
7392 if ($this->progressBar && ($dest=='D' || $dest=='I')) {
7393 if($name=='') { $name='mpdf.pdf'; }
7394 $tempfile = '_tempPDF'.RAND(1,10000);
7395 //Save to local file
7396 $f=fopen(_MPDF_TEMP_PATH.$tempfile.'.pdf','wb');
7397 if(!$f) $this->Error('Unable to create temporary output file: '.$tempfile.'.pdf');
7398 fwrite($f,$this->buffer,strlen($this->buffer));
7399 fclose($f);
7400 $this->UpdateProgressBar(3,'','Finished');
7401
7402 echo '<script type="text/javascript">
7403
7404 var form = document.createElement("form");
7405 form.setAttribute("method", "post");
7406 form.setAttribute("action", "'._MPDF_URI.'includes/out.php");
7407
7408 var hiddenField = document.createElement("input");
7409 hiddenField.setAttribute("type", "hidden");
7410 hiddenField.setAttribute("name", "filename");
7411 hiddenField.setAttribute("value", "'.$tempfile.'");
7412 form.appendChild(hiddenField);
7413
7414 var hiddenField = document.createElement("input");
7415 hiddenField.setAttribute("type", "hidden");
7416 hiddenField.setAttribute("name", "dest");
7417 hiddenField.setAttribute("value", "'.$dest.'");
7418 form.appendChild(hiddenField);
7419
7420 var hiddenField = document.createElement("input");
7421 hiddenField.setAttribute("type", "hidden");
7422 hiddenField.setAttribute("name", "opname");
7423 hiddenField.setAttribute("value", "'.$name.'");
7424 form.appendChild(hiddenField);
7425
7426 var hiddenField = document.createElement("input");
7427 hiddenField.setAttribute("type", "hidden");
7428 hiddenField.setAttribute("name", "path");
7429 hiddenField.setAttribute("value", "'.urlencode(_MPDF_TEMP_PATH).'");
7430 form.appendChild(hiddenField);
7431
7432 document.body.appendChild(form);
7433 form.submit();
7434
7435 </script>
7436 </div>
7437 </body>
7438 </html>';
7439 exit;
7440 }
7441 else {
7442 if ($this->progressBar) { $this->UpdateProgressBar(3,'','Finished'); }
7443 /*-- END PROGRESS-BAR --*/
7444
7445 switch($dest) {
7446 case 'I':
7447 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; }
7448 //Send to standard output
7449 if(PHP_SAPI!='cli') {
7450 //We send to a browser
7451 header('Content-Type: application/pdf');
7452 if(headers_sent())
7453 $this->Error('Some data has already been output to browser, can\'t send PDF file');
7454 if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
7455 // don't use length if server using compression
7456 header('Content-Length: '.strlen($this->buffer));
7457 }
7458 header('Content-disposition: inline; filename="'.$name.'"');
7459 header('Cache-Control: public, must-revalidate, max-age=0');
7460 header('Pragma: public');
7461 header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
7462 header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
7463 }
7464 echo $this->buffer;
7465 break;
7466 case 'D':
7467 //Download file
7468 header('Content-Description: File Transfer');
7469 if (headers_sent())
7470 $this->Error('Some data has already been output to browser, can\'t send PDF file');
7471 header('Content-Transfer-Encoding: binary');
7472 header('Cache-Control: public, must-revalidate, max-age=0');
7473 header('Pragma: public');
7474 header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
7475 header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
7476 header('Content-Type: application/force-download');
7477 header('Content-Type: application/octet-stream', false);
7478 header('Content-Type: application/download', false);
7479 header('Content-Type: application/pdf', false);
7480 if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) {
7481 // don't use length if server using compression
7482 header('Content-Length: '.strlen($this->buffer));
7483 }
7484 header('Content-disposition: attachment; filename="'.$name.'"');
7485 echo $this->buffer;
7486 break;
7487 case 'F':
7488 //Save to local file
7489 $f=fopen($name,'wb');
7490 if(!$f) $this->Error('Unable to create output file: '.$name);
7491 fwrite($f,$this->buffer,strlen($this->buffer));
7492 fclose($f);
7493 break;
7494 case 'S':
7495 //Return as a string
7496 return $this->buffer;
7497 default:
7498 $this->Error('Incorrect output destination: '.$dest);
7499 }
7500
7501 } // *PROGRESS-BAR*
7502 //======================================================================================================
7503 // DELETE OLD TMP FILES - Housekeeping
7504 // Delete any files in tmp/ directory that are >1 hrs old
7505 $interval = 3600;
7506 if ($handle = opendir(preg_replace('/\/$/','',_MPDF_TEMP_PATH))) {
7507 while (false !== ($file = readdir($handle))) {
7508 if (!is_dir($file) && ((filemtime(_MPDF_TEMP_PATH.$file)+$interval) < time()) && ($file != "..") && ($file != ".") && (substr($file, 0, 1) !== '.') && ($file !='dummy.txt')) { // mPDF 5.7
7509 unlink(_MPDF_TEMP_PATH.$file);
7510 }
7511 }
7512 closedir($handle);
7513 }
7514 //==============================================================================================================
7515
7516 return '';
7517 }
7518
7519
7520 // *****************************************************************************
7521 // *
7522 // Protected methods *
7523 // *
7524 // *****************************************************************************
7525 function _dochecks()
7526 {
7527 //Check for locale-related bug
7528 if(1.1==1)
7529 $this->Error('Don\'t alter the locale before including mPDF');
7530 //Check for decimal separator
7531 if(sprintf('%.1f',1.0)!='1.0')
7532 setlocale(LC_NUMERIC,'C');
7533 // mPDF 5.4.11
7534 $mqr=ini_get("magic_quotes_runtime");
7535 if ($mqr) { $this->Error('mPDF requires magic_quotes_runtime to be turned off e.g. by using ini_set("magic_quotes_runtime", 0);'); }
7536 }
7537
7538 function _begindoc()
7539 {
7540 //Start document
7541 $this->state=1;
7542 $this->_out('%PDF-'.$this->pdf_version);
7543 $this->_out('%'.chr(226).chr(227).chr(207).chr(211)); // 4 chars > 128 to show binary file
7544 }
7545
7546
7547 /*-- HTMLHEADERS-FOOTERS --*/
7548 function _puthtmlheaders() {
7549 $this->state=2;
7550 $nb=$this->page;
7551 for($n=1;$n<=$nb;$n++) {
7552 if ($this->mirrorMargins && $n%2==0) { $OE = 'E'; } // EVEN
7553 else { $OE = 'O'; }
7554 $this->page = $n;
7555 if (isset($this->saveHTMLHeader[$n][$OE])) {
7556 $html = $this->saveHTMLHeader[$n][$OE]['html'];
7557 $this->lMargin = $this->saveHTMLHeader[$n][$OE]['ml'];
7558 $this->rMargin = $this->saveHTMLHeader[$n][$OE]['mr'];
7559 $this->tMargin = $this->saveHTMLHeader[$n][$OE]['mh'];
7560 $this->bMargin = $this->saveHTMLHeader[$n][$OE]['mf'];
7561 $this->margin_header = $this->saveHTMLHeader[$n][$OE]['mh'];
7562 $this->margin_footer = $this->saveHTMLHeader[$n][$OE]['mf'];
7563 $this->w = $this->saveHTMLHeader[$n][$OE]['pw'];
7564 $this->h = $this->saveHTMLHeader[$n][$OE]['ph'];
7565 $rotate = (isset($this->saveHTMLHeader[$n][$OE]['rotate']) ? $this->saveHTMLHeader[$n][$OE]['rotate'] : null);
7566 $this->Reset();
7567 $this->pageoutput[$n] = array();
7568 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
7569 $this->x = $this->lMargin;
7570 $this->y = $this->margin_header;
7571 // mPDF 5.6.47
7572 $pn = $this->docPageNum($n);
7573 if ($pn)
7574 $pnstr = $this->pagenumPrefix.$pn.$this->pagenumSuffix;
7575 else { $pnstr = ''; }
7576 $html = str_replace('{PAGENO}',$pnstr,$html);
7577 $pnt = $this->docPageNumTotal($n);
7578 if ($pnt)
7579 $pntstr = $this->nbpgPrefix.$pnt.$this->nbpgSuffix;
7580 else { $pntstr = ''; }
7581 $html = str_replace($this->aliasNbPgGp,$pntstr,$html ); // {nbpg}
7582 $html = str_replace($this->aliasNbPg,$nb,$html ); // {nb}
7583 $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', array($this, 'date_callback') ,$html ); // mPDF 5.7
7584
7585 $this->HTMLheaderPageLinks = array();
7586 $this->HTMLheaderPageAnnots = array();
7587 $this->HTMLheaderPageForms = array();
7588 $this->pageBackgrounds = array();
7589
7590 $this->writingHTMLheader = true;
7591 $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
7592 $this->writingHTMLheader = false;
7593 $this->Reset();
7594 $this->pageoutput[$n] = array();
7595
7596 $s = $this->PrintPageBackgrounds();
7597 $this->headerbuffer = $s . $this->headerbuffer;
7598 $os = '';
7599 if ($rotate) {
7600 $os .= sprintf('q 0 -1 1 0 0 %.3F cm ',($this->w*_MPDFK));
7601 }
7602 $os .= $this->headerbuffer ;
7603 if ($rotate) {
7604 $os .= ' Q' . "\n";
7605 }
7606
7607 // Writes over the page background but behind any other output on page
7608 $os = preg_replace('/\\\\/','\\\\\\\\',$os);
7609 $this->pages[$n] = preg_replace('/(___HEADER___MARKER'.date('jY').')/', "\n".$os."\n".'\\1', $this->pages[$n]);
7610
7611 $lks = $this->HTMLheaderPageLinks;
7612 foreach($lks AS $lk) {
7613 if ($rotate) {
7614 $lw = $lk[2];
7615 $lh = $lk[3];
7616 $lk[2] = $lh;
7617 $lk[3] = $lw; // swap width and height
7618 $ax = $lk[0]/_MPDFK;
7619 $ay = $lk[1]/_MPDFK;
7620 $bx = $ay-($lh/_MPDFK);
7621 $by = $this->w-$ax;
7622 $lk[0] = $bx*_MPDFK;
7623 $lk[1] = ($this->h-$by)*_MPDFK - $lw;
7624 }
7625 $this->PageLinks[$n][]=$lk;
7626 }
7627 /*-- FORMS --*/
7628 foreach($this->HTMLheaderPageForms AS $f) {
7629 $this->form->forms[$f['n']] = $f;
7630 }
7631 /*-- END FORMS --*/
7632
7633
7634 }
7635 if (isset($this->saveHTMLFooter[$n][$OE])) {
7636 $html = $this->saveHTMLFooter[$this->page][$OE]['html'];
7637 $this->lMargin = $this->saveHTMLFooter[$n][$OE]['ml'];
7638 $this->rMargin = $this->saveHTMLFooter[$n][$OE]['mr'];
7639 $this->tMargin = $this->saveHTMLFooter[$n][$OE]['mh'];
7640 $this->bMargin = $this->saveHTMLFooter[$n][$OE]['mf'];
7641 $this->margin_header = $this->saveHTMLFooter[$n][$OE]['mh'];
7642 $this->margin_footer = $this->saveHTMLFooter[$n][$OE]['mf'];
7643 $this->w = $this->saveHTMLFooter[$n][$OE]['pw'];
7644 $this->h = $this->saveHTMLFooter[$n][$OE]['ph'];
7645 $rotate = (isset($this->saveHTMLFooter[$n][$OE]['rotate']) ? $this->saveHTMLFooter[$n][$OE]['rotate'] : null);
7646 $this->Reset();
7647 $this->pageoutput[$n] = array();
7648 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
7649 $this->x = $this->lMargin;
7650 $top_y = $this->y = $this->h - $this->margin_footer;
7651
7652 // if bottom-margin==0, corrects to avoid division by zero
7653 if ($this->y == $this->h) { $top_y = $this->y = ($this->h - 0.1); }
7654 // mPDF 5.6.47
7655 $pn = $this->docPageNum($n);
7656 if ($pn)
7657 $pnstr = $this->pagenumPrefix.$pn.$this->pagenumSuffix;
7658 else { $pnstr = ''; }
7659 $html = str_replace('{PAGENO}',$pnstr,$html);
7660 $pnt = $this->docPageNumTotal($n);
7661 if ($pnt)
7662 $pntstr = $this->nbpgPrefix.$pnt.$this->nbpgSuffix;
7663 else { $pntstr = ''; }
7664 $html = str_replace($this->aliasNbPgGp,$pntstr,$html ); // {nbpg}
7665 $html = str_replace($this->aliasNbPg,$nb,$html ); // {nb}
7666 $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', array($this, 'date_callback') ,$html ); // mPDF 5.7
7667
7668
7669 $this->HTMLheaderPageLinks = array();
7670 $this->HTMLheaderPageAnnots = array();
7671 $this->HTMLheaderPageForms = array();
7672 $this->pageBackgrounds = array();
7673
7674 $this->writingHTMLfooter = true;
7675 $this->InFooter = true;
7676 $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
7677 $this->writingHTMLfooter = false;
7678 $this->InFooter = false;
7679 $this->Reset();
7680 $this->pageoutput[$n] = array();
7681
7682 $fheight = $this->y - $top_y;
7683 $adj = -$fheight;
7684
7685 $s = $this->PrintPageBackgrounds(-$adj);
7686 $this->headerbuffer = $s . $this->headerbuffer;
7687
7688 $os = '';
7689 $os .= $this->StartTransform(true)."\n";
7690 if ($rotate) {
7691 $os .= sprintf('q 0 -1 1 0 0 %.3F cm ',($this->w*_MPDFK));
7692 }
7693 $os .= $this->transformTranslate(0, $adj, true)."\n";
7694 $os .= $this->headerbuffer ;
7695 if ($rotate) {
7696 $os .= ' Q' . "\n";
7697 }
7698 $os .= $this->StopTransform(true)."\n";
7699 // Writes over the page background but behind any other output on page
7700 $os = preg_replace('/\\\\/','\\\\\\\\',$os);
7701 $this->pages[$n] = preg_replace('/(___HEADER___MARKER'.date('jY').')/', "\n".$os."\n".'\\1', $this->pages[$n]);
7702
7703 $lks = $this->HTMLheaderPageLinks;
7704 foreach($lks AS $lk) {
7705 $lk[1] -= $adj*_MPDFK;
7706 if ($rotate) {
7707 $lw = $lk[2];
7708 $lh = $lk[3];
7709 $lk[2] = $lh;
7710 $lk[3] = $lw; // swap width and height
7711
7712 $ax = $lk[0]/_MPDFK;
7713 $ay = $lk[1]/_MPDFK;
7714 $bx = $ay-($lh/_MPDFK);
7715 $by = $this->w-$ax;
7716 $lk[0] = $bx*_MPDFK;
7717 $lk[1] = ($this->h-$by)*_MPDFK - $lw;
7718 }
7719 $this->PageLinks[$n][]=$lk;
7720 }
7721 /*-- FORMS --*/
7722 foreach($this->HTMLheaderPageForms AS $f) {
7723 $f['y'] += $adj;
7724 $this->form->forms[$f['n']] = $f;
7725 }
7726 /*-- END FORMS --*/
7727 }
7728 }
7729 $this->page=$nb;
7730 $this->state=1;
7731 }
7732 /*-- END HTMLHEADERS-FOOTERS --*/
7733
7734
7735 function _putpages()
7736 {
7737 $nb=$this->page;
7738 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
7739
7740 if($this->DefOrientation=='P') {
7741 $defwPt=$this->fwPt;
7742 $defhPt=$this->fhPt;
7743 }
7744 else {
7745 $defwPt=$this->fhPt;
7746 $defhPt=$this->fwPt;
7747 }
7748 $annotid=(3+2*$nb);
7749
7750 // Active Forms
7751 $totaladdnum = 0;
7752 for($n=1;$n<=$nb;$n++) {
7753 if (isset($this->PageLinks[$n])) { $totaladdnum += count($this->PageLinks[$n]); }
7754 /*-- ANNOTATIONS --*/
7755 if (isset($this->PageAnnots[$n])) {
7756 foreach ($this->PageAnnots[$n] as $k => $pl) {
7757 if (!empty($pl['opt']['popup']) || !empty($pl['opt']['file'])) { $totaladdnum += 2 ; }
7758 else { $totaladdnum++; }
7759 }
7760 }
7761 /*-- END ANNOTATIONS --*/
7762
7763 /*-- FORMS --*/
7764 if ( count($this->form->forms) > 0 ) {
7765 $this->form->countPageForms($n, $totaladdnum);
7766 }
7767 /*-- END FORMS --*/
7768 }
7769 /*-- FORMS --*/
7770 // Make a note in the radio button group of the obj_id it will have
7771 $ctr = 0;
7772 if (count($this->form->form_radio_groups)) {
7773 foreach($this->form->form_radio_groups AS $name=>$frg) {
7774 $this->form->form_radio_groups[$name]['obj_id'] = $annotid + $totaladdnum + $ctr;
7775 $ctr++;
7776 }
7777 }
7778 /*-- END FORMS --*/
7779
7780 // Select unused fonts (usually default font)
7781 $unused = array();
7782 foreach($this->fonts as $fk=>$font) {
7783 if (!$font['used'] && ($font['type']=='TTF')) {
7784 $unused[] = $fk;
7785 }
7786 }
7787
7788
7789 for($n=1;$n<=$nb;$n++)
7790 {
7791 $thispage = $this->pages[$n];
7792 // unset($this->pages[$n]); // mPDF 5.6.47
7793 if(isset($this->OrientationChanges[$n])) {
7794 $hPt=$this->pageDim[$n]['w']*_MPDFK;
7795 $wPt=$this->pageDim[$n]['h']*_MPDFK;
7796 $owidthPt_LR = $this->pageDim[$n]['outer_width_TB']*_MPDFK;
7797 $owidthPt_TB = $this->pageDim[$n]['outer_width_LR']*_MPDFK;
7798 }
7799 else {
7800 $wPt=$this->pageDim[$n]['w']*_MPDFK;
7801 $hPt=$this->pageDim[$n]['h']*_MPDFK;
7802 $owidthPt_LR = $this->pageDim[$n]['outer_width_LR']*_MPDFK;
7803 $owidthPt_TB = $this->pageDim[$n]['outer_width_TB']*_MPDFK;
7804 }
7805 // Remove references to unused fonts (usually default font)
7806 foreach($unused as $fk) {
7807 if ($this->fonts[$fk]['sip'] || $this->fonts[$fk]['smp']) {
7808 foreach($this->fonts[$fk]['subsetfontids'] AS $k => $fid) {
7809 $thispage = preg_replace('/\s\/F'.$fid.' \d[\d.]* Tf\s/is',' ',$thispage);
7810 }
7811 }
7812 else {
7813 $thispage = preg_replace('/\s\/F'.$this->fonts[$fk]['i'].' \d[\d.]* Tf\s/is',' ',$thispage);
7814 }
7815 }
7816 //Replace number of pages
7817 if(!empty($this->aliasNbPg)) {
7818 if (!$this->onlyCoreFonts) { $s1 = $this->UTF8ToUTF16BE($this->aliasNbPg, false); }
7819 $s2 = $this->aliasNbPg;
7820 if (!$this->onlyCoreFonts) { $r1 = $this->UTF8ToUTF16BE($nb, false); }
7821 $r2 = $nb;
7822 if (preg_match_all('/{mpdfheadernbpg (C|R) ff=(\S*) fs=(\S*) fz=(.*?)}/',$thispage,$m)) {
7823 for($hi=0;$hi<count($m[0]);$hi++) {
7824 $pos = $m[1][$hi];
7825 $hff = $m[2][$hi];
7826 $hfst = $m[3][$hi];
7827 $hfsz = $m[4][$hi];
7828 $this->SetFont($hff,$hfst,$hfsz, false);
7829 $x1 = $this->GetStringWidth($this->aliasNbPg);
7830 $x2 = $this->GetStringWidth($nb);
7831 $xadj = $x1 - $x2;
7832 if ($pos=='C') { $xadj /= 2; }
7833 $rep = sprintf(' q 1 0 0 1 %.3F 0 cm ', $xadj*_MPDFK);
7834 $thispage = str_replace($m[0][$hi], $rep, $thispage);
7835 }
7836 }
7837 if (!$this->onlyCoreFonts) { $thispage=str_replace($s1,$r1,$thispage); }
7838 $thispage=str_replace($s2,$r2,$thispage);
7839
7840 // And now for any SMP/SIP fonts subset using <HH> format
7841 $r = '';
7842 $nstr = "$nb";
7843 for($i=0;$i<strlen($nstr);$i++) {
7844 $r .= sprintf("%02s", strtoupper(dechex(intval($nstr[$i])+48)));
7845 }
7846 $thispage=str_replace($this->aliasNbPgHex,$r,$thispage);
7847
7848 }
7849 //Replace number of pages in group
7850 if(!empty($this->aliasNbPgGp)) {
7851 if (!$this->onlyCoreFonts) { $s1 = $this->UTF8ToUTF16BE($this->aliasNbPgGp, false); }
7852 $s2 = $this->aliasNbPgGp;
7853 $nbt = $this->docPageNumTotal($n);
7854 if (!$this->onlyCoreFonts) { $r1 = $this->UTF8ToUTF16BE($nbt, false); }
7855 $r2 = $nbt;
7856 if (preg_match_all('/{mpdfheadernbpggp (C|R) ff=(\S*) fs=(\S*) fz=(.*?)}/',$thispage,$m)) {
7857 for($hi=0;$hi<count($m[0]);$hi++) {
7858 $pos = $m[1][$hi];
7859 $hff = $m[2][$hi];
7860 $hfst = $m[3][$hi];
7861 $hfsz = $m[4][$hi];
7862 $this->SetFont($hff,$hfst,$hfsz, false);
7863 $x1 = $this->GetStringWidth($this->aliasNbPgGp);
7864 $x2 = $this->GetStringWidth($nbt);
7865 $xadj = $x1 - $x2;
7866 if ($pos=='C') { $xadj /= 2; }
7867 $rep = sprintf(' q 1 0 0 1 %.3F 0 cm ', $xadj*_MPDFK);
7868 $thispage = str_replace($m[0][$hi], $rep, $thispage);
7869 }
7870 }
7871 if (!$this->onlyCoreFonts) { $thispage=str_replace($s1,$r1,$thispage); }
7872 $thispage=str_replace($s2,$r2,$thispage);
7873
7874 // And now for any SMP/SIP fonts subset using <HH> format
7875 $r = '';
7876 $nstr = "$nbt";
7877 for($i=0;$i<strlen($nstr);$i++) {
7878 $r .= sprintf("%02s", strtoupper(dechex(intval($nstr[$i])+48)));
7879 }
7880 $thispage=str_replace($this->aliasNbPgGpHex,$r,$thispage);
7881
7882 }
7883 $thispage = preg_replace('/(\s*___BACKGROUND___PATTERNS'.date('jY').'\s*)/', " ", $thispage);
7884 $thispage = preg_replace('/(\s*___HEADER___MARKER'.date('jY').'\s*)/', " ", $thispage);
7885 $thispage = preg_replace('/(\s*___PAGE___START'.date('jY').'\s*)/', " ", $thispage);
7886 $thispage = preg_replace('/(\s*___TABLE___BACKGROUNDS'.date('jY').'\s*)/', " ", $thispage);
7887
7888 //Page
7889 $this->_newobj();
7890 $this->_out('<</Type /Page');
7891 $this->_out('/Parent 1 0 R');
7892 if(isset($this->OrientationChanges[$n])) {
7893 $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$hPt,$wPt));
7894 //If BleedBox is defined, it must be larger than the TrimBox, but smaller than the MediaBox
7895 $bleedMargin = $this->pageDim[$n]['bleedMargin']*_MPDFK;
7896 if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) {
7897 $x0 = $owidthPt_TB-$bleedMargin;
7898 $y0 = $owidthPt_LR-$bleedMargin;
7899 $x1 = $hPt-$owidthPt_TB+$bleedMargin;
7900 $y1 = $wPt-$owidthPt_LR+$bleedMargin;
7901 $this->_out(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1));
7902 }
7903 $this->_out(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_TB, $owidthPt_LR, ($hPt-$owidthPt_TB), ($wPt-$owidthPt_LR)));
7904 if (isset($this->OrientationChanges[$n]) && $this->displayDefaultOrientation) {
7905 if ($this->DefOrientation=='P') { $this->_out('/Rotate 270'); }
7906 else { $this->_out('/Rotate 90'); }
7907 }
7908 }
7909 //else if($wPt != $defwPt || $hPt != $defhPt) {
7910 else {
7911 $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$wPt,$hPt));
7912 $bleedMargin = $this->pageDim[$n]['bleedMargin']*_MPDFK;
7913 if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) {
7914 $x0 = $owidthPt_LR-$bleedMargin;
7915 $y0 = $owidthPt_TB-$bleedMargin;
7916 $x1 = $wPt-$owidthPt_LR+$bleedMargin;
7917 $y1 = $hPt-$owidthPt_TB+$bleedMargin;
7918 $this->_out(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1));
7919 }
7920 $this->_out(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_LR, $owidthPt_TB, ($wPt-$owidthPt_LR), ($hPt-$owidthPt_TB)));
7921 }
7922 $this->_out('/Resources 2 0 R');
7923
7924 // Important to keep in RGB colorSpace when using transparency
7925 if (!$this->PDFA && !$this->PDFX) {
7926 if ($this->restrictColorSpace == 3)
7927 $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceCMYK >> ');
7928 else if ($this->restrictColorSpace == 1)
7929 $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceGray >> ');
7930 else
7931 $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceRGB >> ');
7932 }
7933
7934 $annotsnum = 0;
7935 if (isset($this->PageLinks[$n])) { $annotsnum += count($this->PageLinks[$n]); }
7936 /*-- ANNOTATIONS --*/
7937 if (isset($this->PageAnnots[$n])) {
7938 foreach ($this->PageAnnots[$n] as $k => $pl) {
7939 if (!empty($pl['opt']['popup']) || !empty($pl['opt']['file'])) { $annotsnum += 2 ; }
7940 else { $annotsnum++; }
7941 $this->PageAnnots[$n][$k]['pageobj'] = $this->n;
7942 }
7943 }
7944 /*-- END ANNOTATIONS --*/
7945
7946 /*-- FORMS --*/
7947 // Active Forms
7948 $formsnum = 0;
7949 if ( count($this->form->forms) > 0 ) {
7950 foreach( $this->form->forms as $val ) {
7951 if ( $val['page'] == $n )
7952 $formsnum++;
7953 }
7954 }
7955 /*-- END FORMS --*/
7956 if ($annotsnum || $formsnum) {
7957 $s = '/Annots [ ';
7958 for($i=0;$i<$annotsnum;$i++) {
7959 $s .= ($annotid + $i) . ' 0 R ';
7960 }
7961 $annotid += $annotsnum;
7962 /*-- FORMS --*/
7963 if ( count($this->form->forms) > 0 ) {
7964 $this->form->addFormIds($n, $s, $annotid);
7965 }
7966 /*-- END FORMS --*/
7967 $s .= '] ';
7968 $this->_out($s);
7969 }
7970
7971 $this->_out('/Contents '.($this->n+1).' 0 R>>');
7972 $this->_out('endobj');
7973
7974 //Page content
7975 $this->_newobj();
7976 $p=($this->compress) ? gzcompress($thispage) : $thispage;
7977 $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
7978 $this->_putstream($p);
7979 $this->_out('endobj');
7980 }
7981 $this->_putannots($n);
7982
7983 //Pages root
7984 $this->offsets[1]=strlen($this->buffer);
7985 $this->_out('1 0 obj');
7986 $this->_out('<</Type /Pages');
7987 $kids='/Kids [';
7988 for($i=0;$i<$nb;$i++)
7989 $kids.=(3+2*$i).' 0 R ';
7990 $this->_out($kids.']');
7991 $this->_out('/Count '.$nb);
7992 $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]',$defwPt,$defhPt));
7993 $this->_out('>>');
7994 $this->_out('endobj');
7995 }
7996
7997
7998 function _putannots($n) {
7999 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
8000 $nb=$this->page;
8001 for($n=1;$n<=$nb;$n++)
8002 {
8003 $annotobjs = array();
8004 if(isset($this->PageLinks[$n]) || isset($this->PageAnnots[$n]) || count($this->form->forms) > 0 ) {
8005 $wPt=$this->pageDim[$n]['w']*_MPDFK;
8006 $hPt=$this->pageDim[$n]['h']*_MPDFK;
8007
8008 //Links
8009 if(isset($this->PageLinks[$n])) {
8010 foreach($this->PageLinks[$n] as $key => $pl) {
8011 $this->_newobj();
8012 $annot='';
8013 $rect=sprintf('%.3F %.3F %.3F %.3F',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
8014 $annot .= '<</Type /Annot /Subtype /Link /Rect ['.$rect.']';
8015 $annot .= ' /Contents '.$this->_UTF16BEtextstring($pl[4]);
8016 $annot .= ' /NM '.$this->_textstring(sprintf('%04u-%04u', $n, $key));
8017 $annot .= ' /M '.$this->_textstring('D:'.date('YmdHis'));
8018 $annot .= ' /Border [0 0 0]';
8019 // Use this (instead of /Border) to specify border around link
8020 // $annot .= ' /BS <</W 1'; // Width on points; 0 = no line
8021 // $annot .= ' /S /D'; // style - [S]olid, [D]ashed, [B]eveled, [I]nset, [U]nderline
8022 // $annot .= ' /D [3 2]'; // Dash array - if dashed
8023 // $annot .= ' >>';
8024 // $annot .= ' /C [1 0 0]'; // Color RGB
8025
8026 if ($this->PDFA || $this->PDFX) { $annot .= ' /F 28'; }
8027 if (strpos($pl[4],'@')===0) {
8028 $p=substr($pl[4],1);
8029 // $h=isset($this->OrientationChanges[$p]) ? $wPt : $hPt;
8030 $htarg=$this->pageDim[$p]['h']*_MPDFK;
8031 $annot.=sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>',1+2*$p,$htarg);
8032 }
8033 else if(is_string($pl[4])) {
8034 $annot .= ' /A <</S /URI /URI '.$this->_textstring($pl[4]).'>> >>';
8035 }
8036 else {
8037 $l=$this->links[$pl[4]];
8038 // may not be set if #link points to non-existent target
8039 if (isset($this->pageDim[$l[0]]['h'])) { $htarg=$this->pageDim[$l[0]]['h']*_MPDFK; }
8040 else { $htarg=$this->h*_MPDFK; } // doesn't really matter
8041 $annot.=sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>',1+2*$l[0],$htarg-$l[1]*_MPDFK);
8042 }
8043 $this->_out($annot);
8044 $this->_out('endobj');
8045 }
8046 }
8047
8048
8049 /*-- ANNOTATIONS --*/
8050 if(isset($this->PageAnnots[$n])) {
8051 foreach ($this->PageAnnots[$n] as $key => $pl) {
8052 if ($pl['opt']['file']) { $FileAttachment=true; }
8053 else { $FileAttachment=false; }
8054 $this->_newobj();
8055 $annot='';
8056 $pl['opt'] = array_change_key_case($pl['opt'], CASE_LOWER);
8057 $x = $pl['x'];
8058 if ($this->annotMargin <> 0 || $x==0 || $x<0) { // Odd page
8059 $x = ($wPt/_MPDFK) - $this->annotMargin;
8060 }
8061 $w = $h = 0;
8062 $a = $x * _MPDFK;
8063 $b = $hPt - ($pl['y'] * _MPDFK);
8064 $annot .= '<</Type /Annot ';
8065 if ($FileAttachment) {
8066 $annot .= '/Subtype /FileAttachment';
8067 // Need to set a size for FileAttachment icons
8068 if ($pl['opt']['icon']=='Paperclip') { $w=8.235; $h=20; } // 7,17
8069 else if ($pl['opt']['icon']=='Tag') { $w=20; $h=16; }
8070 else if ($pl['opt']['icon']=='Graph') { $w=20; $h=20; }
8071 else { $w=14; $h=20; } // PushPin
8072 $f = $pl['opt']['file'];
8073 $f = preg_replace('/^.*\//', '', $f);
8074 $f = preg_replace('/[^a-zA-Z0-9._]/', '', $f);
8075 $annot .= '/FS <</Type /Filespec /F ('.$f.')';
8076 $annot .= '/EF <</F '.($this->n+1).' 0 R>>';
8077 $annot .= '>>';
8078 }
8079 else {
8080 $annot .= '/Subtype /Text';
8081 }
8082 $rect = sprintf('%.3F %.3F %.3F %.3F', $a, $b-$h, $a+$w, $b);
8083 $annot .= '/Rect ['.$rect.']';
8084
8085 // contents = description of file in free text
8086 $annot .= ' /Contents '.$this->_UTF16BEtextstring($pl['txt']);
8087 $annot .= ' /NM '.$this->_textstring(sprintf('%04u-%04u', $n, (2000 + $key)));
8088 $annot .= ' /M '.$this->_textstring('D:'.date('YmdHis'));
8089 $annot .= ' /CreationDate '.$this->_textstring('D:'.date('YmdHis'));
8090 $annot .= ' /Border [0 0 0]';
8091 if ($this->PDFA || $this->PDFX) {
8092 $annot .= ' /F 28';
8093 $annot .= ' /CA 1';
8094 }
8095 else if ($pl['opt']['ca']>0) { $annot .= ' /CA '.$pl['opt']['ca']; }
8096
8097 $annotcolor = ' /C [';
8098 if (isset($pl['opt']['c']) AND $pl['opt']['c']) {
8099 $col = $pl['opt']['c'];
8100 if ($col{0}==3 || $col{0}==5) { $annotcolor .= sprintf("%.3F %.3F %.3F", ord($col{1})/255,ord($col{2})/255,ord($col{3})/255); }
8101 else if ($col{0}==1) { $annotcolor .= sprintf("%.3F", ord($col{1})/255); }
8102 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); }
8103 else { $annotcolor .= '1 1 0'; }
8104 }
8105 else { $annotcolor .= '1 1 0'; }
8106 $annotcolor .= ']';
8107 $annot .= $annotcolor;
8108 // Usually Author
8109 // Use as Title for fileattachment
8110 if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) {
8111 $annot .= ' /T '.$this->_UTF16BEtextstring($pl['opt']['t']);
8112 }
8113 if ($FileAttachment) {
8114 $iconsapp = array('Paperclip', 'Graph', 'PushPin', 'Tag');
8115 }
8116 else { $iconsapp = array('Comment', 'Help', 'Insert', 'Key', 'NewParagraph', 'Note', 'Paragraph'); }
8117 if (isset($pl['opt']['icon']) AND in_array($pl['opt']['icon'], $iconsapp)) {
8118 $annot .= ' /Name /'.$pl['opt']['icon'];
8119 }
8120 else if ($FileAttachment) { $annot .= ' /Name /PushPin'; }
8121 else { $annot .= ' /Name /Note'; }
8122 if (!$FileAttachment) {
8123 // /Subj is PDF 1.5 spec.
8124 if (isset($pl['opt']['subj']) && !$this->PDFA && !$this->PDFX) {
8125 $annot .= ' /Subj '.$this->_UTF16BEtextstring($pl['opt']['subj']);
8126 }
8127 if (!empty($pl['opt']['popup'])) {
8128 $annot .= ' /Open true';
8129 $annot .= ' /Popup '.($this->n+1).' 0 R';
8130 }
8131 else { $annot .= ' /Open false'; }
8132 }
8133 $annot .= ' /P '.$pl['pageobj'].' 0 R';
8134 $annot .= '>>';
8135 $this->_out($annot);
8136 $this->_out('endobj');
8137
8138 if ($FileAttachment) {
8139 $file = @file_get_contents($pl['opt']['file']) or die('mPDF Error: Cannot access file attachment - '.$pl['opt']['file']);
8140 $filestream = gzcompress($file);
8141 $this->_newobj();
8142 $this->_out('<</Type /EmbeddedFile');
8143 $this->_out('/Length '.strlen($filestream));
8144 $this->_out('/Filter /FlateDecode');
8145 $this->_out('>>');
8146 $this->_putstream($filestream);
8147 $this->_out('endobj');
8148 }
8149 else if (!empty($pl['opt']['popup'])) {
8150 $this->_newobj();
8151 $annot='';
8152 if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][0])) { $x = $pl['opt']['popup'][0] * _MPDFK; }
8153 else { $x = $pl['x'] * _MPDFK; }
8154 if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][1])) { $y = $hPt - ($pl['opt']['popup'][1] * _MPDFK); }
8155 else { $y = $hPt - ($pl['y'] * _MPDFK); }
8156 if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][2])) { $w = $pl['opt']['popup'][2] * _MPDFK; }
8157 else { $w = 180; }
8158 if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][3])) { $h = $pl['opt']['popup'][3] * _MPDFK; }
8159 else { $h = 120; }
8160 $rect = sprintf('%.3F %.3F %.3F %.3F', $x, $y-$h, $x+$w, $y);
8161 $annot .= '<</Type /Annot /Subtype /Popup /Rect ['.$rect.']';
8162 $annot .= ' /M '.$this->_textstring('D:'.date('YmdHis'));
8163 if ($this->PDFA || $this->PDFX) { $annot .= ' /F 28'; }
8164 $annot .= ' /Parent '.($this->n-1).' 0 R';
8165 $annot .= '>>';
8166 $this->_out($annot);
8167 $this->_out('endobj');
8168 }
8169 }
8170 }
8171 /*-- END ANNOTATIONS --*/
8172
8173 /*-- FORMS --*/
8174 // Active Forms
8175 if ( count($this->form->forms) > 0 ) {
8176 $this->form->_putFormItems($n, $hPt);
8177 }
8178 /*-- END FORMS --*/
8179 }
8180 }
8181 /*-- FORMS --*/
8182 // Active Forms - Radio Button Group entries
8183 // Output Radio Button Group form entries (radio_on_obj_id already determined)
8184 if (count($this->form->form_radio_groups)) {
8185 $this->form->_putRadioItems($n);
8186 }
8187 /*-- END FORMS --*/
8188 }
8189
8190
8191 /*-- ANNOTATIONS --*/
8192 function Annotation($text, $x=0, $y=0, $icon='Note', $author='', $subject='', $opacity=0, $colarray=false, $popup='', $file='') {
8193 if (is_array($colarray) && count($colarray)==3) { $colarray = $this->ConvertColor('rgb('.$colarray[0].','.$colarray[1].','.$colarray[2].')'); }
8194 if ($colarray === false) { $colarray = $this->ConvertColor('yellow'); }
8195 if ($x==0) { $x = $this->x; }
8196 if ($y==0) { $y = $this->y; }
8197 $page = $this->page;
8198 if ($page < 1) { // Document has not been started - assume it's for first page
8199 $page = 1;
8200 if ($x==0) { $x = $this->lMargin; }
8201 if ($y==0) { $y = $this->tMargin; }
8202 }
8203
8204 if ($this->PDFA || $this->PDFX) {
8205 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)"; }
8206 $x = ($this->w) - $this->rMargin*0.66;
8207 }
8208 if (!$this->annotMargin) { $y -= $this->FontSize / 2; }
8209
8210 if (!$opacity && $this->annotMargin) { $opacity = 1; }
8211 else if (!$opacity) { $opacity = $this->annotOpacity; }
8212
8213 $an = array('txt' => $text, 'x' => $x, 'y' => $y, 'opt' => array('Icon'=>$icon, 'T'=>$author, 'Subj'=>$subject, 'C'=>$colarray, 'CA'=>$opacity, 'popup'=>$popup, 'file'=>$file));
8214
8215 if ($this->keep_block_together) { // Save to array - don't write yet
8216 $this->ktAnnots[$this->page][]= $an;
8217 return;
8218 }
8219 else if ($this->table_rotate) {
8220 $this->tbrot_Annots[$this->page][]= $an;
8221 return;
8222 }
8223 else if ($this->kwt) {
8224 $this->kwt_Annots[$this->page][]= $an;
8225 return;
8226 }
8227 // mPDF 5.0
8228 if ($this->writingHTMLheader || $this->writingHTMLfooter) {
8229 $this->HTMLheaderPageAnnots[]= $an;
8230 return;
8231 }
8232 //Put an Annotation on the page
8233 $this->PageAnnots[$page][] = $an;
8234 /*-- COLUMNS --*/
8235 // Save cross-reference to Column buffer
8236 $ref = count($this->PageAnnots[$this->page])-1;
8237 $this->columnAnnots[$this->CurrCol][INTVAL($this->x)][INTVAL($this->y)] = $ref;
8238 /*-- END COLUMNS --*/
8239 }
8240 /*-- END ANNOTATIONS --*/
8241
8242
8243 function _putfonts() {
8244 $nf=$this->n;
8245 foreach($this->FontFiles as $fontkey=>$info) {
8246 // TrueType embedded
8247 if (isset($info['type']) && $info['type']=='TTF' && !$info['sip'] && !$info['smp']) {
8248 $used = true;
8249 $asSubset = false;
8250 foreach($this->fonts AS $k=>$f) {
8251 if ($f['fontkey'] == $fontkey && $f['type']=='TTF') {
8252 $used = $f['used'];
8253 if ($used) {
8254 $nChars = (ord($f['cw'][0]) << 8) + ord($f['cw'][1]);
8255 $usage = intval(count($f['subset'])*100 / $nChars);
8256 $fsize = $info['length1'];
8257 // Always subset the very large TTF files
8258 if ($fsize > ($this->maxTTFFilesize *1024)) { $asSubset = true; }
8259 else if ($usage < $this->percentSubset) { $asSubset = true; }
8260 }
8261 if ($f['unAGlyphs']) $aaSubset = true; // mPDF 5.4.05
8262 if ($this->PDFA || $this->PDFX) $asSubset = false;
8263 $this->fonts[$k]['asSubset'] = $asSubset;
8264 break;
8265 }
8266 }
8267 if ($used && !$asSubset) {
8268 //Font file embedding
8269 $this->_newobj();
8270 $this->FontFiles[$fontkey]['n']=$this->n;
8271 $font='';
8272 $originalsize = $info['length1'];
8273 if ($this->repackageTTF || $this->fonts[$fontkey]['TTCfontID']>0) {
8274 // First see if there is a cached compressed file
8275 if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z')) {
8276 $f=fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z','rb');
8277 if(!$f) { $this->Error('Font file .ps.z not found'); }
8278 while(!feof($f)) { $font .= fread($f, 2048); }
8279 fclose($f);
8280 include(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.php'); // sets $originalsize (of repackaged font)
8281 }
8282 else {
8283 if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
8284 $ttf = new TTFontFile();
8285 $font = $ttf->repackageTTF($this->FontFiles[$fontkey]['ttffile'], $this->fonts[$fontkey]['TTCfontID'], $this->debugfonts, $this->fonts[$fontkey]['unAGlyphs']); // mPDF 5.4.05
8286
8287 $originalsize = strlen($font);
8288 $font = gzcompress($font);
8289 unset($ttf);
8290 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
8291 $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.z',"wb");
8292 fwrite($fh,$font,strlen($font));
8293 fclose($fh);
8294 $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.ps.php',"wb");
8295 $len = "<?php \n";
8296 $len.='$originalsize='.$originalsize.";\n";
8297 $len.="?>";
8298 fwrite($fh,$len,strlen($len));
8299 fclose($fh);
8300 }
8301 }
8302 }
8303 else {
8304 // First see if there is a cached compressed file
8305 if (file_exists(_MPDF_TTFONTDATAPATH.$fontkey.'.z')) {
8306 $f=fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.z','rb');
8307 if(!$f) { $this->Error('Font file not found'); }
8308 while(!feof($f)) { $font .= fread($f, 2048); }
8309 fclose($f);
8310 }
8311 else {
8312 $f=fopen($this->FontFiles[$fontkey]['ttffile'],'rb');
8313 if(!$f) { $this->Error('Font file not found'); }
8314 while(!feof($f)) { $font .= fread($f, 2048); }
8315 fclose($f);
8316 $font = gzcompress($font);
8317 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
8318 $fh = fopen(_MPDF_TTFONTDATAPATH.$fontkey.'.z',"wb");
8319 fwrite($fh,$font,strlen($font));
8320 fclose($fh);
8321 }
8322 }
8323 }
8324
8325 $this->_out('<</Length '.strlen($font));
8326 $this->_out('/Filter /FlateDecode');
8327 $this->_out('/Length1 '.$originalsize);
8328 $this->_out('>>');
8329 $this->_putstream($font);
8330 $this->_out('endobj');
8331 }
8332 }
8333 }
8334
8335 $nfonts = count($this->fonts);
8336 $fctr = 1;
8337 foreach($this->fonts as $k=>$font) {
8338 //Font objects
8339 $type=$font['type'];
8340 $name=$font['name'];
8341 if ((!isset($font['used']) || !$font['used']) && $type=='TTF') { continue; }
8342 if ($this->progressBar) { $this->UpdateProgressBar(2,intval($fctr*100/$nfonts),'Writing Fonts'); $fctr++; } // *PROGRESS-BAR*
8343 if (isset($font['asSubset'])) { $asSubset = $font['asSubset']; }
8344 else { $asSubset = ''; }
8345 /*-- CJK-FONTS --*/
8346 if($type=='Type0') { // = Adobe CJK Fonts
8347 $this->fonts[$k]['n']=$this->n+1;
8348 $this->_newobj();
8349 $this->_out('<</Type /Font');
8350 $this->_putType0($font);
8351 }
8352 else
8353 /*-- END CJK-FONTS --*/
8354 if($type=='core') {
8355 //Standard font
8356 $this->fonts[$k]['n']=$this->n+1;
8357 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.)'); }
8358 $this->_newobj();
8359 $this->_out('<</Type /Font');
8360 $this->_out('/BaseFont /'.$name);
8361 $this->_out('/Subtype /Type1');
8362 if($name!='Symbol' && $name!='ZapfDingbats') {
8363 $this->_out('/Encoding /WinAnsiEncoding');
8364 }
8365 $this->_out('>>');
8366 $this->_out('endobj');
8367 }
8368 // TrueType embedded SUBSETS for SIP (CJK extB containing Supplementary Ideographic Plane 2)
8369 // Or Unicode Plane 1 - Supplementary Multilingual Plane
8370 else if ($type=='TTF' && ($font['sip'] || $font['smp'])) {
8371 if (!$font['used']) { continue; }
8372 $ssfaid="AA";
8373 if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
8374 $ttf = new TTFontFile();
8375 for($sfid=0;$sfid<count($font['subsetfontids']);$sfid++) {
8376 $this->fonts[$k]['n'][$sfid]=$this->n+1; // NB an array for subset
8377 $subsetname = 'MPDF'.$ssfaid.'+'.$font['name'];
8378 $ssfaid++;
8379 $subset = $font['subsets'][$sfid];
8380 unset($subset[0]);
8381 $ttfontstream = $ttf->makeSubsetSIP($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts);
8382 $ttfontsize = strlen($ttfontstream);
8383 $fontstream = gzcompress($ttfontstream);
8384 $widthstring = '';
8385 $toUnistring = '';
8386 foreach($font['subsets'][$sfid] AS $cp=>$u) {
8387 $w = $this->_getCharWidth($font['cw'], $u);
8388 if ($w !== false) {
8389 $widthstring .= $w.' ';
8390 }
8391 else {
8392 $widthstring .= round($ttf->defaultWidth).' ';
8393 }
8394 if ($u > 65535) {
8395 $utf8 = chr(($u>>18)+240).chr((($u>>12)&63)+128).chr((($u>>6)&63)+128) .chr(($u&63)+128);
8396 $utf16 = mb_convert_encoding($utf8, 'UTF-16BE', 'UTF-8');
8397 $l1 = ord($utf16[0]);
8398 $h1 = ord($utf16[1]);
8399 $l2 = ord($utf16[2]);
8400 $h2 = ord($utf16[3]);
8401 $toUnistring .= sprintf("<%02s> <%02s%02s%02s%02s>\n", strtoupper(dechex($cp)), strtoupper(dechex($l1)), strtoupper(dechex($h1)), strtoupper(dechex($l2)), strtoupper(dechex($h2)));
8402 }
8403 else {
8404 $toUnistring .= sprintf("<%02s> <%04s>\n", strtoupper(dechex($cp)), strtoupper(dechex($u)));
8405 }
8406 }
8407
8408 //Additional Type1 or TrueType font
8409 $this->_newobj();
8410 $this->_out('<</Type /Font');
8411 $this->_out('/BaseFont /'.$subsetname);
8412 $this->_out('/Subtype /TrueType');
8413 $this->_out('/FirstChar 0 /LastChar '.(count($font['subsets'][$sfid])-1));
8414 $this->_out('/Widths '.($this->n+1).' 0 R');
8415 $this->_out('/FontDescriptor '.($this->n+2).' 0 R');
8416 $this->_out('/ToUnicode '.($this->n + 3).' 0 R');
8417 $this->_out('>>');
8418 $this->_out('endobj');
8419
8420 //Widths
8421 $this->_newobj();
8422 $this->_out('['.$widthstring.']');
8423 $this->_out('endobj');
8424
8425 //Descriptor
8426 $this->_newobj();
8427 $s='<</Type /FontDescriptor /FontName /'.$subsetname."\n";
8428 foreach($font['desc'] as $kd=>$v) {
8429 if ($kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag
8430 $s.=' /'.$kd.' '.$v."\n";
8431 }
8432 $s.='/FontFile2 '.($this->n + 2).' 0 R';
8433 $this->_out($s.'>>');
8434 $this->_out('endobj');
8435
8436 // ToUnicode
8437 $this->_newobj();
8438 $toUni = "/CIDInit /ProcSet findresource begin\n";
8439 $toUni .= "12 dict begin\n";
8440 $toUni .= "begincmap\n";
8441 $toUni .= "/CIDSystemInfo\n";
8442 $toUni .= "<</Registry (Adobe)\n";
8443 $toUni .= "/Ordering (UCS)\n";
8444 $toUni .= "/Supplement 0\n";
8445 $toUni .= ">> def\n";
8446 $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
8447 $toUni .= "/CMapType 2 def\n";
8448 $toUni .= "1 begincodespacerange\n";
8449 $toUni .= "<00> <FF>\n";
8450 $toUni .= "endcodespacerange\n";
8451 $toUni .= count($font['subsets'][$sfid])." beginbfchar\n";
8452 $toUni .= $toUnistring;
8453 $toUni .= "endbfchar\n";
8454 $toUni .= "endcmap\n";
8455 $toUni .= "CMapName currentdict /CMap defineresource pop\n";
8456 $toUni .= "end\n";
8457 $toUni .= "end\n";
8458
8459 $this->_out('<</Length '.(strlen($toUni)).'>>');
8460 $this->_putstream($toUni);
8461 $this->_out('endobj');
8462
8463 //Font file
8464 $this->_newobj();
8465 $this->_out('<</Length '.strlen($fontstream));
8466 $this->_out('/Filter /FlateDecode');
8467 $this->_out('/Length1 '.$ttfontsize);
8468 $this->_out('>>');
8469 $this->_putstream($fontstream);
8470 $this->_out('endobj');
8471 } // foreach subset
8472 unset($ttf);
8473 }
8474 // TrueType embedded SUBSETS or FULL
8475 else if ($type=='TTF') {
8476 $this->fonts[$k]['n']=$this->n+1;
8477 if ($asSubset ) {
8478 $ssfaid="A";
8479 if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
8480 $ttf = new TTFontFile();
8481 $fontname = 'MPDFA'.$ssfaid.'+'.$font['name'];
8482 $subset = $font['subset'];
8483 unset($subset[0]);
8484 $ttfontstream = $ttf->makeSubset($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts, $font['unAGlyphs']); // mPDF 5.4.05
8485 $ttfontsize = strlen($ttfontstream);
8486 $fontstream = gzcompress($ttfontstream);
8487 $codeToGlyph = $ttf->codeToGlyph;
8488 unset($codeToGlyph[0]);
8489 }
8490 else { $fontname = $font['name']; }
8491 // Type0 Font
8492 // A composite font - a font composed of other fonts, organized hierarchically
8493 $this->_newobj();
8494 $this->_out('<</Type /Font');
8495 $this->_out('/Subtype /Type0');
8496 $this->_out('/BaseFont /'.$fontname.'');
8497 $this->_out('/Encoding /Identity-H');
8498 $this->_out('/DescendantFonts ['.($this->n + 1).' 0 R]');
8499 $this->_out('/ToUnicode '.($this->n + 2).' 0 R');
8500 $this->_out('>>');
8501 $this->_out('endobj');
8502
8503 // CIDFontType2
8504 // A CIDFont whose glyph descriptions are based on TrueType font technology
8505 $this->_newobj();
8506 $this->_out('<</Type /Font');
8507 $this->_out('/Subtype /CIDFontType2');
8508 $this->_out('/BaseFont /'.$fontname.'');
8509 $this->_out('/CIDSystemInfo '.($this->n + 2).' 0 R');
8510 $this->_out('/FontDescriptor '.($this->n + 3).' 0 R');
8511 if (isset($font['desc']['MissingWidth'])){
8512 $this->_out('/DW '.$font['desc']['MissingWidth'].'');
8513 }
8514
8515 if (!$asSubset && file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw')) {
8516 $w = '';
8517 $w=file_get_contents(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw');
8518 $this->_out($w);
8519 }
8520 else {
8521 $this->_putTTfontwidths($font, $asSubset, $ttf->maxUni);
8522 }
8523
8524 $this->_out('/CIDToGIDMap '.($this->n + 4).' 0 R');
8525 $this->_out('>>');
8526 $this->_out('endobj');
8527
8528 // ToUnicode
8529 $this->_newobj();
8530 $toUni = "/CIDInit /ProcSet findresource begin\n";
8531 $toUni .= "12 dict begin\n";
8532 $toUni .= "begincmap\n";
8533 $toUni .= "/CIDSystemInfo\n";
8534 $toUni .= "<</Registry (Adobe)\n";
8535 $toUni .= "/Ordering (UCS)\n";
8536 $toUni .= "/Supplement 0\n";
8537 $toUni .= ">> def\n";
8538 $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
8539 $toUni .= "/CMapType 2 def\n";
8540 $toUni .= "1 begincodespacerange\n";
8541 $toUni .= "<0000> <FFFF>\n";
8542 $toUni .= "endcodespacerange\n";
8543 $toUni .= "1 beginbfrange\n";
8544 $toUni .= "<0000> <FFFF> <0000>\n";
8545 $toUni .= "endbfrange\n";
8546 $toUni .= "endcmap\n";
8547 $toUni .= "CMapName currentdict /CMap defineresource pop\n";
8548 $toUni .= "end\n";
8549 $toUni .= "end\n";
8550 $this->_out('<</Length '.(strlen($toUni)).'>>');
8551 $this->_putstream($toUni);
8552 $this->_out('endobj');
8553
8554
8555 // CIDSystemInfo dictionary
8556 $this->_newobj();
8557 $this->_out('<</Registry (Adobe)');
8558 $this->_out('/Ordering (UCS)');
8559 $this->_out('/Supplement 0');
8560 $this->_out('>>');
8561 $this->_out('endobj');
8562
8563 // Font descriptor
8564 $this->_newobj();
8565 $this->_out('<</Type /FontDescriptor');
8566 $this->_out('/FontName /'.$fontname);
8567 foreach($font['desc'] as $kd=>$v) {
8568 if ($asSubset && $kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag
8569 $this->_out(' /'.$kd.' '.$v);
8570 }
8571 if ($font['panose']) {
8572 $this->_out(' /Style << /Panose <'.$font['panose'].'> >>');
8573 }
8574 if ($asSubset ) {
8575 $this->_out('/FontFile2 '.($this->n + 2).' 0 R');
8576 }
8577 else if ($font['fontkey']) {
8578 // obj ID of a stream containing a TrueType font program
8579 $this->_out('/FontFile2 '.$this->FontFiles[$font['fontkey']]['n'].' 0 R');
8580 }
8581 $this->_out('>>');
8582 $this->_out('endobj');
8583
8584 // Embed CIDToGIDMap
8585 // A specification of the mapping from CIDs to glyph indices
8586 if ($asSubset ) {
8587 $cidtogidmap = '';
8588 $cidtogidmap = str_pad('', 256*256*2, "\x00");
8589 foreach($codeToGlyph as $cc=>$glyph) {
8590 $cidtogidmap[$cc*2] = chr($glyph >> 8);
8591 $cidtogidmap[$cc*2 + 1] = chr($glyph & 0xFF);
8592 }
8593 $cidtogidmap = gzcompress($cidtogidmap);
8594 }
8595 else {
8596 // First see if there is a cached CIDToGIDMapfile
8597 $cidtogidmap = '';
8598 if (file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm')) {
8599 $f=fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm','rb');
8600 while(!feof($f)) { $cidtogidmap .= fread($f, 2048); }
8601 fclose($f);
8602 }
8603 else {
8604 if (!class_exists('TTFontFile', false)) { include(_MPDF_PATH .'classes/ttfontsuni.php'); }
8605 $ttf = new TTFontFile();
8606 $charToGlyph = $ttf->getCTG($font['ttffile'], $font['TTCfontID'], $this->debugfonts, $font['unAGlyphs']); // mPDF 5.4.05
8607 $cidtogidmap = str_pad('', 256*256*2, "\x00");
8608 foreach($charToGlyph as $cc=>$glyph) {
8609 $cidtogidmap[$cc*2] = chr($glyph >> 8);
8610 $cidtogidmap[$cc*2 + 1] = chr($glyph & 0xFF);
8611 }
8612 unset($ttf);
8613 $cidtogidmap = gzcompress($cidtogidmap);
8614 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
8615 $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cgm',"wb");
8616 fwrite($fh,$cidtogidmap,strlen($cidtogidmap));
8617 fclose($fh);
8618 }
8619 }
8620 }
8621 $this->_newobj();
8622 $this->_out('<</Length '.strlen($cidtogidmap).'');
8623 $this->_out('/Filter /FlateDecode');
8624 $this->_out('>>');
8625 $this->_putstream($cidtogidmap);
8626 $this->_out('endobj');
8627
8628 //Font file
8629 if ($asSubset ) {
8630 $this->_newobj();
8631 $this->_out('<</Length '.strlen($fontstream));
8632 $this->_out('/Filter /FlateDecode');
8633 $this->_out('/Length1 '.$ttfontsize);
8634 $this->_out('>>');
8635 $this->_putstream($fontstream);
8636 $this->_out('endobj');
8637 unset($ttf);
8638 }
8639 }
8640 else { $this->Error('Unsupported font type: '.$type.' ('.$name.')'); }
8641 }
8642 }
8643
8644
8645
8646 function _putTTfontwidths(&$font, $asSubset, $maxUni) {
8647 if ($asSubset && file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php')) {
8648 include(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php') ;
8649 $startcid = 128;
8650 }
8651 else {
8652 $rangeid = 0;
8653 $range = array();
8654 $prevcid = -2;
8655 $prevwidth = -1;
8656 $interval = false;
8657 $startcid = 1;
8658 }
8659 if ($asSubset) { $cwlen = $maxUni + 1; }
8660 else { $cwlen = (strlen($font['cw'])/2); }
8661
8662 // for each character
8663 for ($cid=$startcid; $cid<$cwlen; $cid++) {
8664 if ($cid==128 && $asSubset && (!file_exists(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php'))) {
8665 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
8666 $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw127.php',"wb");
8667 $cw127='<?php'."\n";
8668 $cw127.='$rangeid='.$rangeid.";\n";
8669 $cw127.='$prevcid='.$prevcid.";\n";
8670 $cw127.='$prevwidth='.$prevwidth.";\n";
8671 if ($interval) { $cw127.='$interval=true'.";\n"; }
8672 else { $cw127.='$interval=false'.";\n"; }
8673 $cw127.='$range='.var_export($range,true).";\n";
8674 $cw127.="?>";
8675 fwrite($fh,$cw127,strlen($cw127));
8676 fclose($fh);
8677 }
8678 }
8679 if ($font['cw'][$cid*2] == "\00" && $font['cw'][$cid*2+1] == "\00") { continue; }
8680 $width = (ord($font['cw'][$cid*2]) << 8) + ord($font['cw'][$cid*2+1]);
8681 if ($width == 65535) { $width = 0; }
8682 if ($asSubset && $cid > 255 && (!isset($font['subset'][$cid]) || !$font['subset'][$cid])) {
8683 continue;
8684 }
8685 if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
8686 if ($cid == ($prevcid + 1)) {
8687 // consecutive CID
8688 if ($width == $prevwidth) {
8689 if ($width == $range[$rangeid][0]) {
8690 $range[$rangeid][] = $width;
8691 } else {
8692 array_pop($range[$rangeid]);
8693 // new range
8694 $rangeid = $prevcid;
8695 $range[$rangeid] = array();
8696 $range[$rangeid][] = $prevwidth;
8697 $range[$rangeid][] = $width;
8698 }
8699 $interval = true;
8700 $range[$rangeid]['interval'] = true;
8701 } else {
8702 if ($interval) {
8703 // new range
8704 $rangeid = $cid;
8705 $range[$rangeid] = array();
8706 $range[$rangeid][] = $width;
8707 } else {
8708 $range[$rangeid][] = $width;
8709 }
8710 $interval = false;
8711 }
8712 } else {
8713 // new range
8714 $rangeid = $cid;
8715 $range[$rangeid] = array();
8716 $range[$rangeid][] = $width;
8717 $interval = false;
8718 }
8719 $prevcid = $cid;
8720 $prevwidth = $width;
8721 }
8722 }
8723 $w = $this->_putfontranges($range);
8724 $this->_out($w);
8725 if (!$asSubset) {
8726 if (is_writable(dirname(_MPDF_TTFONTDATAPATH.'x'))) {
8727 $fh = fopen(_MPDF_TTFONTDATAPATH.$font['fontkey'].'.cw',"wb");
8728 fwrite($fh,$w,strlen($w));
8729 fclose($fh);
8730 }
8731 }
8732 }
8733
8734 function _putfontranges(&$range) {
8735 // optimize ranges
8736 $prevk = -1;
8737 $nextk = -1;
8738 $prevint = false;
8739 foreach ($range as $k => $ws) {
8740 $cws = count($ws);
8741 if (($k == $nextk) AND (!$prevint) AND ((!isset($ws['interval'])) OR ($cws < 4))) {
8742 if (isset($range[$k]['interval'])) {
8743 unset($range[$k]['interval']);
8744 }
8745 $range[$prevk] = array_merge($range[$prevk], $range[$k]);
8746 unset($range[$k]);
8747 } else {
8748 $prevk = $k;
8749 }
8750 $nextk = $k + $cws;
8751 if (isset($ws['interval'])) {
8752 if ($cws > 3) {
8753 $prevint = true;
8754 } else {
8755 $prevint = false;
8756 }
8757 unset($range[$k]['interval']);
8758 --$nextk;
8759 } else {
8760 $prevint = false;
8761 }
8762 }
8763 // output data
8764 $w = '';
8765 foreach ($range as $k => $ws) {
8766 if (count(array_count_values($ws)) == 1) {
8767 // interval mode is more compact
8768 $w .= ' '.$k.' '.($k + count($ws) - 1).' '.$ws[0];
8769 } else {
8770 // range mode
8771 $w .= ' '.$k.' [ '.implode(' ', $ws).' ]' . "\n";
8772 }
8773 }
8774 return '/W ['.$w.' ]';
8775 }
8776
8777
8778 function _putfontwidths(&$font, $cidoffset=0) {
8779 ksort($font['cw']);
8780 unset($font['cw'][65535]);
8781 $rangeid = 0;
8782 $range = array();
8783 $prevcid = -2;
8784 $prevwidth = -1;
8785 $interval = false;
8786 // for each character
8787 foreach ($font['cw'] as $cid => $width) {
8788 $cid -= $cidoffset;
8789 if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
8790 if ($cid == ($prevcid + 1)) {
8791 // consecutive CID
8792 if ($width == $prevwidth) {
8793 if ($width == $range[$rangeid][0]) {
8794 $range[$rangeid][] = $width;
8795 } else {
8796 array_pop($range[$rangeid]);
8797 // new range
8798 $rangeid = $prevcid;
8799 $range[$rangeid] = array();
8800 $range[$rangeid][] = $prevwidth;
8801 $range[$rangeid][] = $width;
8802 }
8803 $interval = true;
8804 $range[$rangeid]['interval'] = true;
8805 } else {
8806 if ($interval) {
8807 // new range
8808 $rangeid = $cid;
8809 $range[$rangeid] = array();
8810 $range[$rangeid][] = $width;
8811 } else {
8812 $range[$rangeid][] = $width;
8813 }
8814 $interval = false;
8815 }
8816 } else {
8817 // new range
8818 $rangeid = $cid;
8819 $range[$rangeid] = array();
8820 $range[$rangeid][] = $width;
8821 $interval = false;
8822 }
8823 $prevcid = $cid;
8824 $prevwidth = $width;
8825 }
8826 }
8827 $this->_out($this->_putfontranges($range));
8828 }
8829
8830
8831 /*-- CJK-FONTS --*/
8832
8833 // from class PDF_Chinese CJK EXTENSIONS
8834 function _putType0(&$font)
8835 {
8836 //Type0
8837 $this->_out('/Subtype /Type0');
8838 $this->_out('/BaseFont /'.$font['name'].'-'.$font['CMap']);
8839 $this->_out('/Encoding /'.$font['CMap']);
8840 $this->_out('/DescendantFonts ['.($this->n+1).' 0 R]');
8841 $this->_out('>>');
8842 $this->_out('endobj');
8843 //CIDFont
8844 $this->_newobj();
8845 $this->_out('<</Type /Font');
8846 $this->_out('/Subtype /CIDFontType0');
8847 $this->_out('/BaseFont /'.$font['name']);
8848
8849 $cidinfo = '/Registry '.$this->_textstring('Adobe');
8850 $cidinfo .= ' /Ordering '.$this->_textstring($font['registry']['ordering']);
8851 $cidinfo .= ' /Supplement '.$font['registry']['supplement'];
8852 $this->_out('/CIDSystemInfo <<'.$cidinfo.'>>');
8853
8854 $this->_out('/FontDescriptor '.($this->n+1).' 0 R');
8855 if (isset($font['MissingWidth'])){
8856 $this->_out('/DW '.$font['MissingWidth'].'');
8857 }
8858 $this->_putfontwidths($font, 31);
8859 $this->_out('>>');
8860 $this->_out('endobj');
8861
8862 //Font descriptor
8863 $this->_newobj();
8864 $s = '<</Type /FontDescriptor /FontName /'.$font['name'];
8865 foreach ($font['desc'] as $k => $v) {
8866 if ($k != 'Style') {
8867 $s .= ' /'.$k.' '.$v.'';
8868 }
8869 }
8870 $this->_out($s.'>>');
8871 $this->_out('endobj');
8872 }
8873 /*-- END CJK-FONTS --*/
8874
8875
8876
8877 function _putimages()
8878 {
8879 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
8880 reset($this->images);
8881 while(list($file,$info)=each($this->images)) {
8882 $this->_newobj();
8883 $this->images[$file]['n']=$this->n;
8884 $this->_out('<</Type /XObject');
8885 $this->_out('/Subtype /Image');
8886 $this->_out('/Width '.$info['w']);
8887 $this->_out('/Height '.$info['h']);
8888 if (isset($info['masked'])) {
8889 $this->_out('/SMask '.($this->n - 1).' 0 R');
8890 }
8891 if($info['cs']=='Indexed') {
8892 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.")."); }
8893 $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
8894 }
8895 else {
8896 $this->_out('/ColorSpace /'.$info['cs']);
8897 if($info['cs']=='DeviceCMYK') {
8898 if ($this->PDFA && $this->restrictColorSpace!=3) { $this->Error("PDFA1-b does not permit Images using mixed colour space (".$file.")."); }
8899 if($info['type']=='jpg') { $this->_out('/Decode [1 0 1 0 1 0 1 0]'); }
8900 }
8901 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.")."); }
8902 }
8903 $this->_out('/BitsPerComponent '.$info['bpc']);
8904 if (isset($info['f']) && $info['f']) { $this->_out('/Filter /'.$info['f']); }
8905 if(isset($info['parms'])) { $this->_out($info['parms']); }
8906 if(isset($info['trns']) and is_array($info['trns'])) {
8907 $trns='';
8908 for($i=0;$i<count($info['trns']);$i++)
8909 $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
8910 $this->_out('/Mask ['.$trns.']');
8911 }
8912 $this->_out('/Length '.strlen($info['data']).'>>');
8913 $this->_putstream($info['data']);
8914
8915 unset($this->images[$file]['data']);
8916 $this->_out('endobj');
8917 //Palette
8918 if($info['cs']=='Indexed') {
8919 $this->_newobj();
8920 $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
8921 $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
8922 $this->_putstream($pal);
8923 $this->_out('endobj');
8924 }
8925 }
8926 }
8927
8928 function _putinfo()
8929 {
8930 $this->_out('/Producer '.$this->_UTF16BEtextstring('mPDF '.mPDF_VERSION));
8931 if(!empty($this->title))
8932 $this->_out('/Title '.$this->_UTF16BEtextstring($this->title));
8933 if(!empty($this->subject))
8934 $this->_out('/Subject '.$this->_UTF16BEtextstring($this->subject));
8935 if(!empty($this->author))
8936 $this->_out('/Author '.$this->_UTF16BEtextstring($this->author));
8937 if(!empty($this->keywords))
8938 $this->_out('/Keywords '.$this->_UTF16BEtextstring($this->keywords));
8939 if(!empty($this->creator))
8940 $this->_out('/Creator '.$this->_UTF16BEtextstring($this->creator));
8941
8942 $z = date('O'); // +0200
8943 $offset = substr($z,0,3)."'".substr($z,3,2)."'";
8944 $this->_out('/CreationDate '.$this->_textstring(date('YmdHis').$offset));
8945 $this->_out('/ModDate '.$this->_textstring(date('YmdHis').$offset));
8946 if ($this->PDFX) {
8947 $this->_out('/Trapped/False');
8948 $this->_out('/GTS_PDFXVersion(PDF/X-1a:2003)');
8949 }
8950 }
8951
8952 function _putmetadata() {
8953 $this->_newobj();
8954 $this->MetadataRoot = $this->n;
8955 $Producer = 'mPDF '.mPDF_VERSION;
8956 $z = date('O'); // +0200
8957 $offset = substr($z,0,3).':'.substr($z,3,2);
8958 $CreationDate = date('Y-m-d\TH:i:s').$offset; // 2006-03-10T10:47:26-05:00 2006-06-19T09:05:17Z
8959 $uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff),
8960 mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000,
8961 mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) );
8962
8963
8964 $m = '<?xpacket begin="'.chr(239).chr(187).chr(191).'" id="W5M0MpCehiHzreSzNTczkc9d"?>'."\n"; // begin = FEFF BOM
8965 $m .= ' <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="3.1-701">'."\n";
8966 $m .= ' <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">'."\n";
8967 $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">'."\n";
8968 $m .= ' <pdf:Producer>'.$Producer.'</pdf:Producer>'."\n";
8969 if(!empty($this->keywords)) { $m .= ' <pdf:Keywords>'.$this->keywords.'</pdf:Keywords>'."\n"; }
8970 $m .= ' </rdf:Description>'."\n";
8971
8972 $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:xmp="http://ns.adobe.com/xap/1.0/">'."\n";
8973 $m .= ' <xmp:CreateDate>'.$CreationDate.'</xmp:CreateDate>'."\n";
8974 $m .= ' <xmp:ModifyDate>'.$CreationDate.'</xmp:ModifyDate>'."\n";
8975 $m .= ' <xmp:MetadataDate>'.$CreationDate.'</xmp:MetadataDate>'."\n";
8976 if(!empty($this->creator)) { $m .= ' <xmp:CreatorTool>'.$this->creator.'</xmp:CreatorTool>'."\n"; }
8977 $m .= ' </rdf:Description>'."\n";
8978
8979 // DC elements
8980 $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:dc="http://purl.org/dc/elements/1.1/">'."\n";
8981 $m .= ' <dc:format>application/pdf</dc:format>'."\n";
8982 if(!empty($this->title)) {
8983 $m .= ' <dc:title>
8984 <rdf:Alt>
8985 <rdf:li xml:lang="x-default">'.$this->title.'</rdf:li>
8986 </rdf:Alt>
8987 </dc:title>'."\n";
8988 }
8989 if(!empty($this->keywords)) {
8990 $m .= ' <dc:subject>
8991 <rdf:Bag>
8992 <rdf:li>'.$this->keywords.'</rdf:li>
8993 </rdf:Bag>
8994 </dc:subject>'."\n";
8995 }
8996 if(!empty($this->subject)) {
8997 $m .= ' <dc:description>
8998 <rdf:Alt>
8999 <rdf:li xml:lang="x-default">'.$this->subject.'</rdf:li>
9000 </rdf:Alt>
9001 </dc:description>'."\n";
9002 }
9003 if(!empty($this->author)) {
9004 $m .= ' <dc:creator>
9005 <rdf:Seq>
9006 <rdf:li>'.$this->author.'</rdf:li>
9007 </rdf:Seq>
9008 </dc:creator>'."\n";
9009 }
9010 $m .= ' </rdf:Description>'."\n";
9011
9012
9013 // This bit is specific to PDFX-1a
9014 if ($this->PDFX) {
9015 $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";
9016 }
9017
9018 // This bit is specific to PDFA-1b
9019 else if ($this->PDFA) {
9020 $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/" >'."\n";
9021 $m .= ' <pdfaid:part>1</pdfaid:part>'."\n";
9022 $m .= ' <pdfaid:conformance>B</pdfaid:conformance>'."\n";
9023 $m .= ' <pdfaid:amd>2005</pdfaid:amd>'."\n";
9024 $m .= ' </rdf:Description>'."\n";
9025 }
9026
9027 $m .= ' <rdf:Description rdf:about="uuid:'.$uuid.'" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">'."\n";
9028 $m .= ' <xmpMM:DocumentID>uuid:'.$uuid.'</xmpMM:DocumentID>'."\n";
9029 $m .= ' </rdf:Description>'."\n";
9030 $m .= ' </rdf:RDF>'."\n";
9031 $m .= ' </x:xmpmeta>'."\n";
9032 $m .= str_repeat(str_repeat(' ',100)."\n",20); // 2-4kB whitespace padding required
9033 $m .= '<?xpacket end="w"?>'; // "r" read only
9034 $this->_out('<</Type/Metadata/Subtype/XML/Length '.strlen($m).'>>');
9035 $this->_putstream($m);
9036 $this->_out('endobj');
9037 }
9038
9039 function _putoutputintent() {
9040 $this->_newobj();
9041 $this->OutputIntentRoot = $this->n;
9042 $this->_out('<</Type /OutputIntent');
9043
9044 if ($this->PDFA) {
9045 $this->_out('/S /GTS_PDFA1');
9046 if ($this->ICCProfile) {
9047 $this->_out('/Info ('.preg_replace('/_/',' ',$this->ICCProfile).')');
9048 $this->_out('/OutputConditionIdentifier (Custom)');
9049 $this->_out('/OutputCondition ()');
9050 }
9051 else {
9052 $this->_out('/Info (sRGB IEC61966-2.1)');
9053 $this->_out('/OutputConditionIdentifier (sRGB IEC61966-2.1)');
9054 $this->_out('/OutputCondition ()');
9055 }
9056 $this->_out('/DestOutputProfile '.($this->n+1).' 0 R');
9057 }
9058 else if ($this->PDFX) { // always a CMYK profile
9059 $this->_out('/S /GTS_PDFX');
9060 if ($this->ICCProfile) {
9061 $this->_out('/Info ('.preg_replace('/_/',' ',$this->ICCProfile).')');
9062 $this->_out('/OutputConditionIdentifier (Custom)');
9063 $this->_out('/OutputCondition ()');
9064 $this->_out('/DestOutputProfile '.($this->n+1).' 0 R');
9065 }
9066 else {
9067 $this->_out('/Info (CGATS TR 001)');
9068 $this->_out('/OutputConditionIdentifier (CGATS TR 001)');
9069 $this->_out('/OutputCondition (CGATS TR 001 (SWOP))');
9070 $this->_out('/RegistryName (http://www.color.org)');
9071 }
9072 }
9073 $this->_out('>>');
9074 $this->_out('endobj');
9075
9076 if ($this->PDFX && !$this->ICCProfile) { return; } // no ICCProfile embedded
9077
9078 $this->_newobj();
9079 if ($this->ICCProfile)
9080 $s = file_get_contents(_MPDF_PATH.'iccprofiles/'.$this->ICCProfile.'.icc');
9081 else
9082 $s = file_get_contents(_MPDF_PATH.'iccprofiles/sRGB_IEC61966-2-1.icc');
9083 if ($this->compress) { $s = gzcompress($s); }
9084 $this->_out('<<');
9085 if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace == 3)) { $this->_out('/N 4'); }
9086 else { $this->_out('/N 3'); }
9087 if ($this->compress)
9088 $this->_out('/Filter /FlateDecode ');
9089 $this->_out('/Length '.strlen($s).'>>');
9090 $this->_putstream($s);
9091 $this->_out('endobj');
9092 }
9093
9094
9095 function _putcatalog() {
9096 $this->_out('/Type /Catalog');
9097 $this->_out('/Pages 1 0 R');
9098 if($this->ZoomMode=='fullpage') $this->_out('/OpenAction [3 0 R /Fit]');
9099 elseif($this->ZoomMode=='fullwidth') $this->_out('/OpenAction [3 0 R /FitH null]');
9100 elseif($this->ZoomMode=='real') $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
9101 elseif(!is_string($this->ZoomMode)) $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode/100).']');
9102 else $this->_out('/OpenAction [3 0 R /XYZ null null null]');
9103 if($this->LayoutMode=='single') $this->_out('/PageLayout /SinglePage');
9104 elseif($this->LayoutMode=='continuous') $this->_out('/PageLayout /OneColumn');
9105 elseif($this->LayoutMode=='twoleft') $this->_out('/PageLayout /TwoColumnLeft');
9106 elseif($this->LayoutMode=='tworight') $this->_out('/PageLayout /TwoColumnRight');
9107 elseif($this->LayoutMode=='two') {
9108 if ($this->mirrorMargins) { $this->_out('/PageLayout /TwoColumnRight'); }
9109 else { $this->_out('/PageLayout /TwoColumnLeft'); }
9110 }
9111
9112 /*-- BOOKMARKS --*/
9113 if(count($this->BMoutlines)>0) {
9114 $this->_out('/Outlines '.$this->OutlineRoot.' 0 R');
9115 $this->_out('/PageMode /UseOutlines');
9116 }
9117 /*-- END BOOKMARKS --*/
9118 if(is_int(strpos($this->DisplayPreferences,'FullScreen'))) $this->_out('/PageMode /FullScreen');
9119
9120 // Metadata
9121 if ($this->PDFA || $this->PDFX) {
9122 $this->_out('/Metadata '.$this->MetadataRoot.' 0 R');
9123 }
9124 // OutputIntents
9125 if ($this->PDFA || $this->PDFX || $this->ICCProfile) {
9126 $this->_out('/OutputIntents ['.$this->OutputIntentRoot.' 0 R]');
9127 }
9128
9129 /*-- FORMS --*/
9130 if (count($this->form->forms)>0) {
9131 $this->form->_putFormsCatalog();
9132 }
9133 /*-- END FORMS --*/
9134 if ( isset($this->js) ) {
9135 $this->_out('/Names << /JavaScript '.($this->n_js).' 0 R >> ');
9136 }
9137
9138 if($this->DisplayPreferences || $this->directionality == 'rtl' || $this->mirrorMargins) {
9139 $this->_out('/ViewerPreferences<<');
9140 if(is_int(strpos($this->DisplayPreferences,'HideMenubar'))) $this->_out('/HideMenubar true');
9141 if(is_int(strpos($this->DisplayPreferences,'HideToolbar'))) $this->_out('/HideToolbar true');
9142 if(is_int(strpos($this->DisplayPreferences,'HideWindowUI'))) $this->_out('/HideWindowUI true');
9143 if(is_int(strpos($this->DisplayPreferences,'DisplayDocTitle'))) $this->_out('/DisplayDocTitle true');
9144 if(is_int(strpos($this->DisplayPreferences,'CenterWindow'))) $this->_out('/CenterWindow true');
9145 if(is_int(strpos($this->DisplayPreferences,'FitWindow'))) $this->_out('/FitWindow true');
9146 // /PrintScaling is PDF 1.6 spec.
9147 if(is_int(strpos($this->DisplayPreferences,'NoPrintScaling')) && !$this->PDFA && !$this->PDFX)
9148 $this->_out('/PrintScaling /None');
9149 if($this->directionality == 'rtl') $this->_out('/Direction /R2L');
9150 // /Duplex is PDF 1.7 spec.
9151 if($this->mirrorMargins && !$this->PDFA && !$this->PDFX) {
9152 // if ($this->DefOrientation=='P') $this->_out('/Duplex /DuplexFlipShortEdge');
9153 $this->_out('/Duplex /DuplexFlipLongEdge'); // PDF v1.7+
9154 }
9155 $this->_out('>>');
9156 }
9157 // mPDF 5.6.01
9158 if($this->open_layer_pane && ($this->hasOC || count($this->layers)))
9159 $this->_out('/PageMode /UseOC');
9160
9161 // mPDF 5.6.01
9162 if ($this->hasOC || count($this->layers)) {
9163 $p = $v = $h = $l = $loff = $lall = $as = ''; // mPDF 5.6.28
9164 if ($this->hasOC) {
9165 if (($this->hasOC & 1) == 1) $p=$this->n_ocg_print.' 0 R';
9166 if (($this->hasOC & 2) == 2) $v=$this->n_ocg_view.' 0 R';
9167 if (($this->hasOC & 4) == 4) $h=$this->n_ocg_hidden.' 0 R';
9168 $as="<</Event /Print /OCGs [$p $v $h] /Category [/Print]>> <</Event /View /OCGs [$p $v $h] /Category [/View]>>";
9169 }
9170
9171 if(count($this->layers)) {
9172 foreach($this->layers as $k=>$layer) { // mPDF 5.6.28
9173 if (strtolower($this->layerDetails[$k]['state'])=='hidden') { $loff .= $layer['n'].' 0 R '; }
9174 else { $l .= $layer['n'].' 0 R '; }
9175 $lall .= $layer['n'].' 0 R ';
9176 }
9177 }
9178 $this->_out("/OCProperties <</OCGs [$p $v $h $lall] /D <</ON [$p $l] /OFF [$v $h $loff] "); // mPDF 5.6.28
9179 $this->_out("/Order [$v $p $h $lall] "); // mPDF 5.6.28
9180 if ($as) $this->_out("/AS [$as] ");
9181 $this->_out(">>>>");
9182
9183 }
9184
9185 }
9186
9187 // Inactive function left for backwards compatability
9188 function SetUserRights($enable=true, $annots="", $form="", $signature="") {
9189 // Does nothing
9190 }
9191
9192 function _enddoc() {
9193 if ($this->progressBar) { $this->UpdateProgressBar(2,'10','Writing Headers & Footers'); } // *PROGRESS-BAR*
9194 $this->_puthtmlheaders(); // *HTMLHEADERS-FOOTERS*
9195 if ($this->progressBar) { $this->UpdateProgressBar(2,'20','Writing Pages'); } // *PROGRESS-BAR*
9196 // Remove references to unused fonts (usually default font)
9197 foreach($this->fonts as $fk=>$font) {
9198 if (!$font['used'] && ($font['type']=='TTF')) {
9199 if ($font['sip'] || $font['smp']) {
9200 foreach($font['subsetfontids'] AS $k => $fid) {
9201 foreach($this->pages AS $pn=>$page) {
9202 $this->pages[$pn] = preg_replace('/\s\/F'.$fid.' \d[\d.]* Tf\s/is',' ',$this->pages[$pn]);
9203 }
9204 }
9205 }
9206 else {
9207 foreach($this->pages AS $pn=>$page) {
9208 $this->pages[$pn] = preg_replace('/\s\/F'.$font['i'].' \d[\d.]* Tf\s/is',' ',$this->pages[$pn]);
9209 }
9210 }
9211 }
9212 }
9213
9214 // mPDF 5.6.01 - LAYERS
9215 if (count($this->layers)) {
9216 foreach($this->pages AS $pn=>$page) {
9217 preg_match_all('/\/OCZ-index \/ZI(\d+) BDC(.*?)(EMCZ)-index/is',$this->pages[$pn],$m1);
9218 preg_match_all('/\/OCBZ-index \/ZI(\d+) BDC(.*?)(EMCBZ)-index/is',$this->pages[$pn],$m2);
9219 preg_match_all('/\/OCGZ-index \/ZI(\d+) BDC(.*?)(EMCGZ)-index/is',$this->pages[$pn],$m3);
9220 $m = array();
9221 for ($i=0;$i<4;$i++) {
9222 $m[$i] = array_merge($m1[$i],$m2[$i],$m3[$i]);
9223 }
9224 if (count($m[0])) {
9225 $sortarr = array();
9226 for($i=0;$i<count($m[0]);$i++) {
9227 $key = $m[1][$i]*2;
9228 if ($m[3][$i]=='EMCZ') $key +=2; // background first then gradient then normal
9229 else if ($m[3][$i]=='EMCGZ') $key +=1;
9230 $sortarr[$i] = $key;
9231 }
9232 asort($sortarr);
9233 foreach($sortarr AS $i=>$k) {
9234 $this->pages[$pn] = str_replace($m[0][$i],'',$this->pages[$pn] );
9235 $this->pages[$pn] .= "\n".$m[0][$i]."\n";
9236 }
9237 $this->pages[$pn] = preg_replace('/\/OC[BG]{0,1}Z-index \/ZI(\d+) BDC/is','/OC /ZI\\1 BDC ',$this->pages[$pn]);
9238 $this->pages[$pn] = preg_replace('/EMC[BG]{0,1}Z-index/is','EMC',$this->pages[$pn]);
9239 }
9240 }
9241 }
9242
9243 $this->_putpages();
9244 if ($this->progressBar) { $this->UpdateProgressBar(2,'30','Writing document resources'); } // *PROGRESS-BAR*
9245
9246 $this->_putresources();
9247 //Info
9248 $this->_newobj();
9249 $this->InfoRoot = $this->n;
9250 $this->_out('<<');
9251 if ($this->progressBar) { $this->UpdateProgressBar(2,'80','Writing document info'); } // *PROGRESS-BAR*
9252 $this->_putinfo();
9253 $this->_out('>>');
9254 $this->_out('endobj');
9255
9256 // METADATA
9257 if ($this->PDFA || $this->PDFX) { $this->_putmetadata(); }
9258 // OUTPUTINTENT
9259 if ($this->PDFA || $this->PDFX || $this->ICCProfile) { $this->_putoutputintent(); }
9260
9261 //Catalog
9262 $this->_newobj();
9263 $this->_out('<<');
9264 if ($this->progressBar) { $this->UpdateProgressBar(2,'90','Writing document catalog'); } // *PROGRESS-BAR*
9265 $this->_putcatalog();
9266 $this->_out('>>');
9267 $this->_out('endobj');
9268 //Cross-ref
9269 $o=strlen($this->buffer);
9270 $this->_out('xref');
9271 $this->_out('0 '.($this->n+1));
9272 $this->_out('0000000000 65535 f ');
9273 for($i=1; $i <= $this->n ; $i++)
9274 $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i]));
9275 //Trailer
9276 $this->_out('trailer');
9277 $this->_out('<<');
9278 $this->_puttrailer();
9279 $this->_out('>>');
9280 $this->_out('startxref');
9281 $this->_out($o);
9282
9283 $this->buffer .= '%%EOF';
9284 $this->state=3;
9285 /*-- IMPORTS --*/
9286
9287 if ($this->enableImports && count($this->parsers) > 0) {
9288 foreach ($this->parsers as $k => $_){
9289 $this->parsers[$k]->closeFile();
9290 $this->parsers[$k] = null;
9291 unset($this->parsers[$k]);
9292 }
9293 }
9294 /*-- END IMPORTS --*/
9295 }
9296
9297 function _beginpage($orientation,$mgl='',$mgr='',$mgt='',$mgb='',$mgh='',$mgf='',$ohname='',$ehname='',$ofname='',$efname='',$ohvalue=0,$ehvalue=0,$ofvalue=0,$efvalue=0,$pagesel='',$newformat='') {
9298 if (!($pagesel && $this->page==1 && (sprintf("%0.4f", $this->y)==sprintf("%0.4f", $this->tMargin)))) {
9299 $this->page++;
9300 $this->pages[$this->page]='';
9301 }
9302 $this->state=2;
9303 $resetHTMLHeadersrequired = false;
9304
9305 if ($newformat) { $this->_setPageSize($newformat, $orientation); }
9306 /*-- CSS-PAGE --*/
9307 // Paged media (page-box)
9308
9309 if ($pagesel || (isset($this->page_box['using']) && $this->page_box['using'])) {
9310 if ($pagesel || $this->page==1) { $first = true; }
9311 else { $first = false; }
9312 if ($this->mirrorMargins && ($this->page % 2==0)) { $oddEven = 'E'; }
9313 else { $oddEven = 'O'; }
9314 if ($pagesel) { $psel = $pagesel; }
9315 else if ($this->page_box['current']) { $psel = $this->page_box['current']; }
9316 else { $psel = ''; }
9317 list($orientation,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS($psel, $first, $oddEven);
9318 if ($this->mirrorMargins && ($this->page % 2==0)) {
9319 if ($hname) { $ehvalue = 1; $ehname = $hname; } else { $ehvalue = -1; }
9320 if ($fname) { $efvalue = 1; $efname = $fname; } else { $efvalue = -1; }
9321 }
9322 else {
9323 if ($hname) { $ohvalue = 1; $ohname = $hname; } else { $ohvalue = -1; }
9324 if ($fname) { $ofvalue = 1; $ofname = $fname; } else { $ofvalue = -1; }
9325 }
9326 if ($resetpagenum || $pagenumstyle || $suppress) {
9327 $this->PageNumSubstitutions[] = array('from'=>($this->page), 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=>$suppress);
9328 }
9329 // PAGED MEDIA - CROP / CROSS MARKS from @PAGE
9330 $this->show_marks = $marks;
9331
9332 // Background color
9333 if (isset($bg['BACKGROUND-COLOR'])) {
9334 $cor = $this->ConvertColor($bg['BACKGROUND-COLOR']);
9335 if ($cor) {
9336 $this->bodyBackgroundColor = $cor;
9337 }
9338 }
9339 else { $this->bodyBackgroundColor = false; }
9340
9341 /*-- BACKGROUNDS --*/
9342 if (isset($bg['BACKGROUND-GRADIENT'])) {
9343 $this->bodyBackgroundGradient = $bg['BACKGROUND-GRADIENT'];
9344 }
9345 else { $this->bodyBackgroundGradient = false; }
9346
9347 // Tiling Patterns
9348 if (isset($bg['BACKGROUND-IMAGE']) && $bg['BACKGROUND-IMAGE']) {
9349 $ret = $this->SetBackground($bg, $this->pgwidth);
9350 if ($ret) { $this->bodyBackgroundImage = $ret; }
9351 }
9352 else { $this->bodyBackgroundImage = false; }
9353 /*-- END BACKGROUNDS --*/
9354
9355 $this->page_box['current'] = $psel;
9356 $this->page_box['using'] = true;
9357 }
9358 /*-- END CSS-PAGE --*/
9359
9360 //Page orientation
9361 if(!$orientation)
9362 $orientation=$this->DefOrientation;
9363 else {
9364 $orientation=strtoupper(substr($orientation,0,1));
9365 if($orientation!=$this->DefOrientation)
9366 $this->OrientationChanges[$this->page]=true;
9367 }
9368 if($orientation!=$this->CurOrientation || $newformat) {
9369
9370 //Change orientation
9371 if($orientation=='P') {
9372 $this->wPt=$this->fwPt;
9373 $this->hPt=$this->fhPt;
9374 $this->w=$this->fw;
9375 $this->h=$this->fh;
9376 if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P') {
9377 $this->tMargin = $this->orig_tMargin;
9378 $this->bMargin = $this->orig_bMargin;
9379 $this->DeflMargin = $this->orig_lMargin;
9380 $this->DefrMargin = $this->orig_rMargin;
9381 $this->margin_header = $this->orig_hMargin;
9382 $this->margin_footer = $this->orig_fMargin;
9383 }
9384 else { $resetHTMLHeadersrequired = true; } // *HTMLHEADERS-FOOTERS*
9385 }
9386 else {
9387 $this->wPt=$this->fhPt;
9388 $this->hPt=$this->fwPt;
9389 $this->w=$this->fh;
9390 $this->h=$this->fw;
9391 if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation=='P') {
9392 $this->tMargin = $this->orig_lMargin;
9393 $this->bMargin = $this->orig_rMargin;
9394 $this->DeflMargin = $this->orig_bMargin;
9395 $this->DefrMargin = $this->orig_tMargin;
9396 $this->margin_header = $this->orig_hMargin;
9397 $this->margin_footer = $this->orig_fMargin;
9398 }
9399 else { $resetHTMLHeadersrequired = true; } // *HTMLHEADERS-FOOTERS*
9400
9401 }
9402 $this->CurOrientation=$orientation;
9403 $this->ResetMargins();
9404 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
9405 $this->PageBreakTrigger=$this->h-$this->bMargin;
9406 }
9407
9408 $this->pageDim[$this->page]['w']=$this->w ;
9409 $this->pageDim[$this->page]['h']=$this->h ;
9410
9411 $this->pageDim[$this->page]['outer_width_LR'] = isset($this->page_box['outer_width_LR']) ? $this->page_box['outer_width_LR'] : 0;
9412 $this->pageDim[$this->page]['outer_width_TB'] = isset($this->page_box['outer_width_TB']) ? $this->page_box['outer_width_TB'] : 0;
9413 if (!isset($this->page_box['outer_width_LR']) && !isset($this->page_box['outer_width_TB'])) {
9414 $this->pageDim[$this->page]['bleedMargin'] = 0;
9415 }
9416 else if ($this->bleedMargin <= $this->page_box['outer_width_LR'] && $this->bleedMargin <= $this->page_box['outer_width_TB']) {
9417 $this->pageDim[$this->page]['bleedMargin'] = $this->bleedMargin;
9418 }
9419 else {
9420 $this->pageDim[$this->page]['bleedMargin'] = min($this->page_box['outer_width_LR'], $this->page_box['outer_width_TB'])-0.01;
9421 }
9422
9423 // If Page Margins are re-defined
9424 // strlen()>0 is used to pick up (integer) 0, (string) '0', or set value
9425 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)) {
9426 if (strlen($mgl)>0) $this->DeflMargin = $mgl;
9427 if (strlen($mgr)>0) $this->DefrMargin = $mgr;
9428 if (strlen($mgt)>0) $this->tMargin = $mgt;
9429 if (strlen($mgb)>0) $this->bMargin = $mgb;
9430 if (strlen($mgh)>0) $this->margin_header=$mgh;
9431 if (strlen($mgf)>0) $this->margin_footer=$mgf;
9432 $this->ResetMargins();
9433 $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
9434 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
9435 $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
9436 }
9437
9438 $this->ResetMargins();
9439 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
9440 $this->SetAutoPageBreak($this->autoPageBreak,$this->bMargin);
9441
9442 // Reset column top margin
9443 $this->y0 = $this->tMargin;
9444
9445 $this->x=$this->lMargin;
9446 $this->y=$this->tMargin;
9447 $this->FontFamily='';
9448
9449 // HEADERS AND FOOTERS
9450 if ($ohvalue<0 || strtoupper($ohvalue)=='OFF') {
9451 $this->HTMLHeader = '';
9452 $this->headerDetails['odd'] = array();
9453 $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
9454 }
9455 else if ($ohname && $ohvalue>0) {
9456 /*-- HTMLHEADERS-FOOTERS --*/
9457 if (preg_match('/^html_(.*)$/i',$ohname,$n)) {
9458 if (isset($this->pageHTMLheaders[$n[1]])) { $this->HTMLHeader = $this->pageHTMLheaders[$n[1]]; }
9459 else { $this->HTMLHeader = ''; }
9460 $this->headerDetails['odd'] = array();
9461 $resetHTMLHeadersrequired = true;
9462 }
9463 else {
9464 /*-- END HTMLHEADERS-FOOTERS --*/
9465 if (isset($this->pageheaders[$ohname])) { $this->headerDetails['odd'] = $this->pageheaders[$ohname]; }
9466 else if ($ohname!='_default') { $this->headerDetails['odd'] = array(); }
9467 $this->HTMLHeader = '';
9468 /*-- HTMLHEADERS-FOOTERS --*/
9469 $resetHTMLHeadersrequired = false;
9470 }
9471 /*-- END HTMLHEADERS-FOOTERS --*/
9472 }
9473
9474 if ($ehvalue<0 || strtoupper($ehvalue)=='OFF') {
9475 $this->HTMLHeaderE = '';
9476 $this->headerDetails['even'] = array();
9477 $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
9478 }
9479 else if ($ehname && $ehvalue>0) {
9480 /*-- HTMLHEADERS-FOOTERS --*/
9481 if (preg_match('/^html_(.*)$/i',$ehname,$n)) {
9482 if (isset($this->pageHTMLheaders[$n[1]])) { $this->HTMLHeaderE = $this->pageHTMLheaders[$n[1]]; }
9483 else { $this->HTMLHeaderE = ''; }
9484 $this->headerDetails['even'] = array();
9485 $resetHTMLHeadersrequired = true;
9486 }
9487 else {
9488 /*-- END HTMLHEADERS-FOOTERS --*/
9489 if (isset($this->pageheaders[$ehname])) { $this->headerDetails['even'] = $this->pageheaders[$ehname]; }
9490 else if ($ehname!='_default') { $this->headerDetails['even'] = array(); }
9491 $this->HTMLHeaderE = '';
9492 /*-- HTMLHEADERS-FOOTERS --*/
9493 $resetHTMLHeadersrequired = false;
9494 }
9495 /*-- END HTMLHEADERS-FOOTERS --*/
9496 }
9497
9498 if ($ofvalue<0 || strtoupper($ofvalue)=='OFF') {
9499 $this->HTMLFooter = '';
9500 $this->footerDetails['odd'] = array();
9501 $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
9502 }
9503 else if ($ofname && $ofvalue>0) {
9504 /*-- HTMLHEADERS-FOOTERS --*/
9505 if (preg_match('/^html_(.*)$/i',$ofname,$n)) {
9506 if (isset($this->pageHTMLfooters[$n[1]])) { $this->HTMLFooter = $this->pageHTMLfooters[$n[1]]; }
9507 else { $this->HTMLFooter = ''; }
9508 $this->footerDetails['odd'] = array();
9509 $resetHTMLHeadersrequired = true;
9510 }
9511 else {
9512 /*-- END HTMLHEADERS-FOOTERS --*/
9513 if (isset($this->pagefooters[$ofname])) { $this->footerDetails['odd'] = $this->pagefooters[$ofname]; }
9514 else if ($ofname!='_default') { $this->footerDetails['odd'] = array(); }
9515 $this->HTMLFooter = '';
9516 /*-- HTMLHEADERS-FOOTERS --*/
9517 $resetHTMLHeadersrequired = true;
9518 }
9519 /*-- END HTMLHEADERS-FOOTERS --*/
9520 }
9521
9522 if ($efvalue<0 || strtoupper($efvalue)=='OFF') {
9523 $this->HTMLFooterE = '';
9524 $this->footerDetails['even'] = array();
9525 $resetHTMLHeadersrequired = true; // *HTMLHEADERS-FOOTERS*
9526 }
9527 else if ($efname && $efvalue>0) {
9528 /*-- HTMLHEADERS-FOOTERS --*/
9529 if (preg_match('/^html_(.*)$/i',$efname,$n)) {
9530 if (isset($this->pageHTMLfooters[$n[1]])) { $this->HTMLFooterE = $this->pageHTMLfooters[$n[1]]; }
9531 else { $this->HTMLFooterE = ''; }
9532 $this->footerDetails['even'] = array();
9533 $resetHTMLHeadersrequired = true;
9534 }
9535 else {
9536 /*-- END HTMLHEADERS-FOOTERS --*/
9537 if (isset($this->pagefooters[$efname])) { $this->footerDetails['even'] = $this->pagefooters[$efname]; }
9538 else if ($efname!='_default') { $this->footerDetails['even'] = array(); }
9539 $this->HTMLFooterE = '';
9540 /*-- HTMLHEADERS-FOOTERS --*/
9541 $resetHTMLHeadersrequired = true;
9542 }
9543 /*-- END HTMLHEADERS-FOOTERS --*/
9544 }
9545 /*-- HTMLHEADERS-FOOTERS --*/
9546 if ($resetHTMLHeadersrequired) {
9547 $this->SetHTMLHeader($this->HTMLHeader );
9548 $this->SetHTMLHeader($this->HTMLHeaderE ,'E');
9549 $this->SetHTMLFooter($this->HTMLFooter );
9550 $this->SetHTMLFooter($this->HTMLFooterE ,'E');
9551 }
9552 /*-- END HTMLHEADERS-FOOTERS --*/
9553
9554
9555 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
9556 $this->_setAutoHeaderHeight($this->headerDetails['even'], $this->HTMLHeaderE);
9557 $this->_setAutoFooterHeight($this->footerDetails['even'], $this->HTMLFooterE);
9558 }
9559 else { // ODD or DEFAULT
9560 $this->_setAutoHeaderHeight($this->headerDetails['odd'], $this->HTMLHeader);
9561 $this->_setAutoFooterHeight($this->footerDetails['odd'], $this->HTMLFooter);
9562 }
9563 // Reset column top margin
9564 $this->y0 = $this->tMargin;
9565
9566 $this->x=$this->lMargin;
9567 $this->y=$this->tMargin;
9568 }
9569
9570
9571
9572 function _setAutoHeaderHeight(&$det, &$htmlh) {
9573 if ($this->setAutoTopMargin=='pad') {
9574 if ($htmlh['h']) { $h = $htmlh['h']; }
9575 else if ($det) { $h = $this->_getHFHeight($det,'H'); }
9576 else { $h = 0; }
9577 $this->tMargin = $this->margin_header + $h + $this->orig_tMargin;
9578 }
9579 else if ($this->setAutoTopMargin=='stretch') {
9580 if ($htmlh['h']) { $h = $htmlh['h']; }
9581 else if ($det) { $h = $this->_getHFHeight($det,'H'); }
9582 else { $h = 0; }
9583 $this->tMargin = max($this->orig_tMargin, $this->margin_header + $h + $this->autoMarginPadding);
9584 }
9585 }
9586
9587
9588 function _setAutoFooterHeight(&$det, &$htmlf) {
9589 if ($this->setAutoBottomMargin=='pad') {
9590 if ($htmlf['h']) { $h = $htmlf['h']; }
9591 else if ($det) { $h = $this->_getHFHeight($det,'F'); }
9592 else { $h = 0; }
9593 $this->bMargin = $this->margin_footer + $h + $this->orig_bMargin;
9594 $this->PageBreakTrigger=$this->h-$this->bMargin ;
9595 }
9596 else if ($this->setAutoBottomMargin=='stretch') {
9597 if ($htmlf['h']) { $h = $htmlf['h']; }
9598 else if ($det) { $h = $this->_getHFHeight($det,'F'); }
9599 else { $h = 0; }
9600 $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $h + $this->autoMarginPadding);
9601 $this->PageBreakTrigger=$this->h-$this->bMargin ;
9602 }
9603 }
9604
9605 function _getHFHeight(&$det,$end) {
9606 $h = 0;
9607 if(count($det)) {
9608 foreach(array('L','C','R') AS $pos) {
9609 if (isset($det[$pos]['content']) && $det[$pos]['content']) {
9610 if (isset($det[$pos]['font-size']) && $det[$pos]['font-size']) { $hfsz = $det[$pos]['font-size']; }
9611 else { $hfsz = $this->default_font_size; }
9612 $h = max($h,$hfsz/_MPDFK);
9613 }
9614 }
9615 if ($det['line'] && $end=='H') { $h += $h/_MPDFK*$this->header_line_spacing; }
9616 else if ($det['line'] && $end=='F') { $h += $h/_MPDFK*$this->footer_line_spacing; }
9617 }
9618 return $h;
9619 }
9620
9621
9622 function _endpage() {
9623 /*-- CSS-IMAGE-FLOAT --*/
9624 $this->printfloatbuffer();
9625 /*-- END CSS-IMAGE-FLOAT --*/
9626
9627 if($this->visibility!='visible')
9628 $this->SetVisibility('visible');
9629 $this->EndLayer(); // mPDF 5.6.01
9630 //End of page contents
9631 $this->state=1;
9632 }
9633
9634 function _newobj($obj_id=false,$onlynewobj=false) {
9635 if (!$obj_id) {
9636 $obj_id = ++$this->n;
9637 }
9638 //Begin a new object
9639 if (!$onlynewobj) {
9640 $this->offsets[$obj_id] = strlen($this->buffer);
9641 $this->_out($obj_id.' 0 obj');
9642 $this->_current_obj_id = $obj_id; // for later use with encryption
9643 }
9644 }
9645
9646 function _dounderline($x,$y,$txt) {
9647 // Now print line exactly where $y secifies - called from Text() and Cell() - adjust position there
9648 // WORD SPACING
9649 $w =($this->GetStringWidth($txt)*_MPDFK) + ($this->charspacing * mb_strlen( $txt, $this->mb_enc ))
9650 + ( $this->ws * mb_substr_count( $txt, ' ', $this->mb_enc ));
9651 //Draw a line
9652 return sprintf('%.3F %.3F m %.3F %.3F l S',$x*_MPDFK,($this->h-$y)*_MPDFK,($x*_MPDFK)+$w,($this->h-$y)*_MPDFK);
9653 }
9654
9655
9656 function _imageError($file, $firsttime, $msg) {
9657 // Save re-trying image URL's which have already failed
9658 $this->failedimages[$file] = true;
9659 if ($firsttime && ($this->showImageErrors || $this->debug)) {
9660 $this->Error("IMAGE Error (".$file."): ".$msg);
9661 }
9662 return false;
9663 }
9664
9665
9666 function _getImage(&$file, $firsttime=true, $allowvector=true, $orig_srcpath=false) {
9667 // firsttime i.e. whether to add to this->images - use false when calling iteratively
9668 // Image Data passed directly as var:varname
9669 if (preg_match('/var:\s*(.*)/',$file, $v)) {
9670 $data = $this->$v[1];
9671 $file = md5($data);
9672 }
9673 // mPDF 5.5.13
9674 if (preg_match('/data:image\/(gif|jpeg|png);base64,(.*)/',$file, $v)) {
9675 $type = $v[1];
9676 $data = base64_decode($v[2]);
9677 $file = md5($data);
9678 }
9679
9680 // mPDF 5.6.02
9681 if ($firsttime && $file && substr($file,0,5)!='data:') { $file = urlencode_part($file); }
9682 if ($firsttime && $orig_srcpath && substr($orig_srcpath,0,5)!='data:') { $orig_srcpath = urlencode_part($orig_srcpath); }
9683
9684 $ppUx = 0;
9685 if ($orig_srcpath && isset($this->images[$orig_srcpath])) { $file=$orig_srcpath; return $this->images[$orig_srcpath]; }
9686 if (isset($this->images[$file])) { return $this->images[$file]; }
9687 else if ($orig_srcpath && isset($this->formobjects[$orig_srcpath])) { $file=$orig_srcpath; return $this->formobjects[$file]; }
9688 else if (isset($this->formobjects[$file])) { return $this->formobjects[$file]; }
9689 // Save re-trying image URL's which have already failed
9690 else if ($firsttime && isset($this->failedimages[$file])) { return $this->_imageError($file, $firsttime, ''); }
9691 if (empty($data)) {
9692 $type = '';
9693 $data = '';
9694
9695 if ($orig_srcpath && $this->basepathIsLocal && $check = @fopen($orig_srcpath,"rb")) {
9696 fclose($check);
9697 $file=$orig_srcpath;
9698 $data = file_get_contents($file);
9699 $type = $this->_imageTypeFromString($data);
9700 }
9701 if (!$data && $check = @fopen($file,"rb")) {
9702 fclose($check);
9703 $data = file_get_contents($file);
9704 $type = $this->_imageTypeFromString($data);
9705 }
9706 if ((!$data || !$type) && !ini_get('allow_url_fopen') ) { // only worth trying if remote file and !ini_get('allow_url_fopen')
9707 $this->file_get_contents_by_socket($file, $data); // needs full url?? even on local (never needed for local)
9708 if ($data) { $type = $this->_imageTypeFromString($data); }
9709 }
9710 if ((!$data || !$type) && !ini_get('allow_url_fopen') && function_exists("curl_init")) {
9711 $this->file_get_contents_by_curl($file, $data); // needs full url?? even on local (never needed for local)
9712 if ($data) { $type = $this->_imageTypeFromString($data); }
9713 }
9714
9715 }
9716 if (!$data) { return $this->_imageError($file, $firsttime, 'Could not find image file'); }
9717 if (empty($type)) { $type = $this->_imageTypeFromString($data); }
9718 if (($type == 'wmf' || $type == 'svg') && !$allowvector) { return $this->_imageError($file, $firsttime, 'WMF or SVG image file not supported in this context'); }
9719
9720 // SVG
9721 if ($type == 'svg') {
9722 if (!class_exists('SVG', false)) { include(_MPDF_PATH .'classes/svg.php'); }
9723 $svg = new SVG($this);
9724 $family=$this->FontFamily;
9725 $style=$this->FontStyle;
9726 $size=$this->FontSizePt;
9727 $info = $svg->ImageSVG($data);
9728 //Restore font
9729 if($family) $this->SetFont($family,$style,$size,false);
9730 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing SVG file'); }
9731 $info['type']='svg';
9732 $info['i']=count($this->formobjects)+1;
9733 $this->formobjects[$file]=$info;
9734 return $info;
9735 }
9736
9737 // JPEG
9738 if ($type == 'jpeg' || $type == 'jpg') {
9739 $hdr = $this->_jpgHeaderFromString($data);
9740 if (!$hdr) { return $this->_imageError($file, $firsttime, 'Error parsing JPG header'); }
9741 $a = $this->_jpgDataFromHeader($hdr);
9742 $j = strpos($data,'JFIF');
9743 if ($j) {
9744 //Read resolution
9745 $unitSp=ord(substr($data,($j+7),1));
9746 if ($unitSp > 0) {
9747 $ppUx=$this->_twobytes2int(substr($data,($j+8),2)); // horizontal pixels per meter, usually set to zero
9748 if ($unitSp == 2) { // = dots per cm (if == 1 set as dpi)
9749 $ppUx=round($ppUx/10 *25.4);
9750 }
9751 }
9752 }
9753 if ($a[2] == 'DeviceCMYK' && (($this->PDFA && $this->restrictColorSpace!=3) || $this->restrictColorSpace==2)) {
9754 // convert to RGB image
9755 if (!function_exists("gd_info")) { $this->Error("JPG image may not use CMYK color space (".$file.")."); }
9756 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.)"; }
9757 $im = @imagecreatefromstring($data);
9758 if ($im) {
9759 $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
9760 imageinterlace($im, false);
9761 $check = @imagepng($im, $tempfile);
9762 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse JPG(CMYK) image'); }
9763 $info = $this->_getImage($tempfile, false);
9764 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse JPG(CMYK) image'); }
9765 imagedestroy($im);
9766 unlink($tempfile);
9767 $info['type']='jpg';
9768 if ($firsttime) {
9769 $info['i']=count($this->images)+1;
9770 $this->images[$file]=$info;
9771 }
9772 return $info;
9773 }
9774 else { return $this->_imageError($file, $firsttime, 'Error creating GD image file from JPG(CMYK) image'); }
9775 }
9776 else if ($a[2] == 'DeviceRGB' && ($this->PDFX || $this->restrictColorSpace==3)) {
9777 // Convert to CMYK image stream - nominally returned as type='png'
9778 $info = $this->_convImage($data, $a[2], 'DeviceCMYK', $a[0], $a[1], $ppUx, false);
9779 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.)"; }
9780 }
9781 else if (($a[2] == 'DeviceRGB' || $a[2] == 'DeviceCMYK') && $this->restrictColorSpace==1) {
9782 // Convert to Grayscale image stream - nominally returned as type='png'
9783 $info = $this->_convImage($data, $a[2], 'DeviceGray', $a[0], $a[1], $ppUx, false);
9784 }
9785 else {
9786 $info = array('w'=>$a[0],'h'=>$a[1],'cs'=>$a[2],'bpc'=>$a[3],'f'=>'DCTDecode','data'=>$data, 'type'=>'jpg');
9787 if ($ppUx) { $info['set-dpi'] = $ppUx; }
9788 }
9789 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing or converting JPG image'); }
9790
9791 if ($firsttime) {
9792 $info['i']=count($this->images)+1;
9793 $this->images[$file]=$info;
9794 }
9795 return $info;
9796 }
9797
9798 // PNG
9799 else if ($type == 'png') {
9800 //Check signature
9801 if(substr($data,0,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
9802 return $this->_imageError($file, $firsttime, 'Error parsing PNG identifier');
9803 }
9804 //Read header chunk
9805 if(substr($data,12,4)!='IHDR') {
9806 return $this->_imageError($file, $firsttime, 'Incorrect PNG file (no IHDR block found)');
9807 }
9808
9809 $w=$this->_fourbytes2int(substr($data,16,4));
9810 $h=$this->_fourbytes2int(substr($data,20,4));
9811 $bpc=ord(substr($data,24,1));
9812 $errpng = false;
9813 $pngalpha = false;
9814 if($bpc>8) { $errpng = 'not 8-bit depth'; }
9815 $ct=ord(substr($data,25,1));
9816 if($ct==0) { $colspace='DeviceGray'; }
9817 elseif($ct==2) { $colspace='DeviceRGB'; }
9818 elseif($ct==3) { $colspace='Indexed'; }
9819 elseif($ct==4) { $colspace='DeviceGray'; $errpng = 'alpha channel'; $pngalpha = true; }
9820 else { $colspace='DeviceRGB'; $errpng = 'alpha channel'; $pngalpha = true; }
9821 if(ord(substr($data,26,1))!=0) { $errpng = 'compression method'; }
9822 if(ord(substr($data,27,1))!=0) { $errpng = 'filter method'; }
9823 if(ord(substr($data,28,1))!=0) { $errpng = 'interlaced file'; }
9824 $j = strpos($data,'pHYs');
9825 if ($j) {
9826 //Read resolution
9827 $unitSp=ord(substr($data,($j+12),1));
9828 if ($unitSp == 1) {
9829 $ppUx=$this->_fourbytes2int(substr($data,($j+4),4)); // horizontal pixels per meter, usually set to zero
9830 $ppUx=round($ppUx/1000 *25.4);
9831 }
9832 }
9833 if (($colspace == 'DeviceRGB' || $colspace == 'Indexed') && ($this->PDFX || $this->restrictColorSpace==3)) {
9834 // Convert to CMYK image stream - nominally returned as type='png'
9835 $info = $this->_convImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha);
9836 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.)"; }
9837 }
9838 else if (($colspace == 'DeviceRGB' || $colspace == 'Indexed') && $this->restrictColorSpace==1) {
9839 // Convert to Grayscale image stream - nominally returned as type='png'
9840 $info = $this->_convImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha);
9841 }
9842 else if (($this->PDFA || $this->PDFX) && $pngalpha) {
9843 // Remove alpha channel
9844 if ($this->restrictColorSpace==1) { // Grayscale
9845 $info = $this->_convImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha);
9846 }
9847 else if ($this->restrictColorSpace==3) { // CMYK
9848 $info = $this->_convImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha);
9849 }
9850 else if ($this->PDFA ) { // RGB
9851 $info = $this->_convImage($data, $colspace, 'DeviceRGB', $w, $h, $ppUx, $pngalpha);
9852 }
9853 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.)"; }
9854 }
9855 else if ($errpng || $pngalpha) {
9856 if (function_exists('gd_info')) { $gd = gd_info(); }
9857 else {$gd = array(); }
9858 if (!isset($gd['PNG Support'])) { return $this->_imageError($file, $firsttime, 'GD library required for PNG image ('.$errpng.')'); }
9859 $im = imagecreatefromstring($data);
9860 if (!$im) { return $this->_imageError($file, $firsttime, 'Error creating GD image from PNG file ('.$errpng.')'); }
9861 $w = imagesx($im);
9862 $h = imagesy($im);
9863 if ($im) {
9864 $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
9865 // Alpha channel set
9866 if ($pngalpha) {
9867 if ($this->PDFA) { $this->Error("PDFA1-b does not permit images with alpha channel transparency (".$file.")."); }
9868 $imgalpha = imagecreate($w, $h);
9869 // generate gray scale pallete
9870 for ($c = 0; $c < 256; ++$c) { ImageColorAllocate($imgalpha, $c, $c, $c); }
9871 // extract alpha channel
9872 $gammacorr = 2.2; // gamma correction
9873 for ($xpx = 0; $xpx < $w; ++$xpx) {
9874 for ($ypx = 0; $ypx < $h; ++$ypx) {
9875 //$colorindex = imagecolorat($im, $xpx, $ypx);
9876 //$col = imagecolorsforindex($im, $colorindex);
9877 //$gamma2 = (pow((((127 - $col['alpha']) * 255 / 127) / 255), $gammacorr) * 255);
9878 $alpha = (imagecolorat($im, $xpx, $ypx) & 0x7F000000) >> 24;
9879 if ($alpha < 127) {
9880 if ($alpha==0) { $gamma = 255; }
9881 else
9882 $gamma = (pow((((127 - $alpha) * 255 / 127) / 255), $gammacorr) * 255);
9883 imagesetpixel($imgalpha, $xpx, $ypx, $gamma);
9884 }
9885 }
9886 }
9887 // create temp alpha file
9888 $tempfile_alpha = _MPDF_TEMP_PATH.'_tempMskPNG'.RAND(1,10000).'.png';
9889 if (!is_writable($tempfile_alpha)) {
9890 ob_start();
9891 $check = @imagepng($imgalpha);
9892 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
9893 imagedestroy($imgalpha);
9894 $this->_tempimg = ob_get_contents();
9895 $this->_tempimglnk = 'var:_tempimg';
9896 ob_end_clean();
9897 // extract image without alpha channel
9898 $imgplain = imagecreatetruecolor($w, $h);
9899 imagecopy($imgplain, $im, 0, 0, 0, 0, $w, $h);
9900 // create temp image file
9901 $minfo = $this->_getImage($this->_tempimglnk, false);
9902 if (!$minfo) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
9903 ob_start();
9904 $check = @imagepng($imgplain);
9905 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
9906 $this->_tempimg = ob_get_contents();
9907 $this->_tempimglnk = 'var:_tempimg';
9908 ob_end_clean();
9909 $info = $this->_getImage($this->_tempimglnk, false);
9910 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
9911 imagedestroy($imgplain);
9912 $imgmask = count($this->images)+1;
9913 $minfo['cs'] = 'DeviceGray';
9914 $minfo['i']=$imgmask ;
9915 $this->images[$tempfile_alpha] = $minfo;
9916
9917 }
9918 else {
9919 $check = @imagepng($imgalpha, $tempfile_alpha);
9920 if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile_alpha.') parsing PNG image with alpha channel ('.$errpng.')'); }
9921 imagedestroy($imgalpha);
9922
9923 // extract image without alpha channel
9924 $imgplain = imagecreatetruecolor($w, $h);
9925 imagecopy($imgplain, $im, 0, 0, 0, 0, $w, $h);
9926
9927 // create temp image file
9928 $check = @imagepng($imgplain, $tempfile);
9929 if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile.') parsing PNG image with alpha channel ('.$errpng.')'); }
9930 imagedestroy($imgplain);
9931 // embed mask image
9932 $minfo = $this->_getImage($tempfile_alpha, false);
9933 unlink($tempfile_alpha);
9934 if (!$minfo) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile_alpha.') created with GD library to parse PNG image'); }
9935 $imgmask = count($this->images)+1;
9936 $minfo['cs'] = 'DeviceGray';
9937 $minfo['i']=$imgmask ;
9938 $this->images[$tempfile_alpha] = $minfo;
9939 // embed image, masked with previously embedded mask
9940 $info = $this->_getImage($tempfile, false);
9941 unlink($tempfile);
9942 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse PNG image'); }
9943
9944 }
9945 $info['masked'] = $imgmask;
9946 if ($ppUx) { $info['set-dpi'] = $ppUx; }
9947 $info['type']='png';
9948 if ($firsttime) {
9949 $info['i']=count($this->images)+1;
9950 $this->images[$file]=$info;
9951 }
9952 return $info;
9953 }
9954 else { // No alpha/transparency set
9955 imagealphablending($im, false);
9956 imagesavealpha($im, false);
9957 imageinterlace($im, false);
9958 if (!is_writable($tempfile)) {
9959 ob_start();
9960 $check = @imagepng($im);
9961 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse PNG image'); }
9962 $this->_tempimg = ob_get_contents();
9963 $this->_tempimglnk = 'var:_tempimg';
9964 ob_end_clean();
9965 $info = $this->_getImage($this->_tempimglnk, false);
9966 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse PNG image'); }
9967 imagedestroy($im);
9968 }
9969 else {
9970 $check = @imagepng($im, $tempfile );
9971 if (!$check) { return $this->_imageError($file, $firsttime, 'Failed to create temporary image file ('.$tempfile.') parsing PNG image ('.$errpng.')'); }
9972 imagedestroy($im);
9973 $info = $this->_getImage($tempfile, false) ;
9974 unlink($tempfile );
9975 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse PNG image'); }
9976 }
9977 if ($ppUx) { $info['set-dpi'] = $ppUx; }
9978 $info['type']='png';
9979 if ($firsttime) {
9980 $info['i']=count($this->images)+1;
9981 $this->images[$file]=$info;
9982 }
9983 return $info;
9984 }
9985 }
9986 }
9987
9988 else {
9989 $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
9990 //Scan chunks looking for palette, transparency and image data
9991 $pal='';
9992 $trns='';
9993 $pngdata='';
9994 $p = 33;
9995 do {
9996 $n=$this->_fourbytes2int(substr($data,$p,4)); $p += 4;
9997 $type=substr($data,$p,4); $p += 4;
9998 if($type=='PLTE') {
9999 //Read palette
10000 $pal=substr($data,$p,$n); $p += $n;
10001 $p += 4;
10002 }
10003 elseif($type=='tRNS') {
10004 //Read transparency info
10005 $t=substr($data,$p,$n); $p += $n;
10006 if($ct==0) $trns=array(ord(substr($t,1,1)));
10007 elseif($ct==2) $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
10008 else
10009 {
10010 $pos=strpos($t,chr(0));
10011 if(is_int($pos)) $trns=array($pos);
10012 }
10013 $p += 4;
10014 }
10015 elseif($type=='IDAT') {
10016 $pngdata.=substr($data,$p,$n); $p += $n;
10017 $p += 4;
10018 }
10019 elseif($type=='IEND') { break; }
10020 else if (preg_match('/[a-zA-Z]{4}/',$type)) { $p += $n+4; }
10021 else { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data'); }
10022 }
10023 while($n);
10024 if (!$pngdata) { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data - no IDAT data found'); }
10025 if($colspace=='Indexed' and empty($pal)) { return $this->_imageError($file, $firsttime, 'Error parsing PNG image data - missing colour palette'); }
10026 $info = array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$pngdata);
10027 $info['type']='png';
10028 if ($ppUx) { $info['set-dpi'] = $ppUx; }
10029 }
10030
10031 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing or converting PNG image'); }
10032
10033 if ($firsttime) {
10034 $info['i']=count($this->images)+1;
10035 $this->images[$file]=$info;
10036 }
10037 return $info;
10038 }
10039
10040 // GIF
10041 else if ($type == 'gif') {
10042 if (function_exists('gd_info')) { $gd = gd_info(); }
10043 else {$gd = array(); }
10044 if (isset($gd['GIF Read Support']) && $gd['GIF Read Support']) {
10045 $im = @imagecreatefromstring($data);
10046 if ($im) {
10047 $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
10048 imagealphablending($im, false);
10049 imagesavealpha($im, false);
10050 imageinterlace($im, false);
10051 if (!is_writable($tempfile)) {
10052 ob_start();
10053 $check = @imagepng($im);
10054 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse GIF image'); }
10055 $this->_tempimg = ob_get_contents();
10056 $this->_tempimglnk = 'var:_tempimg';
10057 ob_end_clean();
10058 $info = $this->_getImage($this->_tempimglnk, false);
10059 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file image object created with GD library to parse GIF image'); }
10060 imagedestroy($im);
10061 }
10062 else {
10063 $check = @imagepng($im, $tempfile);
10064 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse GIF image'); }
10065 $info = $this->_getImage($tempfile, false);
10066 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse GIF image'); }
10067 imagedestroy($im);
10068 unlink($tempfile);
10069 }
10070 $info['type']='gif';
10071 if ($firsttime) {
10072 $info['i']=count($this->images)+1;
10073 $this->images[$file]=$info;
10074 }
10075 return $info;
10076 }
10077 else { return $this->_imageError($file, $firsttime, 'Error creating GD image file from GIF image'); }
10078 }
10079
10080 if (!class_exists('gif', false)) {
10081 include_once(_MPDF_PATH.'classes/gif.php');
10082 }
10083 $gif=new CGIF();
10084
10085 $h=0;
10086 $w=0;
10087 $gif->loadFile($data, 0);
10088
10089 if(isset($gif->m_img->m_gih->m_bLocalClr) && $gif->m_img->m_gih->m_bLocalClr) {
10090 $nColors = $gif->m_img->m_gih->m_nTableSize;
10091 $pal = $gif->m_img->m_gih->m_colorTable->toString();
10092 if($bgColor != -1) {
10093 $bgColor = $gif->m_img->m_gih->m_colorTable->colorIndex($bgColor);
10094 }
10095 $colspace='Indexed';
10096 } elseif(isset($gif->m_gfh->m_bGlobalClr) && $gif->m_gfh->m_bGlobalClr) {
10097 $nColors = $gif->m_gfh->m_nTableSize;
10098 $pal = $gif->m_gfh->m_colorTable->toString();
10099 if((isset($bgColor)) and $bgColor != -1) {
10100 $bgColor = $gif->m_gfh->m_colorTable->colorIndex($bgColor);
10101 }
10102 $colspace='Indexed';
10103 } else {
10104 $nColors = 0;
10105 $bgColor = -1;
10106 $colspace='DeviceGray';
10107 $pal='';
10108 }
10109
10110 $trns='';
10111 if(isset($gif->m_img->m_bTrans) && $gif->m_img->m_bTrans && ($nColors > 0)) {
10112 $trns=array($gif->m_img->m_nTrans);
10113 }
10114 $gifdata=$gif->m_img->m_data;
10115 $w=$gif->m_gfh->m_nWidth;
10116 $h=$gif->m_gfh->m_nHeight;
10117 $gif->ClearData();
10118
10119 if($colspace=='Indexed' and empty($pal)) {
10120 return $this->_imageError($file, $firsttime, 'Error parsing GIF image - missing colour palette');
10121 }
10122 if ($this->compress) {
10123 $gifdata=gzcompress($gifdata);
10124 $info = array( 'w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>8, 'f'=>'FlateDecode', 'pal'=>$pal, 'trns'=>$trns, 'data'=>$gifdata);
10125 }
10126 else {
10127 $info = array( 'w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>8, 'pal'=>$pal, 'trns'=>$trns, 'data'=>$gifdata);
10128 }
10129 $info['type']='gif';
10130 if ($firsttime) {
10131 $info['i']=count($this->images)+1;
10132 $this->images[$file]=$info;
10133 }
10134 return $info;
10135 }
10136
10137 /*-- IMAGES-BMP --*/
10138 // BMP (Windows Bitmap)
10139 else if ($type == 'bmp') {
10140 if (!class_exists('bmp', false)) { include(_MPDF_PATH.'classes/bmp.php'); }
10141 if (empty($this->bmp)) { $this->bmp = new bmp($this); }
10142 $info = $this->bmp->_getBMPimage($data, $file);
10143 if (isset($info['error'])) {
10144 return $this->_imageError($file, $firsttime, $info['error']);
10145 }
10146 if ($firsttime) {
10147 $info['i']=count($this->images)+1;
10148 $this->images[$file]=$info;
10149 }
10150 return $info;
10151 }
10152 /*-- END IMAGES-BMP --*/
10153 /*-- IMAGES-WMF --*/
10154 // WMF
10155 else if ($type == 'wmf') {
10156 if (!class_exists('wmf', false)) { include(_MPDF_PATH.'classes/wmf.php'); }
10157 if (empty($this->wmf)) { $this->wmf = new wmf($this); }
10158 $wmfres = $this->wmf->_getWMFimage($data);
10159 if ($wmfres[0]==0) {
10160 if ($wmfres[1]) { return $this->_imageError($file, $firsttime, $wmfres[1]); }
10161 return $this->_imageError($file, $firsttime, 'Error parsing WMF image');
10162 }
10163 $info = array('x'=>$wmfres[2][0],'y'=>$wmfres[2][1],'w'=>$wmfres[3][0],'h'=>$wmfres[3][1],'data'=>$wmfres[1]);
10164 $info['i']=count($this->formobjects)+1;
10165 $info['type']='wmf';
10166 $this->formobjects[$file]=$info;
10167 return $info;
10168 }
10169 /*-- END IMAGES-WMF --*/
10170
10171 // UNKNOWN TYPE - try GD imagecreatefromstring
10172 else {
10173 if (function_exists('gd_info')) { $gd = gd_info(); }
10174 else {$gd = array(); }
10175 if (isset($gd['PNG Support']) && $gd['PNG Support']) {
10176 $im = @imagecreatefromstring($data);
10177 if (!$im) { return $this->_imageError($file, $firsttime, 'Error parsing image file - image type not recognised, and not supported by GD imagecreate'); }
10178 $tempfile = _MPDF_TEMP_PATH.'_tempImgPNG'.RAND(1,10000).'.png';
10179 imagealphablending($im, false);
10180 imagesavealpha($im, false);
10181 imageinterlace($im, false);
10182 $check = @imagepng($im, $tempfile);
10183 if (!$check) { return $this->_imageError($file, $firsttime, 'Error creating temporary file ('.$tempfile.') whilst using GD library to parse unknown image type'); }
10184 $info = $this->_getImage($tempfile, false);
10185 imagedestroy($im);
10186 unlink($tempfile);
10187 if (!$info) { return $this->_imageError($file, $firsttime, 'Error parsing temporary file ('.$tempfile.') created with GD library to parse unknown image type'); }
10188 $info['type']='png';
10189 if ($firsttime) {
10190 $info['i']=count($this->images)+1;
10191 $this->images[$file]=$info;
10192 }
10193 return $info;
10194 }
10195 }
10196
10197 return $this->_imageError($file, $firsttime, 'Error parsing image file - image type not recognised');
10198 }
10199 //==============================================================
10200 function _convImage(&$data, $colspace, $targetcs, $w, $h, $dpi, $mask) {
10201 if ($this->PDFA || $this->PDFX) { $mask=false; }
10202 $im = @imagecreatefromstring($data);
10203 $info = array();
10204 if ($im) {
10205 $imgdata = '';
10206 $mimgdata = '';
10207 $minfo = array();
10208 //Read transparency info
10209 $trns=array();
10210 $trnsrgb = false;
10211 if (!$this->PDFA && !$this->PDFX) {
10212 $p = strpos($data,'tRNS');
10213 if ($p) {
10214 $n=$this->_fourbytes2int(substr($data,($p-4),4));
10215 $t = substr($data,($p+4),$n);
10216 if ($colspace=='DeviceGray') {
10217 $trns=array(ord(substr($t,1,1)));
10218 $trnsrgb = array($trns[0],$trns[0],$trns[0]);
10219 }
10220 else if ($colspace=='DeviceRGB') {
10221 $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
10222 $trnsrgb = $trns;
10223 if ($targetcs=='DeviceCMYK') {
10224 $col = $this->rgb2cmyk(array(3,$trns[0],$trns[1],$trns[2]));
10225 $c1 = intval($col[1]*2.55);
10226 $c2 = intval($col[2]*2.55);
10227 $c3 = intval($col[3]*2.55);
10228 $c4 = intval($col[4]*2.55);
10229 $trns = array($c1,$c2,$c3,$c4);
10230 }
10231 else if ($targetcs=='DeviceGray') {
10232 $c = intval(($trns[0] * .21) + ($trns[1] * .71) + ($trns[2] * .07));
10233 $trns = array($c);
10234 }
10235 }
10236 else { // Indexed
10237 $pos = strpos($t,chr(0));
10238 if (is_int($pos)) {
10239 $pal = imagecolorsforindex($im, $pos);
10240 $r = $pal['red'];
10241 $g = $pal['green'];
10242 $b = $pal['blue'];
10243 $trns=array($r,$g,$b); // ****
10244 $trnsrgb = $trns;
10245 if ($targetcs=='DeviceCMYK') {
10246 $col = $this->rgb2cmyk(array(3,$r,$g,$b));
10247 $c1 = intval($col[1]*2.55);
10248 $c2 = intval($col[2]*2.55);
10249 $c3 = intval($col[3]*2.55);
10250 $c4 = intval($col[4]*2.55);
10251 $trns = array($c1,$c2,$c3,$c4);
10252 }
10253 else if ($targetcs=='DeviceGray') {
10254 $c = intval(($r * .21) + ($g * .71) + ($b * .07));
10255 $trns = array($c);
10256 }
10257 }
10258 }
10259 }
10260 }
10261 for ($i = 0; $i < $h; $i++) {
10262 for ($j = 0; $j < $w; $j++) {
10263 $rgb = imagecolorat($im, $j, $i);
10264 $r = ($rgb >> 16) & 0xFF;
10265 $g = ($rgb >> 8) & 0xFF;
10266 $b = $rgb & 0xFF;
10267 if ($colspace=='Indexed') {
10268 $pal = imagecolorsforindex($im, $rgb);
10269 $r = $pal['red'];
10270 $g = $pal['green'];
10271 $b = $pal['blue'];
10272 }
10273
10274 if ($targetcs=='DeviceCMYK') {
10275 $col = $this->rgb2cmyk(array(3,$r,$g,$b));
10276 $c1 = intval($col[1]*2.55);
10277 $c2 = intval($col[2]*2.55);
10278 $c3 = intval($col[3]*2.55);
10279 $c4 = intval($col[4]*2.55);
10280 if ($trnsrgb) {
10281 // original pixel was not set as transparent but processed color does match
10282 if ($trnsrgb!=array($r,$g,$b) && $trns==array($c1,$c2,$c3,$c4)) {
10283 if ($c4==0) { $c4=1; } else { $c4--; }
10284 }
10285 }
10286 $imgdata .= chr($c1).chr($c2).chr($c3).chr($c4);
10287 }
10288 else if ($targetcs=='DeviceGray') {
10289 $c = intval(($r * .21) + ($g * .71) + ($b * .07));
10290 if ($trnsrgb) {
10291 // original pixel was not set as transparent but processed color does match
10292 if ($trnsrgb!=array($r,$g,$b) && $trns==array($c)) {
10293 if ($c==0) { $c=1; } else { $c--; }
10294 }
10295 }
10296 $imgdata .= chr($c);
10297 }
10298 else if ($targetcs=='DeviceRGB') {
10299 $imgdata .= chr($r).chr($g).chr($b);
10300 }
10301 if ($mask) {
10302 $col = imagecolorsforindex($im, $rgb);
10303 $gammacorr = 2.2; // gamma correction
10304 $gamma = intval((pow((((127 - $col['alpha']) * 255 / 127) / 255), $gammacorr) * 255));
10305 $mimgdata .= chr($gamma);
10306 }
10307 }
10308 }
10309
10310 if ($targetcs=='DeviceGray') { $ncols = 1; }
10311 else if ($targetcs=='DeviceRGB') { $ncols = 3; }
10312 else if ($targetcs=='DeviceCMYK') { $ncols = 4; }
10313
10314 $imgdata = gzcompress($imgdata);
10315 $info = array('w'=>$w,'h'=>$h,'cs'=>$targetcs,'bpc'=>8,'f'=>'FlateDecode','data'=>$imgdata, 'type'=>'png',
10316 'parms'=>'/DecodeParms <</Colors '.$ncols.' /BitsPerComponent 8 /Columns '.$w.'>>');
10317 if ($dpi) { $info['set-dpi'] = $dpi; }
10318 if ($mask) {
10319 $mimgdata = gzcompress($mimgdata);
10320 $minfo = array('w'=>$w,'h'=>$h,'cs'=>'DeviceGray','bpc'=>8,'f'=>'FlateDecode','data'=>$mimgdata, 'type'=>'png',
10321 'parms'=>'/DecodeParms <</Colors '.$ncols.' /BitsPerComponent 8 /Columns '.$w.'>>');
10322 if ($dpi) { $minfo['set-dpi'] = $dpi; }
10323 $tempfile = '_tempImgPNG'.RAND(1,10000).'.png';
10324 $imgmask = count($this->images)+1;
10325 $minfo['i']=$imgmask ;
10326 $this->images[$tempfile] = $minfo;
10327 $info['masked'] = $imgmask;
10328 }
10329 else if ($trns) { $info['trns'] = $trns; }
10330 imagedestroy($im);
10331 }
10332 return $info;
10333 }
10334
10335
10336
10337
10338 function _fourbytes2int($s) {
10339 //Read a 4-byte integer from string
10340 return (ord($s[0])<<24) + (ord($s[1])<<16) + (ord($s[2])<<8) + ord($s[3]);
10341 }
10342
10343 function _twobytes2int($s) {
10344 //Read a 2-byte integer from string
10345 return (ord(substr($s, 0, 1))<<8) + ord(substr($s, 1, 1));
10346 }
10347
10348 function _jpgHeaderFromString(&$data) {
10349 $p = 4;
10350 $p += $this->_twobytes2int(substr($data, $p, 2)); // Length of initial marker block
10351 $marker = substr($data, $p, 2);
10352 while($marker != chr(255).chr(192) && $marker != chr(255).chr(194) && $p<strlen($data)) {
10353 // Start of frame marker (FFC0) or (FFC2) mPDF 4.4.004
10354 $p += ($this->_twobytes2int(substr($data, $p+2, 2))) + 2; // Length of marker block
10355 $marker = substr($data, $p, 2);
10356 }
10357 if ($marker != chr(255).chr(192) && $marker != chr(255).chr(194)) { return false; }
10358 return substr($data, $p+2, 10);
10359 }
10360
10361 function _jpgDataFromHeader($hdr) {
10362 $bpc = ord(substr($hdr, 2, 1));
10363 if (!$bpc) { $bpc = 8; }
10364 $h = $this->_twobytes2int(substr($hdr, 3, 2));
10365 $w = $this->_twobytes2int(substr($hdr, 5, 2));
10366 $channels = ord(substr($hdr, 7, 1));
10367 if ($channels==3) { $colspace='DeviceRGB'; }
10368 elseif($channels==4) { $colspace='DeviceCMYK'; }
10369 else { $colspace='DeviceGray'; }
10370 return array($w, $h, $colspace, $bpc);
10371 }
10372
10373 function file_get_contents_by_curl($url, &$data) {
10374 $timeout = 5;
10375 $ch = curl_init($url);
10376 curl_setopt($ch, CURLOPT_HEADER, 0);
10377 curl_setopt($ch, CURLOPT_NOBODY, 0);
10378 curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 );
10379 curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , $timeout );
10380 $data = curl_exec($ch);
10381 curl_close($ch);
10382 }
10383
10384
10385 function file_get_contents_by_socket($url, &$data) {
10386 $timeout = 1;
10387 $p = parse_url($url);
10388 $file = $p['path'];
10389 if ($p['query']) { $file .= '?'.$p['query']; }
10390 if(!($fh = @fsockopen($p['host'], 80, $errno, $errstr, $timeout))) { return false; }
10391 $getstring =
10392 "GET ".$file." HTTP/1.0 \r\n" .
10393 "Host: ".$p['host']." \r\n" .
10394 "Connection: close\r\n\r\n";
10395 fwrite($fh, $getstring);
10396 // Get rid of HTTP header
10397 $s = fgets($fh, 1024);
10398 if (!$s) { return false; }
10399 $httpheader .= $s;
10400 while (!feof($fh)) {
10401 $s = fgets($fh, 1024);
10402 if ( $s == "\r\n" ) { break; }
10403 }
10404 $data = '';
10405 while (!feof($fh)) {
10406 $data .= fgets($fh, 1024);
10407 }
10408 fclose($fh);
10409 }
10410
10411 //==============================================================
10412
10413 function _imageTypeFromString(&$data) {
10414 $type = '';
10415 if (substr($data, 6, 4)== 'JFIF' || substr($data, 6, 4)== 'Exif') {
10416 $type = 'jpeg';
10417 }
10418 else if (substr($data, 0, 6)== "GIF87a" || substr($data, 0, 6)== "GIF89a") {
10419 $type = 'gif';
10420 }
10421 else if (substr($data, 0, 8)== chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
10422 $type = 'png';
10423 }
10424 /*-- IMAGES-WMF --*/
10425 else if (substr($data, 0, 4)== chr(215).chr(205).chr(198).chr(154)) {
10426 $type = 'wmf';
10427 }
10428 /*-- END IMAGES-WMF --*/
10429 else if (preg_match('/<svg.*<\/svg>/is',$data)) {
10430 $type = 'svg';
10431 }
10432 // BMP images
10433 else if (substr($data, 0, 2)== "BM") {
10434 $type = 'bmp';
10435 }
10436 return $type;
10437 }
10438 //==============================================================
10439
10440 // Moved outside WMF as also needed for SVG
10441 function _putformobjects() {
10442 reset($this->formobjects);
10443 while(list($file,$info)=each($this->formobjects)) {
10444 $this->_newobj();
10445 $this->formobjects[$file]['n']=$this->n;
10446 $this->_out('<</Type /XObject');
10447 $this->_out('/Subtype /Form');
10448 $this->_out('/Group '.($this->n+1).' 0 R');
10449 $this->_out('/BBox ['.$info['x'].' '.$info['y'].' '.($info['w']+$info['x']).' '.($info['h']+$info['y']).']');
10450 if ($this->compress)
10451 $this->_out('/Filter /FlateDecode');
10452 $data=($this->compress) ? gzcompress($info['data']) : $info['data'];
10453 $this->_out('/Length '.strlen($data).'>>');
10454 $this->_putstream($data);
10455 unset($this->formobjects[$file]['data']);
10456 $this->_out('endobj');
10457 // Required for SVG transparency (opacity) to work
10458 $this->_newobj();
10459 $this->_out('<</Type /Group');
10460 $this->_out('/S /Transparency');
10461 $this->_out('>>');
10462 $this->_out('endobj');
10463 }
10464 }
10465
10466 function _freadint($f)
10467 {
10468 //Read a 4-byte integer from file
10469 $i=ord(fread($f,1))<<24;
10470 $i+=ord(fread($f,1))<<16;
10471 $i+=ord(fread($f,1))<<8;
10472 $i+=ord(fread($f,1));
10473 return $i;
10474 }
10475
10476 function _UTF16BEtextstring($s) {
10477 $s = $this->UTF8ToUTF16BE($s, true);
10478 /*-- ENCRYPTION --*/
10479 if ($this->encrypted) {
10480 $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
10481 }
10482 /*-- END ENCRYPTION --*/
10483 return '('. $this->_escape($s).')';
10484 }
10485
10486 function _textstring($s) {
10487 /*-- ENCRYPTION --*/
10488 if ($this->encrypted) {
10489 $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
10490 }
10491 /*-- END ENCRYPTION --*/
10492 return '('. $this->_escape($s).')';
10493 }
10494
10495
10496 function _escape($s)
10497 {
10498 // the chr(13) substitution fixes the Bugs item #1421290.
10499 return strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r'));
10500 }
10501
10502 function _putstream($s) {
10503 /*-- ENCRYPTION --*/
10504 if ($this->encrypted) {
10505 $s = $this->_RC4($this->_objectkey($this->_current_obj_id), $s);
10506 }
10507 /*-- END ENCRYPTION --*/
10508 $this->_out('stream');
10509 $this->_out($s);
10510 $this->_out('endstream');
10511 }
10512
10513
10514 function _out($s,$ln=true) {
10515 if($this->state==2) {
10516 if ($this->bufferoutput) {
10517 $this->headerbuffer.= $s."\n";
10518 }
10519 /*-- COLUMNS --*/
10520 else if (($this->ColActive) && !$this->processingHeader && !$this->processingFooter) {
10521 // Captures everything in buffer for columns; Almost everything is sent from fn. Cell() except:
10522 // Images sent from Image() or
10523 // later sent as _out($textto) in printbuffer
10524 // Line()
10525 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
10526 $h = ($m[1]/_MPDFK);
10527 // Update/overwrite the lowest bottom of printing y value for a column
10528 $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y+$h;
10529 }
10530 /*-- TABLES --*/
10531 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
10532 $h = ($m[1]/_MPDFK);
10533 // Update/overwrite the lowest bottom of printing y value for a column
10534 $this->ColDetails[$this->CurrCol]['bottom_margin'] = max($this->ColDetails[$this->CurrCol]['bottom_margin'],($this->y+$h));
10535 }
10536 /*-- END TABLES --*/
10537 else { // Td Text Set in Cell()
10538 if (isset($this->ColDetails[$this->CurrCol]['bottom_margin'])) { $h = $this->ColDetails[$this->CurrCol]['bottom_margin'] - $this->y; }
10539 else { $h = 0; }
10540 }
10541 if ($h < 0) { $h = -$h; }
10542 $this->columnbuffer[] = array(
10543 's' => $s, // Text string to output
10544 'col' => $this->CurrCol, // Column when printed
10545 'x' => $this->x, // x when printed
10546 'y' => $this->y, // this->y when printed (after column break)
10547 'h' => $h // actual y at bottom when printed = y+h
10548 );
10549 }
10550 /*-- END COLUMNS --*/
10551 /*-- TABLES --*/
10552 else if ($this->table_rotate && !$this->processingHeader && !$this->processingFooter) {
10553 // Captures eveything in buffer for rotated tables;
10554 $this->tablebuffer .= $s . "\n";
10555 }
10556 /*-- END TABLES --*/
10557 else if ($this->kwt && !$this->processingHeader && !$this->processingFooter) {
10558 // Captures eveything in buffer for keep-with-table (h1-6);
10559 $this->kwt_buffer[] = array(
10560 's' => $s, // Text string to output
10561 'x' => $this->x, // x when printed
10562 'y' => $this->y, // y when printed
10563 );
10564 }
10565 else if (($this->keep_block_together) && !$this->processingHeader && !$this->processingFooter) {
10566 if (!isset($this->ktBlock[$this->page]['bottom_margin'])) {
10567 $this->ktBlock[$this->page]['bottom_margin'] = $this->y;
10568 }
10569
10570 // Captures eveything in buffer;
10571 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
10572 $h = ($m[1]/_MPDFK);
10573 // Update/overwrite the lowest bottom of printing y value for Keep together block
10574 $this->ktBlock[$this->page]['bottom_margin'] = $this->y+$h;
10575 }
10576 else { // Td Text Set in Cell()
10577 if (isset($this->ktBlock[$this->page]['bottom_margin'])) { $h = $this->ktBlock[$this->page]['bottom_margin'] - $this->y; }
10578 else { $h = 0; }
10579 }
10580 if ($h < 0) { $h = -$h; }
10581 $this->divbuffer[] = array(
10582 'page' => $this->page,
10583 's' => $s, // Text string to output
10584 'x' => $this->x, // x when printed
10585 'y' => $this->y, // y when printed (after column break)
10586 'h' => $h // actual y at bottom when printed = y+h
10587 );
10588 }
10589 else {
10590 $this->pages[$this->page] .= $s.($ln == true ? "\n" : '');
10591 }
10592
10593 }
10594 else {
10595 $this->buffer .= $s.($ln == true ? "\n" : '');
10596 }
10597 }
10598
10599 /*-- WATERMARK --*/
10600 // add a watermark
10601 function watermark( $texte, $angle=45, $fontsize=96, $alpha=0.2 ) {
10602 if ($this->PDFA || $this->PDFX) { $this->Error('PDFA and PDFX do not permit transparency, so mPDF does not allow Watermarks!'); }
10603 if (!$this->watermark_font) { $this->watermark_font = $this->default_font; }
10604 $this->SetFont( $this->watermark_font, "B", $fontsize, false ); // Don't output
10605 $texte= $this->purify_utf8_text($texte);
10606 if ($this->text_input_as_HTML) {
10607 $texte= $this->all_entities_to_utf8($texte);
10608 }
10609 if ($this->usingCoreFont) { $texte = mb_convert_encoding($texte,$this->mb_enc,'UTF-8'); }
10610 // DIRECTIONALITY
10611 $this->magic_reverse_dir($texte, true, $this->directionality); // *RTL*
10612 // Font-specific ligature substitution for Indic fonts
10613 if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($texte); // *INDIC*
10614
10615 $this->SetAlpha($alpha);
10616
10617 $this->SetTColor($this->ConvertColor(0));
10618 $szfont = $fontsize;
10619 $loop = 0;
10620 $maxlen = (min($this->w,$this->h) ); // sets max length of text as 7/8 width/height of page
10621 while ( $loop == 0 )
10622 {
10623 $this->SetFont( $this->watermark_font, "B", $szfont, false ); // Don't output
10624 $offset = ((sin(deg2rad($angle))) * ($szfont/_MPDFK));
10625
10626 $strlen = $this->GetStringWidth($texte);
10627 if ( $strlen > $maxlen - $offset )
10628 $szfont --;
10629 else
10630 $loop ++;
10631 }
10632
10633 $this->SetFont( $this->watermark_font, "B", $szfont-0.1, true, true); // Output The -0.1 is because SetFont above is not written to PDF
10634 // Repeating it will not output anything as mPDF thinks it is set
10635 $adj = ((cos(deg2rad($angle))) * ($strlen/2));
10636 $opp = ((sin(deg2rad($angle))) * ($strlen/2));
10637 $wx = ($this->w/2) - $adj + $offset/3;
10638 $wy = ($this->h/2) + $opp;
10639 $this->Rotate($angle,$wx,$wy);
10640 $this->Text($wx,$wy,$texte);
10641 $this->Rotate(0);
10642 $this->SetTColor($this->ConvertColor(0));
10643
10644 $this->SetAlpha(1);
10645
10646 }
10647
10648 function watermarkImg( $src, $alpha=0.2 ) {
10649 if ($this->PDFA || $this->PDFX) { $this->Error('PDFA and PDFX do not permit transparency, so mPDF does not allow Watermarks!'); }
10650 if ($this->watermarkImgBehind) { $this->watermarkImgAlpha = $this->SetAlpha($alpha, 'Normal', true); }
10651 else { $this->SetAlpha($alpha, $this->watermarkImgAlphaBlend); }
10652 $this->Image($src,0,0,0,0,'','', true, true, true);
10653 if (!$this->watermarkImgBehind) { $this->SetAlpha(1); }
10654 }
10655 /*-- END WATERMARK --*/
10656
10657
10658 function Rotate($angle,$x=-1,$y=-1)
10659 {
10660 if($x==-1)
10661 $x=$this->x;
10662 if($y==-1)
10663 $y=$this->y;
10664 if($this->angle!=0)
10665 $this->_out('Q');
10666 $this->angle=$angle;
10667 if($angle!=0)
10668 {
10669 $angle*=M_PI/180;
10670 $c=cos($angle);
10671 $s=sin($angle);
10672 $cx=$x*_MPDFK;
10673 $cy=($this->h-$y)*_MPDFK;
10674 $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));
10675 }
10676 }
10677
10678
10679
10680 function CircularText($x, $y, $r, $text, $align='top', $fontfamily='', $fontsize=0, $fontstyle='', $kerning=120, $fontwidth=100, $divider) { // mPDF 5.5.23
10681 if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
10682 if (empty($this->directw)) { $this->directw = new directw($this); }
10683 $this->directw->CircularText($x, $y, $r, $text, $align, $fontfamily, $fontsize, $fontstyle, $kerning, $fontwidth, $divider); // mPDF 5.5.23
10684 }
10685
10686
10687 // From Invoice
10688 function RoundedRect($x, $y, $w, $h, $r, $style = '')
10689 {
10690 $hp = $this->h;
10691 if($style=='F')
10692 $op='f';
10693 elseif($style=='FD' or $style=='DF')
10694 $op='B';
10695 else
10696 $op='S';
10697 $MyArc = 4/3 * (sqrt(2) - 1);
10698 $this->_out(sprintf('%.3F %.3F m',($x+$r)*_MPDFK,($hp-$y)*_MPDFK ));
10699 $xc = $x+$w-$r ;
10700 $yc = $y+$r;
10701 $this->_out(sprintf('%.3F %.3F l', $xc*_MPDFK,($hp-$y)*_MPDFK ));
10702
10703 $this->_Arc($xc + $r*$MyArc, $yc - $r, $xc + $r, $yc - $r*$MyArc, $xc + $r, $yc);
10704 $xc = $x+$w-$r ;
10705 $yc = $y+$h-$r;
10706 $this->_out(sprintf('%.3F %.3F l',($x+$w)*_MPDFK,($hp-$yc)*_MPDFK));
10707 $this->_Arc($xc + $r, $yc + $r*$MyArc, $xc + $r*$MyArc, $yc + $r, $xc, $yc + $r);
10708 $xc = $x+$r ;
10709 $yc = $y+$h-$r;
10710 $this->_out(sprintf('%.3F %.3F l',$xc*_MPDFK,($hp-($y+$h))*_MPDFK));
10711 $this->_Arc($xc - $r*$MyArc, $yc + $r, $xc - $r, $yc + $r*$MyArc, $xc - $r, $yc);
10712 $xc = $x+$r ;
10713 $yc = $y+$r;
10714 $this->_out(sprintf('%.3F %.3F l',($x)*_MPDFK,($hp-$yc)*_MPDFK ));
10715 $this->_Arc($xc - $r, $yc - $r*$MyArc, $xc - $r*$MyArc, $yc - $r, $xc, $yc - $r);
10716 $this->_out($op);
10717 }
10718
10719 function _Arc($x1, $y1, $x2, $y2, $x3, $y3)
10720 {
10721 $h = $this->h;
10722 $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $x1*_MPDFK, ($h-$y1)*_MPDFK,
10723 $x2*_MPDFK, ($h-$y2)*_MPDFK, $x3*_MPDFK, ($h-$y3)*_MPDFK));
10724 }
10725
10726
10727
10728
10729 //====================================================
10730
10731
10732
10733 /*-- DIRECTW --*/
10734 function Shaded_box( $text,$font='',$fontstyle='B',$szfont='',$width='70%',$style='DF',$radius=2.5,$fill='#FFFFFF',$color='#000000',$pad=2 ) {
10735 // F (shading - no line),S (line, no shading),DF (both)
10736 if (!class_exists('directw', false)) { include(_MPDF_PATH.'classes/directw.php'); }
10737 if (empty($this->directw)) { $this->directw = new directw($this); }
10738 $this->directw->Shaded_box( $text,$font,$fontstyle,$szfont,$width,$style,$radius,$fill,$color,$pad);
10739 }
10740 /*-- END DIRECTW --*/
10741
10742
10743 function UTF8StringToArray($str, $addSubset=true) {
10744 $out = array();
10745 $len = strlen($str);
10746 for ($i = 0; $i < $len; $i++) {
10747 $uni = -1;
10748 $h = ord($str[$i]);
10749 if ( $h <= 0x7F )
10750 $uni = $h;
10751 elseif ( $h >= 0xC2 ) {
10752 if ( ($h <= 0xDF) && ($i < $len -1) )
10753 $uni = ($h & 0x1F) << 6 | (ord($str[++$i]) & 0x3F);
10754 elseif ( ($h <= 0xEF) && ($i < $len -2) )
10755 $uni = ($h & 0x0F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
10756 elseif ( ($h <= 0xF4) && ($i < $len -3) )
10757 $uni = ($h & 0x0F) << 18 | (ord($str[++$i]) & 0x3F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
10758 }
10759 if ($uni >= 0) {
10760 $out[] = $uni;
10761 if ($addSubset && isset($this->CurrentFont['subset'])) {
10762 $this->CurrentFont['subset'][$uni] = $uni;
10763 }
10764 }
10765 }
10766 return $out;
10767 }
10768
10769
10770 //Convert utf-8 string to <HHHHHH> for Font Subsets
10771 function UTF8toSubset($str) {
10772 $ret = '<';
10773 $str = preg_replace('/'.preg_quote($this->aliasNbPg,'/').'/', chr(7), $str );
10774 $str = preg_replace('/'.preg_quote($this->aliasNbPgGp,'/').'/', chr(8), $str );
10775 $unicode = $this->UTF8StringToArray($str);
10776 $orig_fid = $this->CurrentFont['subsetfontids'][0];
10777 $last_fid = $this->CurrentFont['subsetfontids'][0];
10778 foreach($unicode as $c) {
10779 if ($c == 7 || $c == 8) {
10780 if ($orig_fid != $last_fid) {
10781 $ret .= '> Tj /F'.$orig_fid.' '.$this->FontSizePt.' Tf <';
10782 $last_fid = $orig_fid;
10783 }
10784 if ($c == 7) { $ret .= $this->aliasNbPgHex; }
10785 else { $ret .= $this->aliasNbPgGpHex; }
10786 continue;
10787 }
10788 for ($i=0; $i<99; $i++) {
10789 // return c as decimal char
10790 $init = array_search($c, $this->CurrentFont['subsets'][$i]);
10791 if ($init!==false) {
10792 if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
10793 $ret .= '> Tj /F'.$this->CurrentFont['subsetfontids'][$i].' '.$this->FontSizePt.' Tf <';
10794 $last_fid = $this->CurrentFont['subsetfontids'][$i];
10795 }
10796 $ret .= sprintf("%02s", strtoupper(dechex($init)));
10797 break;
10798 }
10799 // TrueType embedded SUBSETS
10800 else if (count($this->CurrentFont['subsets'][$i]) < 255) {
10801 $n = count($this->CurrentFont['subsets'][$i]);
10802 $this->CurrentFont['subsets'][$i][$n] = $c;
10803 if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
10804 $ret .= '> Tj /F'.$this->CurrentFont['subsetfontids'][$i].' '.$this->FontSizePt.' Tf <';
10805 $last_fid = $this->CurrentFont['subsetfontids'][$i];
10806 }
10807 $ret .= sprintf("%02s", strtoupper(dechex($n)));
10808 break;
10809 }
10810 else if (!isset($this->CurrentFont['subsets'][($i+1)])) {
10811 // TrueType embedded SUBSETS
10812 $this->CurrentFont['subsets'][($i+1)] = array(0=>0);
10813 $new_fid = count($this->fonts)+$this->extraFontSubsets+1;
10814 $this->CurrentFont['subsetfontids'][($i+1)] = $new_fid;
10815 $this->extraFontSubsets++;
10816 }
10817 }
10818 }
10819 $ret .= '>';
10820 if ($last_fid != $orig_fid) {
10821 $ret .= ' Tj /F'.$orig_fid.' '.$this->FontSizePt.' Tf <> ';
10822 }
10823 return $ret;
10824 }
10825
10826
10827 // Converts UTF-8 strings to UTF16-BE.
10828 function UTF8ToUTF16BE($str, $setbom=true) {
10829 if ($this->checkSIP && preg_match("/([\x{20000}-\x{2FFFF}])/u", $str)) {
10830 if (!in_array($this->currentfontfamily, array('gb','big5','sjis','uhc','gbB','big5B','sjisB','uhcB','gbI','big5I','sjisI','uhcI',
10831 'gbBI','big5BI','sjisBI','uhcBI'))) {
10832 $str = preg_replace("/[\x{20000}-\x{2FFFF}]/u", chr(0), $str);
10833 }
10834 }
10835 if ($this->checkSMP && preg_match("/([\x{10000}-\x{1FFFF}])/u", $str )) {
10836 $str = preg_replace("/[\x{10000}-\x{1FFFF}]/u", chr(0), $str );
10837 }
10838 $outstr = ""; // string to be returned
10839 if ($setbom) {
10840 $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM)
10841 }
10842 $outstr .= mb_convert_encoding($str, 'UTF-16BE', 'UTF-8');
10843 return $outstr;
10844 }
10845
10846
10847
10848
10849
10850 // ====================================================
10851 // ====================================================
10852 /*-- CJK-FONTS --*/
10853
10854 // from class PDF_Chinese CJK EXTENSIONS
10855 function AddCIDFont($family,$style,$name,&$cw,$CMap,$registry,$desc)
10856 {
10857 $fontkey=strtolower($family).strtoupper($style);
10858 if(isset($this->fonts[$fontkey]))
10859 $this->Error("Font already added: $family $style");
10860 $i=count($this->fonts)+$this->extraFontSubsets+1;
10861 $name=str_replace(' ','',$name);
10862 if ($family == 'sjis') { $up = -120; } else { $up = -130; }
10863 // ? 'up' and 'ut' do not seem to be referenced anywhere
10864 $this->fonts[$fontkey]=array('i'=>$i,'type'=>'Type0','name'=>$name,'up'=>$up,'ut'=>40,'cw'=>$cw,'CMap'=>$CMap,'registry'=>$registry,'MissingWidth'=>1000,'desc'=>$desc);
10865 }
10866
10867 function AddCJKFont($family) {
10868
10869 if ($this->PDFA || $this->PDFX) {
10870 $this->Error("Adobe CJK fonts cannot be embedded in mPDF (required for PDFA1-b and PDFX/1-a).");
10871 }
10872 if ($family == 'big5') { $this->AddBig5Font(); }
10873 else if ($family == 'gb') { $this->AddGBFont(); }
10874 else if ($family == 'sjis') { $this->AddSJISFont(); }
10875 else if ($family == 'uhc') { $this->AddUHCFont(); }
10876 }
10877
10878 function AddBig5Font()
10879 {
10880 //Add Big5 font with proportional Latin
10881 $family='big5';
10882 $name='MSungStd-Light-Acro';
10883 $cw=$this->Big5_widths;
10884 $CMap='UniCNS-UTF16-H';
10885 $registry=array('ordering'=>'CNS1','supplement'=>4);
10886 $desc = array(
10887 'Ascent' => 880,
10888 'Descent' => -120,
10889 'CapHeight' => 880,
10890 'Flags' => 6,
10891 'FontBBox' => '[-160 -249 1015 1071]',
10892 'ItalicAngle' => 0,
10893 'StemV' => 93,
10894 );
10895 $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
10896 $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
10897 $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
10898 $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
10899 }
10900
10901
10902 function AddGBFont()
10903 {
10904 //Add GB font with proportional Latin
10905 $family='gb';
10906 $name='STSongStd-Light-Acro';
10907 $cw=$this->GB_widths;
10908 $CMap='UniGB-UTF16-H';
10909 $registry=array('ordering'=>'GB1','supplement'=>4);
10910 $desc = array(
10911 'Ascent' => 752,
10912 'Descent' => -271,
10913 'CapHeight' => 737,
10914 'Flags' => 6,
10915 'FontBBox' => '[-25 -254 1000 880]',
10916 'ItalicAngle' => 0,
10917 'StemV' => 58,
10918 'Style' => '<< /Panose <000000000400000000000000> >>',
10919 );
10920 $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
10921 $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
10922 $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
10923 $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
10924 }
10925
10926
10927 function AddSJISFont()
10928 {
10929 //Add SJIS font with proportional Latin
10930 $family='sjis';
10931 $name='KozMinPro-Regular-Acro';
10932 $cw=$this->SJIS_widths;
10933 $CMap='UniJIS-UTF16-H';
10934 $registry=array('ordering'=>'Japan1','supplement'=>5);
10935 $desc = array(
10936 'Ascent' => 880,
10937 'Descent' => -120,
10938 'CapHeight' => 740,
10939 'Flags' => 6,
10940 'FontBBox' => '[-195 -272 1110 1075]',
10941 'ItalicAngle' => 0,
10942 'StemV' => 86,
10943 'XHeight' => 502,
10944 );
10945 $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
10946 $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
10947 $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
10948 $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
10949 }
10950
10951 function AddUHCFont()
10952 {
10953 //Add UHC font with proportional Latin
10954 $family='uhc';
10955 $name='HYSMyeongJoStd-Medium-Acro';
10956 $cw=$this->UHC_widths;
10957 $CMap='UniKS-UTF16-H';
10958 $registry=array('ordering'=>'Korea1','supplement'=>2);
10959 $desc = array(
10960 'Ascent' => 880,
10961 'Descent' => -120,
10962 'CapHeight' => 720,
10963 'Flags' => 6,
10964 'FontBBox' => '[-28 -148 1001 880]',
10965 'ItalicAngle' => 0,
10966 'StemV' => 60,
10967 'Style' => '<< /Panose <000000000600000000000000> >>',
10968 );
10969 $this->AddCIDFont($family,'',$name,$cw,$CMap,$registry,$desc);
10970 $this->AddCIDFont($family,'B',$name.',Bold',$cw,$CMap,$registry,$desc);
10971 $this->AddCIDFont($family,'I',$name.',Italic',$cw,$CMap,$registry,$desc);
10972 $this->AddCIDFont($family,'BI',$name.',BoldItalic',$cw,$CMap,$registry,$desc);
10973 }
10974
10975 /*-- END CJK-FONTS --*/
10976
10977 //////////////////////////////////////////////////////////////////////////////
10978 //////////////////////////////////////////////////////////////////////////////
10979 //////////////////////////////////////////////////////////////////////////////
10980 //////////////////////////////////////////////////////////////////////////////
10981 //////////////////////////////////////////////////////////////////////////////
10982 //////////////////////////////////////////////////////////////////////////////
10983 //////////////////////////////////////////////////////////////////////////////
10984 function SetAutoFont($af = AUTOFONT_ALL) {
10985 if ($this->onlyCoreFonts) { return false; }
10986 if (!$af && $af !== 0) { $af = AUTOFONT_ALL; }
10987 $this->autoFontGroups = $af;
10988 if ($this->autoFontGroups ) {
10989 $this->useLang = true;
10990 }
10991 }
10992
10993
10994 function SetDefaultFont($font) {
10995 // Disallow embedded fonts to be used as defaults in PDFA
10996 if ($this->PDFA || $this->PDFX) {
10997 if (strtolower($font) == 'ctimes') { $font = 'serif'; }
10998 if (strtolower($font) == 'ccourier') { $font = 'monospace'; }
10999 if (strtolower($font) == 'chelvetica') { $font = 'sans-serif'; }
11000 }
11001 $font = $this->SetFont($font); // returns substituted font if necessary
11002 $this->default_font = $font;
11003 $this->original_default_font = $font;
11004 if (!$this->watermark_font ) { $this->watermark_font = $font; } // *WATERMARK*
11005 $this->defaultCSS['BODY']['FONT-FAMILY'] = $font;
11006 $this->cssmgr->CSS['BODY']['FONT-FAMILY'] = $font;
11007 }
11008
11009 function SetDefaultFontSize($fontsize) {
11010 $this->default_font_size = $fontsize;
11011 $this->original_default_font_size = $fontsize;
11012 $this->SetFontSize($fontsize);
11013 $this->defaultCSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
11014 $this->cssmgr->CSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
11015 }
11016
11017 function SetDefaultBodyCSS($prop, $val) {
11018 if ($prop) {
11019 $this->defaultCSS['BODY'][strtoupper($prop)] = $val;
11020 $this->cssmgr->CSS['BODY'][strtoupper($prop)] = $val;
11021 }
11022 }
11023
11024
11025 function SetDirectionality($dir='ltr') {
11026 /*-- RTL --*/
11027 if (strtolower($dir) == 'rtl') {
11028 if ($this->directionality != 'rtl') {
11029 // Swop L/R Margins so page 1 RTL is an 'even' page
11030 $tmp = $this->DeflMargin;
11031 $this->DeflMargin = $this->DefrMargin;
11032 $this->DefrMargin = $tmp;
11033 $this->orig_lMargin = $this->DeflMargin;
11034 $this->orig_rMargin = $this->DefrMargin;
11035
11036 $this->SetMargins($this->DeflMargin,$this->DefrMargin,$this->tMargin);
11037 }
11038 $this->directionality = 'rtl';
11039 $this->defaultAlign = 'R';
11040 $this->defaultTableAlign = 'R';
11041 }
11042 else {
11043 /*-- END RTL --*/
11044 $this->directionality = 'ltr';
11045 $this->defaultAlign = 'L';
11046 $this->defaultTableAlign = 'L';
11047 } // *RTL*
11048 $this->cssmgr->CSS['BODY']['DIRECTION'] = $this->directionality;
11049 }
11050
11051
11052
11053 // Added to set line-height-correction
11054 function SetLineHeightCorrection($val) {
11055 if ($val > 0) { $this->default_lineheight_correction = $val; }
11056 else { $this->default_lineheight_correction = 1.2; }
11057 }
11058
11059 // Set a (fixed) lineheight to an actual value - either to named fontsize(pts) or default
11060 function SetLineHeight($FontPt='',$spacing = '') {
11061 if ($this->shrin_k > 1) { $k = $this->shrin_k; }
11062 else { $k = 1; }
11063 if ($spacing > 0) {
11064 if (preg_match('/mm/',$spacing)) {
11065 $this->lineheight = ($spacing + 0.0) / $k; // convert to number
11066 }
11067 else {
11068 if ($FontPt) { $this->lineheight = (($FontPt/_MPDFK) *$spacing); }
11069 else { $this->lineheight = (($this->FontSizePt/_MPDFK) *$spacing); }
11070 }
11071 }
11072 else {
11073 if ($FontPt) { $this->lineheight = (($FontPt/_MPDFK) *$this->normalLineheight); }
11074 else { $this->lineheight = (($this->FontSizePt/_MPDFK) *$this->normalLineheight); }
11075 }
11076 }
11077
11078 function _computeLineheight($lh, $fs='') {
11079 if ($this->shrin_k > 1) { $k = $this->shrin_k; }
11080 else { $k = 1; }
11081 if (!$fs) { $fs = $this->FontSize; }
11082 if (preg_match('/mm/',$lh)) {
11083 return (($lh + 0.0) / $k); // convert to number
11084 }
11085 else if ($lh > 0) {
11086 return ($fs * $lh);
11087 }
11088 else if (isset($this->normalLineheight)) { return ($fs * $this->normalLineheight); }
11089 else return ($fs * $this->default_lineheight_correction);
11090 }
11091
11092
11093 function SetBasePath($str='') {
11094 if ( isset($_SERVER['HTTP_HOST']) ) { $host = $_SERVER['HTTP_HOST']; }
11095 else if ( isset($_SERVER['SERVER_NAME']) ) { $host = $_SERVER['SERVER_NAME']; }
11096 else { $host = ''; }
11097 if (!$str) {
11098 if ($_SERVER['SCRIPT_NAME']) { $currentPath = dirname($_SERVER['SCRIPT_NAME']); }
11099 else { $currentPath = dirname($_SERVER['PHP_SELF']); }
11100 $currentPath = str_replace("\\","/",$currentPath);
11101 if ($currentPath == '/') { $currentPath = ''; }
11102 if ($host) { $currpath = 'http://' . $host . $currentPath .'/'; }
11103 else { $currpath = ''; }
11104 $this->basepath = $currpath;
11105 $this->basepathIsLocal = true;
11106 return;
11107 }
11108 $str = preg_replace('/\?.*/','',$str);
11109 if (!preg_match('/(http|https|ftp):\/\/.*\//i',$str)) { $str .= '/'; }
11110 $str .= 'xxx'; // in case $str ends in / e.g. http://www.bbc.co.uk/
11111 $this->basepath = dirname($str) . "/"; // returns e.g. e.g. http://www.google.com/dir1/dir2/dir3/
11112 $this->basepath = str_replace("\\","/",$this->basepath); //If on Windows
11113 $tr = parse_url($this->basepath);
11114 if (isset($tr['host']) && ($tr['host'] == $host)) { $this->basepathIsLocal = true; }
11115 else { $this->basepathIsLocal = false; }
11116 }
11117
11118
11119 function GetFullPath(&$path,$basepath='') {
11120 // When parsing CSS need to pass temporary basepath - so links are relative to current stylesheet
11121 if (!$basepath) { $basepath = $this->basepath; }
11122 //Fix path value
11123 $path = str_replace("\\","/",$path); //If on Windows
11124 $path = preg_replace('/^\/\//','http://',$path); // mPDF 5.6.27
11125 $regexp = '|^./|'; // Inadvertently corrects "./path/etc" and "//www.domain.com/etc"
11126 $path = preg_replace($regexp,'',$path);
11127
11128
11129 if(substr($path,0,1) == '#') { return; }
11130 if (stristr($path,"mailto:") !== false) { return; }
11131 if (strpos($path,"../") !== false ) { //It is a Relative Link
11132 $backtrackamount = substr_count($path,"../");
11133 $maxbacktrack = substr_count($basepath,"/") - 3; // mPDF 5.6.18
11134 $filepath = str_replace("../",'',$path);
11135 $path = $basepath;
11136 //If it is an invalid relative link, then make it go to directory root
11137 if ($backtrackamount > $maxbacktrack) $backtrackamount = $maxbacktrack;
11138 //Backtrack some directories
11139 for( $i = 0 ; $i < $backtrackamount + 1 ; $i++ ) $path = substr( $path, 0 , strrpos($path,"/") );
11140 $path = $path . "/" . $filepath; //Make it an absolute path
11141 }
11142 else if( strpos($path,":/") === false || strpos($path,":/") > 10) { //It is a Local Link
11143 if (substr($path,0,1) == "/") {
11144 $tr = parse_url($basepath);
11145 $root = $tr['scheme'].'://'.$tr['host'];
11146 $path = $root . $path;
11147 }
11148 else { $path = $basepath . $path; }
11149 }
11150 //Do nothing if it is an Absolute Link
11151 }
11152
11153
11154 // Used for external CSS files
11155 function _get_file($path) {
11156 // If local file try using local path (? quicker, but also allowed even if allow_url_fopen false)
11157 $contents = '';
11158 $contents = @file_get_contents($path);
11159 if ($contents) { return $contents; }
11160 if ($this->basepathIsLocal) {
11161 $tr = parse_url($path);
11162 $lp=getenv("SCRIPT_NAME");
11163 $ap=realpath($lp);
11164 $ap=str_replace("\\","/",$ap);
11165 $docroot=substr($ap,0,strpos($ap,$lp));
11166 // WriteHTML parses all paths to full URLs; may be local file name
11167 if ($tr['scheme'] && $tr['host'] && $_SERVER["DOCUMENT_ROOT"] ) {
11168 $localpath = $_SERVER["DOCUMENT_ROOT"] . $tr['path'];
11169 }
11170 // DOCUMENT_ROOT is not returned on IIS
11171 else if ($docroot) {
11172 $localpath = $docroot . $tr['path'];
11173 }
11174 else { $localpath = $path; }
11175 $contents = @file_get_contents($localpath);
11176 }
11177 // if not use full URL
11178 else if (!$contents && !ini_get('allow_url_fopen') && function_exists("curl_init")) {
11179 $ch = curl_init($path);
11180 curl_setopt($ch, CURLOPT_HEADER, 0);
11181 curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 );
11182 $contents = curl_exec($ch);
11183 curl_close($ch);
11184 }
11185 return $contents;
11186 }
11187
11188
11189 function docPageNum($num = 0, $extras = false) {
11190 if ($num < 1) { $num = $this->page; }
11191 $type = '1'; // set default decimal
11192 $ppgno = $num;
11193 $suppress = 0;
11194 $offset = 0;
11195 $lastreset = 0;
11196 foreach($this->PageNumSubstitutions AS $psarr) {
11197 if ($num >= $psarr['from']) {
11198 if ($psarr['reset']) {
11199 if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
11200 $ppgno = $num - $psarr['from'] + 1 + $offset;
11201 $lastreset = $psarr['from'];
11202 }
11203 if ($psarr['type']) { $type = $psarr['type']; }
11204 if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
11205 else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
11206 }
11207 }
11208 if ($suppress) { return ''; }
11209
11210 foreach($this->pgsIns AS $k=>$v) {
11211 if ($k>$lastreset && $k<$num) {
11212 $ppgno -= $v;
11213 }
11214 }
11215 if ($type=='A') { $ppgno = $this->dec2alpha($ppgno,true); }
11216 else if ($type=='a') { $ppgno = $this->dec2alpha($ppgno,false);}
11217 else if ($type=='I') { $ppgno = $this->dec2roman($ppgno,true); }
11218 else if ($type=='i') { $ppgno = $this->dec2roman($ppgno,false); }
11219 if ($extras) { $ppgno = $this->pagenumPrefix . $ppgno . $this->pagenumSuffix; }
11220 return $ppgno;
11221 }
11222
11223
11224 function docPageSettings($num = 0) {
11225 // Returns current type (numberstyle), suppression state for this page number;
11226 // reset is only returned if set for this page number
11227 if ($num < 1) { $num = $this->page; }
11228 $type = '1'; // set default decimal
11229 $ppgno = $num;
11230 $suppress = 0;
11231 $offset = 0;
11232 $reset = '';
11233 foreach($this->PageNumSubstitutions AS $psarr) {
11234 if ($num >= $psarr['from']) {
11235 if ($psarr['reset']) {
11236 if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
11237 $ppgno = $num - $psarr['from'] + 1 + $offset;
11238 }
11239 if ($psarr['type']) { $type = $psarr['type']; }
11240 if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
11241 else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
11242 }
11243 if ($num == $psarr['from']) { $reset = $psarr['reset']; }
11244 }
11245 if ($suppress) { $suppress = 'on'; }
11246 else { $suppress = 'off'; }
11247 return array($type, $suppress, $reset);
11248 }
11249
11250 function docPageNumTotal($num = 0, $extras = false) {
11251 if ($num < 1) { $num = $this->page; }
11252 $type = '1'; // set default decimal
11253 $ppgstart = 1;
11254 $ppgend = count($this->pages)+1;
11255 $suppress = 0;
11256 $offset = 0;
11257 foreach($this->PageNumSubstitutions AS $psarr) {
11258 if ($num >= $psarr['from']) {
11259 if ($psarr['reset']) {
11260 if ($psarr['reset']>1) { $offset = $psarr['reset']-1; }
11261 $ppgstart = $psarr['from'] + $offset;
11262 $ppgend = count($this->pages)+1 + $offset;
11263 }
11264 if ($psarr['type']) { $type = $psarr['type']; }
11265 if (strtoupper($psarr['suppress'])=='ON' || $psarr['suppress']==1) { $suppress = 1; }
11266 else if (strtoupper($psarr['suppress'])=='OFF') { $suppress = 0; }
11267 }
11268 if ($num < $psarr['from']) {
11269 if ($psarr['reset']) {
11270 $ppgend = $psarr['from'] + $offset;
11271 break;
11272 }
11273 }
11274 }
11275 if ($suppress) { return ''; }
11276 $ppgno = $ppgend-$ppgstart+$offset;
11277
11278 // mPDF 5.6.47
11279 foreach($this->pgsIns AS $k => $v) {
11280 if ($k>$ppgstart && $k<$ppgend) {
11281 $ppgno -= $v;
11282 }
11283 }
11284
11285 if ($extras) { $ppgno = $this->nbpgPrefix . $ppgno . $this->nbpgSuffix; }
11286 return $ppgno;
11287 }
11288
11289 function RestartDocTemplate() {
11290 $this->docTemplateStart = $this->page;
11291 }
11292
11293
11294
11295 //Page header
11296 function Header($content='') {
11297
11298 $this->cMarginL = 0;
11299 $this->cMarginR = 0;
11300
11301
11302 /*-- HTMLHEADERS-FOOTERS --*/
11303 if (($this->mirrorMargins && ($this->page%2==0) && $this->HTMLHeaderE) || ($this->mirrorMargins && ($this->page%2==1) && $this->HTMLHeader) || (!$this->mirrorMargins && $this->HTMLHeader)) {
11304 $this->writeHTMLHeaders();
11305 return;
11306 }
11307 /*-- END HTMLHEADERS-FOOTERS --*/
11308 $this->processingHeader=true;
11309 $h = $this->headerDetails;
11310 if(count($h)) {
11311
11312 if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
11313 $this->_out(sprintf('q 0 -1 1 0 0 %.3F cm ',($this->h*_MPDFK)));
11314 $yadj = $this->w - $this->h;
11315 $headerpgwidth = $this->h - $this->orig_lMargin - $this->orig_rMargin;
11316 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
11317 $headerlmargin = $this->orig_rMargin;
11318 }
11319 else {
11320 $headerlmargin = $this->orig_lMargin;
11321 }
11322 }
11323 else {
11324 $yadj = 0;
11325 $headerpgwidth = $this->pgwidth;
11326 $headerlmargin = $this->lMargin;
11327 }
11328
11329 $this->y = $this->margin_header - $yadj ;
11330 $this->SetTColor($this->ConvertColor(0));
11331 $this->SUP = false;
11332 $this->SUB = false;
11333 $this->bullet = false;
11334
11335 // only show pagenumber if numbering on
11336 $pgno = $this->docPageNum($this->page, true);
11337
11338 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
11339 $side = 'even';
11340 }
11341 else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS = DEFAULT
11342 $side = 'odd';
11343 }
11344 $maxfontheight = 0;
11345 foreach(array('L','C','R') AS $pos) {
11346 if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
11347 if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
11348 else { $hfsz = $this->default_font_size; }
11349 $maxfontheight = max($maxfontheight,$hfsz);
11350 }
11351 }
11352 // LEFT-CENTER-RIGHT
11353 foreach(array('L','C','R') AS $pos) {
11354 if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
11355 $hd = str_replace('{PAGENO}',$pgno,$h[$side][$pos]['content']);
11356 $hd = str_replace($this->aliasNbPgGp,$this->nbpgPrefix.$this->aliasNbPgGp.$this->nbpgSuffix,$hd);
11357 $hd = preg_replace_callback('/\{DATE\s+(.*?)\}/', array($this, 'date_callback') ,$hd); // mPDF 5.7
11358 if (isset($h[$side][$pos]['font-family']) && $h[$side][$pos]['font-family']) { $hff = $h[$side][$pos]['font-family']; }
11359 else { $hff = $this->original_default_font; }
11360 if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
11361 else { $hfsz = $this->original_default_font_size; } // pts
11362 $maxfontheight = max($maxfontheight,$hfsz);
11363 $hfst = '';
11364 if (isset($h[$side][$pos]['font-style']) && $h[$side][$pos]['font-style']) {
11365 $hfst = $h[$side][$pos]['font-style'];
11366 }
11367 if (isset($h[$side][$pos]['color']) && $h[$side][$pos]['color']) {
11368 $hfcol = $h[$side][$pos]['color'];
11369 $cor = $this->ConvertColor($hfcol);
11370 if ($cor) { $this->SetTColor($cor); }
11371 }
11372 else { $hfcol = ''; }
11373 $this->SetFont($hff,$hfst,$hfsz,true,true);
11374 $this->x = $headerlmargin ;
11375 $this->y = $this->margin_header - $yadj ;
11376
11377 $hd = $this->purify_utf8_text($hd);
11378 if ($this->text_input_as_HTML) {
11379 $hd = $this->all_entities_to_utf8($hd);
11380 }
11381 // CONVERT CODEPAGE
11382 if ($this->usingCoreFont) { $hd = mb_convert_encoding($hd,$this->mb_enc,'UTF-8'); }
11383 // DIRECTIONALITY RTL
11384 $this->magic_reverse_dir($hd, true, $this->directionality); // *RTL*
11385 // Font-specific ligature substitution for Indic fonts
11386 if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($hd); // *INDIC*
11387 $align = $pos;
11388 /*-- RTL --*/
11389 if ($this->directionality == 'rtl') {
11390 if ($pos == 'L') { $align = 'R'; }
11391 else if ($pos == 'R') { $align = 'L'; }
11392 }
11393 /*-- END RTL --*/
11394 if ($pos!='L' && (strpos($hd,$this->aliasNbPg)!==false || strpos($hd,$this->aliasNbPgGp)!==false)) {
11395 if (strpos($hd,$this->aliasNbPgGp)!==false) { $type= 'nbpggp'; } else { $type= 'nbpg'; }
11396 $this->_out('{mpdfheader'.$type.' '.$pos.' ff='.$hff.' fs='.$hfst.' fz='.$hfsz.'}');
11397 $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
11398 $this->_out('Q');
11399 }
11400 else {
11401 $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
11402 }
11403 if ($hfcol) { $this->SetTColor($this->ConvertColor(0)); }
11404 }
11405 }
11406 //Return Font to normal
11407 $this->SetFont($this->default_font,'',$this->original_default_font_size);
11408 // LINE
11409 if (isset($h[$side]['line']) && $h[$side]['line']) {
11410 $this->SetLineWidth(0.1);
11411 $this->SetDColor($this->ConvertColor(0));
11412 $this->Line($headerlmargin , $this->margin_header + ($maxfontheight*(1+$this->header_line_spacing)/_MPDFK) - $yadj , $headerlmargin + $headerpgwidth, $this->margin_header + ($maxfontheight*(1+$this->header_line_spacing)/_MPDFK) - $yadj );
11413 }
11414 if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
11415 $this->_out('Q');
11416 }
11417 }
11418 $this->SetY($this->tMargin);
11419 if ($this->ColActive) { $this->pgwidth = $this->ColWidth; } // *COLUMNS*
11420
11421 $this->processingHeader=false;
11422 }
11423
11424
11425
11426 /*-- TABLES --*/
11427 function TableHeaderFooter($content='',$tablestartpage='',$tablestartcolumn ='',$horf = 'H',$level, $firstSpread=true, $finalSpread=true) {
11428 if(($horf=='H' || $horf=='F') && !empty($content) && !empty($content[0])) { // mPDF 5.6.61
11429 $table = &$this->table[1][1];
11430 // Advance down page by half width of top border
11431
11432 if ($horf=='H') { // Only if header
11433 if ($table['borders_separate']) { $adv = $table['border_spacing_V']/2 + $table['border_details']['T']['w'] + $table['padding']['T']; }
11434 else { $adv = $table['max_cell_border_width']['T'] /2 ; }
11435 if ($adv) {
11436 if ($this->table_rotate) {
11437 $this->y += ($adv);
11438 }
11439 else {
11440 $this->DivLn($adv,$this->blklvl,true);
11441 }
11442 }
11443 }
11444
11445 if ($horf=='F') { // Table Footer
11446 $firstrow = count($table['cells']) - $table['footernrows'];
11447 $lastrow = count($table['cells']) - 1;
11448 }
11449 else { // Table Header
11450 $firstrow = 0;
11451 $lastrow = $table['headernrows'] - 1;
11452 }
11453
11454 $topy = $content[$firstrow][0]['y']-$this->y;
11455
11456 for ($i=$firstrow ; $i<=$lastrow; $i++) {
11457
11458 $y = $this->y;
11459
11460 /*-- COLUMNS --*/
11461 // If outside columns, this is done in PaintDivBB
11462 if ($this->ColActive) {
11463 //OUTER FILL BGCOLOR of DIVS
11464 if ($this->blklvl > 0) {
11465 $firstblockfill = $this->GetFirstBlockFill();
11466 if ($firstblockfill && $this->blklvl >= $firstblockfill) {
11467 $divh = $content[$i][0]['h'];
11468 $bak_x = $this->x;
11469 $this->DivLn($divh,-3,false);
11470 // Reset current block fill
11471 $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
11472 $this->SetFColor($bcor);
11473 $this->x = $bak_x;
11474 }
11475 }
11476 }
11477 /*-- END COLUMNS --*/
11478
11479 $colctr = 0;
11480 foreach($content[$i] as $tablehf) {
11481 $colctr++;
11482 $y = $tablehf['y'] - $topy;
11483 $this->y = $y;
11484 //Set some cell values
11485 $x = $tablehf['x'];
11486 if (($this->mirrorMargins) && ($tablestartpage == 'ODD') && (($this->page)%2==0)) { // EVEN
11487 $x = $x +$this->MarginCorrection;
11488 }
11489 else if (($this->mirrorMargins) && ($tablestartpage == 'EVEN') && (($this->page)%2==1)) { // ODD
11490 $x = $x +$this->MarginCorrection;
11491 }
11492 /*-- COLUMNS --*/
11493 // Added to correct for Columns
11494 if ($this->ColActive) {
11495 if ($this->directionality == 'rtl') { // *RTL*
11496 $x -= ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth+$this->ColGap); // *RTL*
11497 } // *RTL*
11498 else { // *RTL*
11499 $x += ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth+$this->ColGap);
11500 } // *RTL*
11501 }
11502 /*-- END COLUMNS --*/
11503
11504 if ($colctr==1) { $x0 = $x; }
11505
11506 // mPDF ITERATION
11507 if ($this->iterationCounter) {
11508 foreach($tablehf['textbuffer'] AS $k=>$t) {
11509 if (!is_array($t[0]) && preg_match('/{iteration ([a-zA-Z0-9_]+)}/',$t[0], $m)) { // mPDF 5.5.06
11510 $vname = '__'.$m[1].'_';
11511 if (!isset($this->$vname)) { $this->$vname = 1; }
11512 else { $this->$vname++; }
11513 $tablehf['textbuffer'][$k][0] = preg_replace('/{iteration '.$m[1].'}/', $this->$vname, $tablehf['textbuffer'][$k][0]);
11514 }
11515 }
11516 }
11517
11518
11519 $w = $tablehf['w'];
11520 $h = $tablehf['h'];
11521 $va = $tablehf['va'];
11522 $R = $tablehf['R'];
11523 $mih = $tablehf['mih'];
11524 $border = $tablehf['border'];
11525 $border_details = $tablehf['border_details'];
11526 $padding = $tablehf['padding'];
11527 $this->tabletheadjustfinished = true;
11528
11529 $textbuffer = $tablehf['textbuffer'];
11530
11531 $align = $tablehf['a'];
11532 //Align
11533 $this->divalign=$align;
11534 $this->x = $x;
11535
11536 if ($this->ColActive) {
11537 if ($table['borders_separate']) {
11538 $tablefill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0;
11539 if ($tablefill) {
11540 $color = $this->ConvertColor($tablefill);
11541 if ($color) {
11542 $xadj = ($table['border_spacing_H']/2);
11543 $yadj = ($table['border_spacing_V']/2);
11544 $wadj = $table['border_spacing_H'];
11545 $hadj = $table['border_spacing_V'];
11546 if ($i == $firstrow && $horf=='H') { // Top
11547 $yadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
11548 $hadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
11549 }
11550 if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i+$tablehf['rowspan']) == ($lastrow+1)) || (!isset($tablehf['rowspan']) && ($i+1) == ($lastrow+1))) && $horf=='F') { // Bottom
11551 $hadj += $table['padding']['B'] + $table['border_details']['B']['w'] ;
11552 }
11553 if ($colctr == 1) { // Left
11554 $xadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
11555 $wadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
11556 }
11557 if ($colctr == count($content[$i]) ) { // Right
11558 $wadj += $table['padding']['R'] + $table['border_details']['R']['w'] ;
11559 }
11560 $this->SetFColor($color);
11561 $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F');
11562 }
11563 }
11564 }
11565 }
11566
11567 if ($table['empty_cells']!='hide' || !empty($textbuffer) || !$table['borders_separate']) { $paintcell = true; }
11568 else { $paintcell = false; }
11569
11570 //Vertical align
11571 if ($R && INTVAL($R) > 0 && isset($va) && $va!='B') { $va='B';}
11572
11573 if (!isset($va) || empty($va) || $va=='M') $this->y += ($h-$mih)/2;
11574 elseif (isset($va) && $va=='B') $this->y += $h-$mih;
11575
11576
11577 //TABLE ROW OR CELL FILL BGCOLOR
11578 $fill = 0;
11579 if (isset($tablehf['bgcolor']) && $tablehf['bgcolor'] && $tablehf['bgcolor']!='transparent') {
11580 $fill = $tablehf['bgcolor'];
11581 $leveladj = 6;
11582 }
11583 else if (isset($content[$i][0]['trbgcolor']) && $content[$i][0]['trbgcolor'] && $content[$i][0]['trbgcolor']!='transparent') { // Row color
11584 $fill = $content[$i][0]['trbgcolor'];
11585 $leveladj = 3;
11586 }
11587 if ($fill && $paintcell) {
11588 $color = $this->ConvertColor($fill);
11589 if ($color) {
11590 if ($table['borders_separate']) {
11591 if ($this->ColActive) {
11592 $this->SetFColor($color);
11593 $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');
11594 }
11595 else {
11596 $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);
11597 }
11598 }
11599 else {
11600 if ($this->ColActive) {
11601 $this->SetFColor($color);
11602 $this->Rect($x, $y, $w, $h, 'F');
11603 }
11604 else {
11605 $this->tableBackgrounds[$level*9+$leveladj][] = array('gradient'=>false, 'x'=>$x, 'y'=>$y, 'w'=>$w, 'h'=>$h, 'col'=>$color);
11606 }
11607 }
11608 }
11609 }
11610
11611
11612 /*-- BACKGROUNDS --*/
11613 if (isset($tablehf['gradient']) && $tablehf['gradient'] && $paintcell){
11614 $g = $this->grad->parseBackgroundGradient($tablehf['gradient']);
11615 if ($g) {
11616 if ($table['borders_separate']) {
11617 $px = $x+ ($table['border_spacing_H']/2);
11618 $py = $y+ ($table['border_spacing_V']/2);
11619 $pw = $w- $table['border_spacing_H'];
11620 $ph = $h- $table['border_spacing_V'];
11621 }
11622 else {
11623 $px = $x;
11624 $py = $y;
11625 $pw = $w;
11626 $ph = $h;
11627 }
11628 if ($this->ColActive) {
11629 $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
11630 }
11631 else {
11632 $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'=>'');
11633 }
11634 }
11635 }
11636
11637 if (isset($tablehf['background-image']) && $paintcell){
11638 if ($tablehf['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $tablehf['background-image']['gradient'] )) {
11639 $g = $this->grad->parseMozGradient( $tablehf['background-image']['gradient'] );
11640 if ($g) {
11641 if ($table['borders_separate']) {
11642 $px = $x+ ($table['border_spacing_H']/2);
11643 $py = $y+ ($table['border_spacing_V']/2);
11644 $pw = $w- $table['border_spacing_H'];
11645 $ph = $h- $table['border_spacing_V'];
11646 }
11647 else {
11648 $px = $x;
11649 $py = $y;
11650 $pw = $w;
11651 $ph = $h;
11652 }
11653 if ($this->ColActive) {
11654 $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
11655 }
11656 else {
11657 $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'=>'');
11658 }
11659 }
11660 }
11661 else if ($tablehf['background-image']['image_id']) { // Background pattern
11662 $n = count($this->patterns)+1;
11663 if ($table['borders_separate']) {
11664 $px = $x+ ($table['border_spacing_H']/2);
11665 $py = $y+ ($table['border_spacing_V']/2);
11666 $pw = $w- $table['border_spacing_H'];
11667 $ph = $h- $table['border_spacing_V'];
11668 }
11669 else {
11670 $px = $x;
11671 $py = $y;
11672 $pw = $w;
11673 $ph = $h;
11674 }
11675 if ($this->ColActive) {
11676 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']);
11677 $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']);
11678 if ($tablehf['background-image']['opacity']>0 && $tablehf['background-image']['opacity']<1) { $opac = $this->SetAlpha($tablehf['background-image']['opacity'],'Normal',true); }
11679 else { $opac = ''; }
11680 $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));
11681 }
11682 else {
11683 $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']);
11684 }
11685 }
11686 }
11687 /*-- END BACKGROUNDS --*/
11688
11689 //Cell Border
11690 if ($table['borders_separate'] && $paintcell && $border) {
11691 $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']);
11692 }
11693 else if ($paintcell && $border) {
11694 $this->_tableRect($x, $y, $w, $h, $border, $border_details, true, $table['borders_separate']); // true causes buffer
11695 }
11696
11697 //Print cell content
11698 //$this->divheight = $this->table_lineheight*$this->lineheight;
11699 if (!empty($textbuffer)) {
11700 if ($horf=='F' && preg_match('/{colsum([0-9]*)[_]*}/', $textbuffer[0][0], $m)) {
11701 $rep = sprintf("%01.".intval($m[1])."f", $this->colsums[$colctr-1]);
11702 $textbuffer[0][0] = preg_replace('/{colsum[0-9_]*}/', $rep ,$textbuffer[0][0]);
11703 }
11704
11705 if ($R) {
11706 $cellPtSize = $textbuffer[0][11] / $this->shrin_k;
11707 if (!$cellPtSize) { $cellPtSize = $this->default_font_size; }
11708 $cellFontHeight = ($cellPtSize/_MPDFK);
11709 $opx = $this->x;
11710 $opy = $this->y;
11711 $angle = INTVAL($R);
11712 // Only allow 45 - 90 degrees (when bottom-aligned) or -90
11713 if ($angle > 90) { $angle = 90; }
11714 else if ($angle > 0 && (isset($va) && $va!='B')) { $angle = 90; }
11715 else if ($angle > 0 && $angle <45) { $angle = 45; }
11716 else if ($angle < 0) { $angle = -90; }
11717 $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight);
11718 if (isset($align) && $align =='R') {
11719 $this->x += ($w) + ($offset) - ($cellFontHeight/3) - ($padding['R'] + $border_details['R']['w']);
11720 }
11721 else if (!isset($align ) || $align =='C') {
11722 $this->x += ($w/2) + ($offset);
11723 }
11724 else {
11725 $this->x += ($offset) + ($cellFontHeight/3)+($padding['L'] + $border_details['L']['w']);
11726 }
11727 $str = '';
11728 foreach($tablehf['textbuffer'] AS $t) { $str .= $t[0].' '; }
11729 $str = trim($str);
11730
11731 if (!isset($va) || $va=='M') {
11732 $this->y -= ($h-$mih)/2; //Undo what was added earlier VERTICAL ALIGN
11733 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'])); }
11734 else if ($angle < 0) { $this->y += (($h-$mih)/2)+($padding['T'] + $border_details['T']['w']); }
11735 }
11736 else if (isset($va) && $va=='B') {
11737 $this->y -= $h-$mih; //Undo what was added earlier VERTICAL ALIGN
11738 if ($angle > 0) { $this->y += $h-($border_details['B']['w']+$padding['B']); }
11739 else if ($angle < 0) { $this->y += $h-$mih+($padding['T'] + $border_details['T']['w']); }
11740 }
11741 else if (isset($va) && $va=='T') {
11742 if ($angle > 0) { $this->y += $mih-($border_details['B']['w']+$padding['B']); }
11743 else if ($angle < 0) { $this->y += ($padding['T'] + $border_details['T']['w']); }
11744 }
11745
11746 $this->Rotate($angle,$this->x,$this->y);
11747 $s_fs = $this->FontSizePt;
11748 $s_f = $this->FontFamily;
11749 $s_st = $this->FontStyle;
11750 if (!empty($textbuffer[0][3])) { //Font Color
11751 $cor = $textbuffer[0][3];
11752 $this->SetTColor($cor);
11753 }
11754 $s_str = $this->strike;
11755 $this->strike = $textbuffer[0][8]; //Strikethrough
11756 $this->SetFont($textbuffer[0][4],$textbuffer[0][2],$cellPtSize,true,true);
11757 $this->Text($this->x,$this->y,$str);
11758 $this->Rotate(0);
11759 $this->SetFont($s_f,$s_st,$s_fs,true,true);
11760 $this->SetTColor(0);
11761 $this->strike = $s_str;
11762 $this->x = $opx;
11763 $this->y = $opy;
11764 }
11765 else {
11766 if ($table['borders_separate']) { // NB twice border width
11767 $xadj = $border_details['L']['w'] + $padding['L'] +($table['border_spacing_H']/2);
11768 $wadj = $border_details['L']['w'] + $border_details['R']['w'] + $padding['L'] +$padding['R'] + $table['border_spacing_H'];
11769 $yadj = $border_details['T']['w'] + $padding['T'] + ($table['border_spacing_H']/2);
11770 }
11771 else {
11772 $xadj = $border_details['L']['w']/2 + $padding['L'];
11773 $wadj = ($border_details['L']['w'] + $border_details['R']['w'])/2 + $padding['L'] + $padding['R'];
11774 $yadj = $border_details['T']['w']/2 + $padding['T'];
11775 }
11776
11777 $this->divwidth=$w-($wadj);
11778 $this->x += $xadj;
11779 $this->y += $yadj;
11780 $this->printbuffer($textbuffer,'',true);
11781 }
11782
11783 }
11784 $textbuffer = array();
11785
11786 /*-- BACKGROUNDS --*/
11787 if (!$this->ColActive) {
11788 if (isset($content[$i][0]['trgradients']) && ($colctr==1 || $table['borders_separate'])) {
11789 $g = $this->grad->parseBackgroundGradient($content[$i][0]['trgradients']);
11790 if ($g) {
11791 $gx = $x0;
11792 $gy = $y;
11793 $gh = $h;
11794 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
11795 if ($table['borders_separate']) {
11796 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
11797 $s = '';
11798 $clx = $x+ ($table['border_spacing_H']/2);
11799 $cly = $y+ ($table['border_spacing_V']/2);
11800 $clw = $w- $table['border_spacing_H'];
11801 $clh = $h- $table['border_spacing_V'];
11802 // Set clipping path
11803 $s = ' q 0 w '; // Line width=0
11804 $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
11805 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
11806 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
11807 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
11808 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
11809 $s .= ' W n '; // Ends path no-op & Sets the clipping path
11810 $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);
11811 }
11812 else {
11813 $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'=>'');
11814 }
11815 }
11816 }
11817
11818 if (isset($content[$i][0]['trbackground-images']) && ($colctr==1 || $table['borders_separate'])) {
11819 if ($content[$i][0]['trbackground-images']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $content[$i][0]['trbackground-images']['gradient'] )) {
11820 $g = $this->grad->parseMozGradient( $content[$i][0]['trbackground-images']['gradient'] );
11821 if ($g) {
11822 $gx = $x0;
11823 $gy = $y;
11824 $gh = $h;
11825 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
11826 if ($table['borders_separate']) {
11827 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
11828 $s = '';
11829 $clx = $x+ ($table['border_spacing_H']/2);
11830 $cly = $y+ ($table['border_spacing_V']/2);
11831 $clw = $w- $table['border_spacing_H'];
11832 $clh = $h- $table['border_spacing_V'];
11833 // Set clipping path
11834 $s = ' q 0 w '; // Line width=0
11835 $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
11836 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
11837 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
11838 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
11839 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
11840 $s .= ' W n '; // Ends path no-op & Sets the clipping path
11841 $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);
11842 }
11843 else {
11844 $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'=>'');
11845 }
11846 }
11847 }
11848 else {
11849 $image_id = $content[$i][0]['trbackground-images']['image_id'];
11850 $orig_w = $content[$i][0]['trbackground-images']['orig_w'];
11851 $orig_h = $content[$i][0]['trbackground-images']['orig_h'];
11852 $x_pos = $content[$i][0]['trbackground-images']['x_pos'];
11853 $y_pos = $content[$i][0]['trbackground-images']['y_pos'];
11854 $x_repeat = $content[$i][0]['trbackground-images']['x_repeat'];
11855 $y_repeat = $content[$i][0]['trbackground-images']['y_repeat'];
11856 $resize = $content[$i][0]['trbackground-images']['resize'];
11857 $opacity = $content[$i][0]['trbackground-images']['opacity'];
11858 $itype = $content[$i][0]['trbackground-images']['itype'];
11859
11860 $clippath = '';
11861 $gx = $x0;
11862 $gy = $y;
11863 $gh = $h;
11864 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
11865 if ($table['borders_separate']) {
11866 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
11867 $s = '';
11868 $clx = $x+ ($table['border_spacing_H']/2);
11869 $cly = $y+ ($table['border_spacing_V']/2);
11870 $clw = $w- $table['border_spacing_H'];
11871 $clh = $h- $table['border_spacing_V'];
11872 // Set clipping path
11873 $s = ' q 0 w '; // Line width=0
11874 $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
11875 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
11876 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
11877 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
11878 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
11879 $s .= ' W n '; // Ends path no-op & Sets the clipping path
11880 $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);
11881 }
11882 else {
11883 $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);
11884 }
11885 }
11886 }
11887 }
11888 /*-- END BACKGROUNDS --*/
11889
11890 // TABLE BORDER - if separate OR collapsed and only table border
11891 if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) {
11892 $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H']/2);
11893 $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H']/2);
11894 $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V']/2);
11895 $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V']/2);
11896 $tbx = $x;
11897 $tby = $y;
11898 $tbw = $w;
11899 $tbh = $h;
11900 $tab_bord = 0;
11901 $corner = '';
11902 if ($i == $firstrow && $horf=='H') { // Top
11903 $tby -= $halfspaceT + ($table['border_details']['T']['w']/2);
11904 $tbh += $halfspaceT + ($table['border_details']['T']['w']/2);
11905 $this->setBorder($tab_bord , _BORDER_TOP);
11906 $corner .= 'T';
11907 }
11908 if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i+$tablehf['rowspan']) == ($lastrow+1))) && $horf=='F') { // Bottom
11909 $tbh += $halfspaceB + ($table['border_details']['B']['w']/2);
11910 $this->setBorder($tab_bord , _BORDER_BOTTOM);
11911 $corner .= 'B';
11912 }
11913 if ($colctr == 1 && $firstSpread) { // Left
11914 $tbx -= $halfspaceL + ($table['border_details']['L']['w']/2);
11915 $tbw += $halfspaceL + ($table['border_details']['L']['w']/2);
11916 $this->setBorder($tab_bord , _BORDER_LEFT);
11917 $corner .= 'L';
11918 }
11919 if ($colctr == count($content[$i]) && $finalSpread) { // Right
11920 $tbw += $halfspaceR + ($table['border_details']['R']['w']/2);
11921 $this->setBorder($tab_bord , _BORDER_RIGHT);
11922 $corner .= 'R';
11923 }
11924 $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'] );
11925 }
11926
11927
11928 }// end column $content
11929 $this->y = $y + $h; //Update y coordinate
11930 }// end row $i
11931 unset($table );
11932 $this->colsums = array();
11933 }
11934 }
11935 /*-- END TABLES --*/
11936
11937 /*-- HTMLHEADERS-FOOTERS --*/
11938 function SetHTMLHeader($header='',$OE='',$write=false) {
11939
11940 $height = 0;
11941 if (is_array($header) && isset($header['html']) && $header['html']) {
11942 $Hhtml = $header['html'];
11943 if ($this->setAutoTopMargin) {
11944 if (isset($header['h'])) { $height = $header['h']; }
11945 else { $height = $this->_gethtmlheight($Hhtml); }
11946 }
11947 }
11948 else if (!is_array($header) && $header) {
11949 $Hhtml = $header;
11950 if ($this->setAutoTopMargin) { $height = $this->_gethtmlheight($Hhtml); }
11951 }
11952 else { $Hhtml = ''; }
11953
11954 if ($OE != 'E') { $OE = 'O'; }
11955 if ($OE == 'E') {
11956
11957 if ($Hhtml) {
11958 $this->HTMLHeaderE['html'] = $Hhtml;
11959 $this->HTMLHeaderE['h'] = $height;
11960 }
11961 else { $this->HTMLHeaderE = ''; }
11962 }
11963 else {
11964
11965 if ($Hhtml) {
11966 $this->HTMLHeader['html'] = $Hhtml;
11967 $this->HTMLHeader['h'] = $height;
11968 }
11969 else { $this->HTMLHeader = ''; }
11970 }
11971 if (!$this->mirrorMargins && $OE == 'E') { return; }
11972 if ($Hhtml=='') { return; }
11973 if ($OE == 'E') {
11974 $this->headerDetails['even'] = array(); // override and clear any other non-HTML header/footer
11975 }
11976 else {
11977 $this->headerDetails['odd'] = array(); // override and clear any non-HTML other header/footer
11978 }
11979
11980 if ($this->setAutoTopMargin=='pad') {
11981 $this->tMargin = $this->margin_header + $height + $this->orig_tMargin;
11982 if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) { $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin; }
11983 }
11984 else if ($this->setAutoTopMargin=='stretch') {
11985 $this->tMargin = max($this->orig_tMargin, $this->margin_header + $height + $this->autoMarginPadding);
11986 if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) { $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin; }
11987 }
11988 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(); }
11989 }
11990
11991 function SetHTMLFooter($footer='',$OE='') {
11992
11993 $height = 0;
11994 if (is_array($footer) && isset($footer['html']) && $footer['html']) {
11995 $Fhtml = $footer['html'];
11996 if ($this->setAutoBottomMargin) {
11997 if (isset($footer['h'])) { $height = $footer['h']; }
11998 else { $height = $this->_gethtmlheight($Fhtml); }
11999 }
12000 }
12001 else if (!is_array($footer) && $footer) {
12002 $Fhtml = $footer;
12003 if ($this->setAutoBottomMargin) { $height = $this->_gethtmlheight($Fhtml); }
12004 }
12005 else { $Fhtml = ''; }
12006
12007 if ($OE != 'E') { $OE = 'O'; }
12008 if ($OE == 'E') {
12009
12010 if ($Fhtml) {
12011 $this->HTMLFooterE['html'] = $Fhtml;
12012 $this->HTMLFooterE['h'] = $height;
12013 }
12014 else { $this->HTMLFooterE = ''; }
12015 }
12016 else {
12017
12018 if ($Fhtml) {
12019 $this->HTMLFooter['html'] = $Fhtml;
12020 $this->HTMLFooter['h'] = $height;
12021 }
12022 else { $this->HTMLFooter = ''; }
12023 }
12024 if (!$this->mirrorMargins && $OE == 'E') { return; }
12025 if ($Fhtml=='') { return false; }
12026 if ($OE == 'E') {
12027 $this->footerDetails['even'] = array(); // override and clear any other header/footer
12028 }
12029 else {
12030 $this->footerDetails['odd'] = array(); // override and clear any other header/footer
12031 }
12032
12033 if ($this->setAutoBottomMargin=='pad') {
12034 $this->bMargin = $this->margin_footer + $height + $this->orig_bMargin;
12035 $this->PageBreakTrigger=$this->h-$this->bMargin ;
12036 if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) { $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin; }
12037 }
12038 else if ($this->setAutoBottomMargin=='stretch') {
12039 $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $height + $this->autoMarginPadding);
12040 $this->PageBreakTrigger=$this->h-$this->bMargin ;
12041 if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) { $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin; }
12042 }
12043 }
12044
12045
12046 function _getHtmlHeight($html) {
12047 $save_state = $this->state;
12048 if($this->state==0) {
12049 $this->AddPage($this->CurOrientation);
12050 }
12051 $this->state = 2;
12052 $this->Reset();
12053 $this->pageoutput[$this->page] = array();
12054 $save_x = $this->x;
12055 $save_y = $this->y;
12056 $this->x = $this->lMargin;
12057 $this->y = $this->margin_header;
12058 $html = str_replace('{PAGENO}',$this->pagenumPrefix.$this->docPageNum($this->page).$this->pagenumSuffix,$html);
12059 $html = str_replace($this->aliasNbPgGp,$this->nbpgPrefix.$this->docPageNumTotal($this->page).$this->nbpgSuffix,$html );
12060 $html = str_replace($this->aliasNbPg,$this->page,$html );
12061 $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', array($this, 'date_callback') ,$html ); // mPDF 5.7
12062 $this->HTMLheaderPageLinks = array();
12063 $this->HTMLheaderPageAnnots = array();
12064 $this->HTMLheaderPageForms = array();
12065 $savepb = $this->pageBackgrounds;
12066 $this->writingHTMLheader = true;
12067 $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
12068 $this->writingHTMLheader = false;
12069 $h = ($this->y - $this->margin_header);
12070 $this->Reset();
12071 $this->pageoutput[$this->page] = array();
12072 $this->headerbuffer = '';
12073 $this->pageBackgrounds = $savepb;
12074 $this->x = $save_x;
12075 $this->y = $save_y;
12076 $this->state = $save_state;
12077 if($save_state==0) {
12078 unset($this->pages[1]);
12079 $this->page = 0;
12080 }
12081 return $h;
12082 }
12083
12084
12085 // Called internally from Header
12086 function writeHTMLHeaders() {
12087
12088 if ($this->mirrorMargins && ($this->page)%2==0) { $OE = 'E'; } // EVEN
12089 else { $OE = 'O'; }
12090 if ($OE == 'E') {
12091 $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeaderE['html'] ;
12092 }
12093 else {
12094 $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeader['html'] ;
12095 }
12096 if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
12097 $this->saveHTMLHeader[$this->page][$OE]['rotate'] = true;
12098 $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->tMargin;
12099 $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->bMargin;
12100 $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
12101 $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
12102 $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->h;
12103 $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->w;
12104 }
12105 else {
12106 $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->lMargin;
12107 $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->rMargin;
12108 $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
12109 $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
12110 $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->w;
12111 $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->h;
12112 }
12113 }
12114
12115 function writeHTMLFooters() {
12116
12117 if ($this->mirrorMargins && ($this->page)%2==0) { $OE = 'E'; } // EVEN
12118 else { $OE = 'O'; }
12119 if ($OE == 'E') {
12120 $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooterE['html'] ;
12121 }
12122 else {
12123 $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooter['html'] ;
12124 }
12125 if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
12126 $this->saveHTMLFooter[$this->page][$OE]['rotate'] = true;
12127 $this->saveHTMLFooter[$this->page][$OE]['ml'] = $this->tMargin;
12128 $this->saveHTMLFooter[$this->page][$OE]['mr'] = $this->bMargin;
12129 $this->saveHTMLFooter[$this->page][$OE]['mt'] = $this->rMargin;
12130 $this->saveHTMLFooter[$this->page][$OE]['mb'] = $this->lMargin;
12131 $this->saveHTMLFooter[$this->page][$OE]['mh'] = $this->margin_header;
12132 $this->saveHTMLFooter[$this->page][$OE]['mf'] = $this->margin_footer;
12133 $this->saveHTMLFooter[$this->page][$OE]['pw'] = $this->h;
12134 $this->saveHTMLFooter[$this->page][$OE]['ph'] = $this->w;
12135 }
12136 else {
12137 $this->saveHTMLFooter[$this->page][$OE]['ml'] = $this->lMargin;
12138 $this->saveHTMLFooter[$this->page][$OE]['mr'] = $this->rMargin;
12139 $this->saveHTMLFooter[$this->page][$OE]['mt'] = $this->tMargin;
12140 $this->saveHTMLFooter[$this->page][$OE]['mb'] = $this->bMargin;
12141 $this->saveHTMLFooter[$this->page][$OE]['mh'] = $this->margin_header;
12142 $this->saveHTMLFooter[$this->page][$OE]['mf'] = $this->margin_footer;
12143 $this->saveHTMLFooter[$this->page][$OE]['pw'] = $this->w;
12144 $this->saveHTMLFooter[$this->page][$OE]['ph'] = $this->h;
12145 }
12146 }
12147 /*-- END HTMLHEADERS-FOOTERS --*/
12148
12149 function DefHeaderByName($name,$arr) {
12150 if (!$name) { $name = '_default'; }
12151 $this->pageheaders[$name] = $arr;
12152 }
12153
12154 function DefFooterByName($name,$arr) {
12155 if (!$name) { $name = '_default'; }
12156 $this->pagefooters[$name] = $arr;
12157 }
12158
12159 function SetHeaderByName($name,$side='O',$write=false) {
12160 if (!$name) { $name = '_default'; }
12161 if ($side=='E') { $this->headerDetails['even'] = $this->pageheaders[$name]; }
12162 else { $this->headerDetails['odd'] = $this->pageheaders[$name]; }
12163 if ($write) { $this->Header(); }
12164 }
12165
12166 function SetFooterByName($name,$side='O') {
12167 if (!$name) { $name = '_default'; }
12168 if ($side=='E') { $this->footerDetails['even'] = $this->pagefooters[$name]; }
12169 else { $this->footerDetails['odd'] = $this->pagefooters[$name]; }
12170 }
12171
12172 /*-- HTMLHEADERS-FOOTERS --*/
12173 function DefHTMLHeaderByName($name,$html) {
12174 if (!$name) { $name = '_default'; }
12175
12176 $this->pageHTMLheaders[$name]['html'] = $html;
12177 $this->pageHTMLheaders[$name]['h'] = $this->_gethtmlheight($html);
12178 }
12179
12180 function DefHTMLFooterByName($name,$html) {
12181 if (!$name) { $name = '_default'; }
12182
12183 $this->pageHTMLfooters[$name]['html'] = $html;
12184 $this->pageHTMLfooters[$name]['h'] = $this->_gethtmlheight($html);
12185 }
12186
12187 function SetHTMLHeaderByName($name,$side='O',$write=false) {
12188 if (!$name) { $name = '_default'; }
12189 $this->SetHTMLHeader($this->pageHTMLheaders[$name],$side,$write);
12190 }
12191
12192 function SetHTMLFooterByName($name,$side='O') {
12193 if (!$name) { $name = '_default'; }
12194 $this->SetHTMLFooter($this->pageHTMLfooters[$name],$side,$write);
12195 }
12196 /*-- END HTMLHEADERS-FOOTERS --*/
12197
12198
12199 function SetHeader($Harray=array(),$side='',$write=false) {
12200 if (is_string($Harray)) {
12201 if (strlen($Harray)==0) {
12202 if ($side=='O') { $this->headerDetails['odd'] = array(); }
12203 else if ($side=='E') { $this->headerDetails['even'] = array(); }
12204 else { $this->headerDetails = array(); }
12205 }
12206 else if (strpos($Harray,'|') || strpos($Harray,'|')===0) {
12207 $hdet = explode('|',$Harray);
12208 $this->headerDetails = array (
12209 'odd' => array (
12210 'L' => array ('content' => $hdet[0], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
12211 'C' => array ('content' => $hdet[1], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
12212 'R' => array ('content' => $hdet[2], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
12213 'line' => $this->defaultheaderline,
12214 ),
12215 'even' => array (
12216 'R' => array ('content' => $hdet[0], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
12217 'C' => array ('content' => $hdet[1], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
12218 'L' => array ('content' => $hdet[2], 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
12219 'line' => $this->defaultheaderline,
12220 )
12221 );
12222 }
12223 else {
12224 $this->headerDetails = array (
12225 'odd' => array (
12226 'R' => array ('content' => $Harray, 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
12227 'line' => $this->defaultheaderline,
12228 ),
12229 'even' => array (
12230 'L' => array ('content' => $Harray, 'font-size' => $this->defaultheaderfontsize, 'font-style' => $this->defaultheaderfontstyle),
12231 'line' => $this->defaultheaderline,
12232 )
12233 );
12234 }
12235 }
12236 else if (is_array($Harray)) {
12237 if ($side=='O') { $this->headerDetails['odd'] = $Harray; }
12238 else if ($side=='E') { $this->headerDetails['even'] = $Harray; }
12239 else { $this->headerDetails = $Harray; }
12240 }
12241 /*-- HTMLHEADERS-FOOTERS --*/
12242 // Overwrite any HTML Header previously set
12243 if ($side=='E') { $this->SetHTMLHeader('','E'); }
12244 else if ($side=='O') { $this->SetHTMLHeader(''); }
12245 else {
12246 $this->SetHTMLHeader('');
12247 $this->SetHTMLHeader('','E');
12248 }
12249 /*-- END HTMLHEADERS-FOOTERS --*/
12250
12251 if ($write) {
12252 $save_y = $this->y;
12253 $this->Header();
12254 $this->SetY($save_y) ;
12255 }
12256 }
12257
12258
12259
12260
12261 function SetFooter($Farray=array(),$side='') {
12262 if (is_string($Farray)) {
12263 if (strlen($Farray)==0) {
12264 if ($side=='O') { $this->footerDetails['odd'] = array(); }
12265 else if ($side=='E') { $this->footerDetails['even'] = array(); }
12266 else { $this->footerDetails = array(); }
12267 }
12268 else if (strpos($Farray,'|') || strpos($Farray,'|')===0) {
12269 $fdet = explode('|',$Farray);
12270 $this->footerDetails = array (
12271 'odd' => array (
12272 'L' => array ('content' => $fdet[0], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
12273 'C' => array ('content' => $fdet[1], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
12274 'R' => array ('content' => $fdet[2], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
12275 'line' => $this->defaultfooterline,
12276 ),
12277 'even' => array (
12278 'R' => array ('content' => $fdet[0], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
12279 'C' => array ('content' => $fdet[1], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
12280 'L' => array ('content' => $fdet[2], 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
12281 'line' => $this->defaultfooterline,
12282 )
12283 );
12284 }
12285 else {
12286 $this->footerDetails = array (
12287 'odd' => array (
12288 'R' => array ('content' => $Farray, 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
12289 'line' => $this->defaultfooterline,
12290 ),
12291 'even' => array (
12292 'L' => array ('content' => $Farray, 'font-size' => $this->defaultfooterfontsize, 'font-style' => $this->defaultfooterfontstyle),
12293 'line' => $this->defaultfooterline,
12294 )
12295 );
12296 }
12297 }
12298 else if (is_array($Farray)) {
12299 if ($side=='O') { $this->footerDetails['odd'] = $Farray; }
12300 else if ($side=='E') { $this->footerDetails['even'] = $Farray; }
12301 else { $this->footerDetails = $Farray; }
12302 }
12303 /*-- HTMLHEADERS-FOOTERS --*/
12304 // Overwrite any HTML Footer previously set
12305 if ($side=='E') { $this->SetHTMLFooter('','E'); }
12306 else if ($side=='O') { $this->SetHTMLFooter(''); }
12307 else {
12308 $this->SetHTMLFooter('');
12309 $this->SetHTMLFooter('','E');
12310 }
12311 /*-- END HTMLHEADERS-FOOTERS --*/
12312 }
12313
12314 /*-- WATERMARK --*/
12315 function setUnvalidatedText($txt='', $alpha=-1) {
12316 if ($alpha>=0) $this->watermarkTextAlpha = $alpha;
12317 $this->watermarkText = $txt;
12318 }
12319 function SetWatermarkText($txt='', $alpha=-1) {
12320 if ($alpha>=0) $this->watermarkTextAlpha = $alpha;
12321 $this->watermarkText = $txt;
12322 }
12323
12324 function SetWatermarkImage($src, $alpha=-1, $size='D', $pos='F') {
12325 if ($alpha>=0) $this->watermarkImageAlpha = $alpha;
12326 $this->watermarkImage = $src;
12327 $this->watermark_size = $size;
12328 $this->watermark_pos = $pos;
12329 }
12330 /*-- END WATERMARK --*/
12331
12332
12333 //Page footer
12334 function Footer() {
12335 /*-- CSS-PAGE --*/
12336 // PAGED MEDIA - CROP / CROSS MARKS from @PAGE
12337 if ($this->show_marks == 'CROP' || $this->show_marks == 'CROPCROSS') {
12338 // Show TICK MARKS
12339 $this->SetLineWidth(0.1); // = 0.1 mm
12340 $this->SetDColor($this->ConvertColor(0));
12341 $l = $this->cropMarkLength;
12342 $m = $this->cropMarkMargin; // Distance of crop mark from margin
12343 $b = $this->nonPrintMargin; // Non-printable border at edge of paper sheet
12344 $ax1 = $b;
12345 $bx = $this->page_box['outer_width_LR'] - $m;
12346 $ax = max($ax1, $bx-$l);
12347 $cx1 = $this->w - $b;
12348 $dx = $this->w - $this->page_box['outer_width_LR'] + $m;
12349 $cx = min($cx1, $dx+$l);
12350 $ay1 = $b;
12351 $by = $this->page_box['outer_width_TB'] - $m;
12352 $ay = max($ay1, $by-$l);
12353 $cy1 = $this->h - $b;
12354 $dy = $this->h - $this->page_box['outer_width_TB'] + $m;
12355 $cy = min($cy1, $dy+$l);
12356
12357 $this->Line($ax, $this->page_box['outer_width_TB'], $bx, $this->page_box['outer_width_TB']);
12358 $this->Line($cx, $this->page_box['outer_width_TB'], $dx, $this->page_box['outer_width_TB']);
12359 $this->Line($ax, $this->h - $this->page_box['outer_width_TB'], $bx, $this->h - $this->page_box['outer_width_TB']);
12360 $this->Line($cx, $this->h - $this->page_box['outer_width_TB'], $dx, $this->h - $this->page_box['outer_width_TB']);
12361 $this->Line($this->page_box['outer_width_LR'], $ay, $this->page_box['outer_width_LR'], $by);
12362 $this->Line($this->page_box['outer_width_LR'], $cy, $this->page_box['outer_width_LR'], $dy);
12363 $this->Line($this->w - $this->page_box['outer_width_LR'], $ay, $this->w - $this->page_box['outer_width_LR'], $by);
12364 $this->Line($this->w - $this->page_box['outer_width_LR'], $cy, $this->w - $this->page_box['outer_width_LR'], $dy);
12365
12366 if ($this->printers_info) {
12367 $hd = date('Y-m-d H:i').' Page '.$this->page.' of {nb}';
12368 $this->SetTColor($this->ConvertColor(0));
12369 $this->SetFont('arial','',7.5,true,true);
12370 $this->x = $this->page_box['outer_width_LR'] + 1.5;
12371 $this->y = 1;
12372 $this->Cell($headerpgwidth ,$this->FontSize,$hd,0,0,'L',0,'',0,0,0,'M');
12373 $this->SetFont($this->default_font,'',$this->original_default_font_size);
12374 }
12375
12376 }
12377 if ($this->show_marks == 'CROSS' || $this->show_marks == 'CROPCROSS') {
12378 $this->SetLineWidth(0.1); // = 0.1 mm
12379 $this->SetDColor($this->ConvertColor(0));
12380 $l = 14 /2; // longer length of the cross line (half)
12381 $w = 6 /2; // shorter width of the cross line (half)
12382 $r = 1.2; // radius of circle
12383 $m = $this->crossMarkMargin; // Distance of cross mark from margin
12384 $x1 = $this->page_box['outer_width_LR'] - $m;
12385 $x2 = $this->w - $this->page_box['outer_width_LR'] + $m;
12386 $y1 = $this->page_box['outer_width_TB'] - $m;
12387 $y2 = $this->h - $this->page_box['outer_width_TB'] + $m;
12388 // Left
12389 $this->Circle($x1, $this->h/2, $r, 'S') ;
12390 $this->Line($x1-$w, $this->h/2, $x1+$w, $this->h/2);
12391 $this->Line($x1, $this->h/2-$l, $x1, $this->h/2+$l);
12392 // Right
12393 $this->Circle($x2, $this->h/2, $r, 'S') ;
12394 $this->Line($x2-$w, $this->h/2, $x2+$w, $this->h/2);
12395 $this->Line($x2, $this->h/2-$l, $x2, $this->h/2+$l);
12396 // Top
12397 $this->Circle($this->w/2, $y1, $r, 'S') ;
12398 $this->Line($this->w/2, $y1-$w, $this->w/2, $y1+$w);
12399 $this->Line($this->w/2-$l, $y1, $this->w/2+$l, $y1);
12400 // Bottom
12401 $this->Circle($this->w/2, $y2, $r, 'S') ;
12402 $this->Line($this->w/2, $y2-$w, $this->w/2, $y2+$w);
12403 $this->Line($this->w/2-$l, $y2, $this->w/2+$l, $y2);
12404 }
12405
12406
12407 // If @page set non-HTML headers/footers named, they were not read until later in the HTML code - so now set them
12408 if ($this->page==1) {
12409 if ($this->firstPageBoxHeader) {
12410 $this->headerDetails['odd'] = $this->pageheaders[$this->firstPageBoxHeader];
12411 $this->Header();
12412 }
12413 if ($this->firstPageBoxFooter) {
12414 $this->footerDetails['odd'] = $this->pagefooters[$this->firstPageBoxFooter];
12415 }
12416 $this->firstPageBoxHeader='';
12417 $this->firstPageBoxFooter='';
12418 }
12419 /*-- END CSS-PAGE --*/
12420
12421
12422
12423 /*-- HTMLHEADERS-FOOTERS --*/
12424 if (($this->mirrorMargins && ($this->page%2==0) && $this->HTMLFooterE) || ($this->mirrorMargins && ($this->page%2==1) && $this->HTMLFooter) || (!$this->mirrorMargins && $this->HTMLFooter)) {
12425 $this->writeHTMLFooters();
12426 /*-- WATERMARK --*/
12427 if (($this->watermarkText) && ($this->showWatermarkText)) {
12428 $this->watermark( $this->watermarkText, 45, 120, $this->watermarkTextAlpha); // Watermark text
12429 }
12430 if (($this->watermarkImage) && ($this->showWatermarkImage)) {
12431 $this->watermarkImg( $this->watermarkImage, $this->watermarkImageAlpha); // Watermark image
12432 }
12433 /*-- END WATERMARK --*/
12434 return;
12435 }
12436 /*-- END HTMLHEADERS-FOOTERS --*/
12437
12438 $this->processingHeader=true;
12439 $this->ResetMargins(); // necessary after columns
12440 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
12441 /*-- WATERMARK --*/
12442 if (($this->watermarkText) && ($this->showWatermarkText)) {
12443 $this->watermark( $this->watermarkText, 45, 120, $this->watermarkTextAlpha); // Watermark text
12444 }
12445 if (($this->watermarkImage) && ($this->showWatermarkImage)) {
12446 $this->watermarkImg( $this->watermarkImage, $this->watermarkImageAlpha); // Watermark image
12447 }
12448 /*-- END WATERMARK --*/
12449 $h = $this->footerDetails;
12450 if(count($h)) {
12451
12452 if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
12453 $this->_out(sprintf('q 0 -1 1 0 0 %.3F cm ',($this->h*_MPDFK)));
12454 $headerpgwidth = $this->h - $this->orig_lMargin - $this->orig_rMargin;
12455 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
12456 $headerlmargin = $this->orig_rMargin;
12457 }
12458 else {
12459 $headerlmargin = $this->orig_lMargin;
12460 }
12461 }
12462 else {
12463 $yadj = 0;
12464 $headerpgwidth = $this->pgwidth;
12465 $headerlmargin = $this->lMargin;
12466 }
12467 $this->SetY(-$this->margin_footer);
12468
12469 $this->SetTColor($this->ConvertColor(0));
12470 $this->SUP = false;
12471 $this->SUB = false;
12472 $this->bullet = false;
12473
12474 // only show pagenumber if numbering on
12475 $pgno = $this->docPageNum($this->page, true);
12476
12477 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
12478 $side = 'even';
12479 }
12480 else { // ODD // OR NOT MIRRORING MARGINS/FOOTERS = DEFAULT
12481 $side = 'odd';
12482 }
12483 $maxfontheight = 0;
12484 foreach(array('L','C','R') AS $pos) {
12485 if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
12486 if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
12487 else { $hfsz = $this->default_font_size; }
12488 $maxfontheight = max($maxfontheight,$hfsz);
12489 }
12490 }
12491 // LEFT-CENTER-RIGHT
12492 foreach(array('L','C','R') AS $pos) {
12493 if (isset($h[$side][$pos]['content']) && $h[$side][$pos]['content']) {
12494 $hd = str_replace('{PAGENO}',$pgno,$h[$side][$pos]['content']);
12495 $hd = str_replace($this->aliasNbPgGp,$this->nbpgPrefix.$this->aliasNbPgGp.$this->nbpgSuffix,$hd);
12496 $hd = preg_replace_callback('/\{DATE\s+(.*?)\}/', array($this, 'date_callback') ,$hd); // mPDF 5.7
12497 if (isset($h[$side][$pos]['font-family']) && $h[$side][$pos]['font-family']) { $hff = $h[$side][$pos]['font-family']; }
12498 else { $hff = $this->original_default_font; }
12499 if (isset($h[$side][$pos]['font-size']) && $h[$side][$pos]['font-size']) { $hfsz = $h[$side][$pos]['font-size']; }
12500 else { $hfsz = $this->original_default_font_size; }
12501 $maxfontheight = max($maxfontheight,$hfsz);
12502 if (isset($h[$side][$pos]['font-style']) && $h[$side][$pos]['font-style']) { $hfst = $h[$side][$pos]['font-style']; }
12503 else { $hfst = ''; }
12504 if (isset($h[$side][$pos]['color']) && $h[$side][$pos]['color']) {
12505 $hfcol = $h[$side][$pos]['color'];
12506 $cor = $this->ConvertColor($hfcol);
12507 if ($cor) { $this->SetTColor($cor); }
12508 }
12509 else { $hfcol = ''; }
12510 $this->SetFont($hff,$hfst,$hfsz,true,true);
12511 $this->x = $headerlmargin ;
12512 $this->y = $this->h - $this->margin_footer - ($maxfontheight/_MPDFK);
12513 $hd = $this->purify_utf8_text($hd);
12514 if ($this->text_input_as_HTML) {
12515 $hd = $this->all_entities_to_utf8($hd);
12516 }
12517 // CONVERT CODEPAGE
12518 if ($this->usingCoreFont) { $hd = mb_convert_encoding($hd,$this->mb_enc,'UTF-8'); }
12519 // DIRECTIONALITY RTL
12520 $this->magic_reverse_dir($hd, true, $this->directionality); // *RTL*
12521 // Font-specific ligature substitution for Indic fonts
12522 if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($hd); // *INDIC*
12523 $align = $pos;
12524 if ($this->directionality == 'rtl') {
12525 if ($pos == 'L') { $align = 'R'; }
12526 else if ($pos == 'R') { $align = 'L'; }
12527 }
12528
12529 if ($pos!='L' && (strpos($hd,$this->aliasNbPg)!==false || strpos($hd,$this->aliasNbPgGp)!==false)) {
12530 if (strpos($hd,$this->aliasNbPgGp)!==false) { $type= 'nbpggp'; } else { $type= 'nbpg'; }
12531 $this->_out('{mpdfheader'.$type.' '.$pos.' ff='.$hff.' fs='.$hfst.' fz='.$hfsz.'}');
12532 $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
12533 $this->_out('Q');
12534 }
12535 else {
12536 $this->Cell($headerpgwidth ,$maxfontheight/_MPDFK ,$hd,0,0,$align,0,'',0,0,0,'M');
12537 }
12538 if ($hfcol) { $this->SetTColor($this->ConvertColor(0)); }
12539 }
12540 }
12541 // Return Font to normal
12542 $this->SetFont($this->default_font,'',$this->original_default_font_size);
12543
12544 // LINE
12545
12546 if (isset($h[$side]['line']) && $h[$side]['line']) {
12547 $this->SetLineWidth(0.1);
12548 $this->SetDColor($this->ConvertColor(0));
12549 $this->Line($headerlmargin , $this->y-($maxfontheight*($this->footer_line_spacing)/_MPDFK), $headerlmargin +$headerpgwidth, $this->y-($maxfontheight*($this->footer_line_spacing)/_MPDFK));
12550 }
12551 if ($this->forcePortraitHeaders && $this->CurOrientation=='L' && $this->CurOrientation!=$this->DefOrientation) {
12552 $this->_out('Q');
12553 }
12554 }
12555 $this->processingHeader=false;
12556
12557 }
12558
12559 ///////////////////
12560 // HYPHENATION
12561 ///////////////////
12562 // mPDF 5.6.21
12563 // Hard hyphens
12564 function hardHyphenate($word, $maxWidth) {
12565 // Don't hyphenate web addresses
12566 if (preg_match('/^(http:|www\.)/',$word)) { return array(false,'','',''); }
12567
12568 // Get dictionary
12569 $poss = array();
12570 $softhyphens = array();
12571 $offset = 0;
12572 $p = true;
12573 if ($this->usingCoreFont) {
12574 $wl = strlen($word);
12575 }
12576 else {
12577 $wl = mb_strlen($word,'UTF-8');
12578 }
12579 while($offset < $wl) {
12580 if (!$this->usingCoreFont) {
12581 $p = mb_strpos($word, "-", $offset, 'UTF-8');
12582 }
12583 else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
12584 $p = strpos($word, "-", $offset);
12585 }
12586 if ($p !== false) { $poss[] = $p - count($poss); }
12587 else { break; }
12588 $offset = $p+1;
12589 }
12590 $success = false;
12591 foreach($poss AS $i) {
12592 if ($this->usingCoreFont) {
12593 $a = substr($word,0,$i);
12594 if ($this->GetStringWidth($a.'-') > $maxWidth) { break ; }
12595 $pre = $a;
12596 $post = substr($word,$i,strlen($word));
12597 $prelength = strlen($pre);
12598 }
12599 else {
12600 $a = mb_substr($word,0,$i,'UTF-8');
12601 if ($this->GetStringWidth($a.'-') > $maxWidth) { break ; }
12602 $pre = $a;
12603 $post = mb_substr($word,$i,mb_strlen($word,'UTF-8'),'UTF-8');
12604 $prelength = mb_strlen($pre, 'UTF-8');
12605 }
12606 $success = true;
12607 }
12608 return array($success,$pre,$post,$prelength);
12609 }
12610
12611
12612 /*-- HYPHENATION --*/
12613 ///////////////////
12614 ///////////////////
12615 // HYPHENATION
12616 ///////////////////
12617 // Soft hyphs
12618 function softHyphenate($word, $maxWidth) {
12619 // Don't hyphenate web addresses
12620 if (preg_match('/^(http:|www\.)/',$word)) { return array(false,'','',''); }
12621
12622 // Get dictionary
12623 $poss = array();
12624 $softhyphens = array();
12625 $offset = 0;
12626 $p = true;
12627 if ($this->usingCoreFont) {
12628 $wl = strlen($word);
12629 }
12630 else {
12631 $wl = mb_strlen($word,'UTF-8');
12632 }
12633 while($offset < $wl) {
12634 // Soft Hyphens chr(173)
12635 if (!$this->usingCoreFont) {
12636 $p = mb_strpos($word, "\xc2\xad", $offset, 'UTF-8');
12637 }
12638 else if ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats') {
12639 $p = strpos($word, chr(173), $offset);
12640 }
12641 if ($p !== false) { $poss[] = $p - count($poss); }
12642 else { break; }
12643 $offset = $p+1;
12644 }
12645 $success = false;
12646 foreach($poss AS $i) {
12647 if ($this->usingCoreFont) {
12648 $a = substr($word,0,$i);
12649 if ($this->GetStringWidth($a.'-') > $maxWidth) { break ; }
12650 $pre = $a;
12651 $post = substr($word,$i,strlen($word));
12652 $prelength = strlen($pre);
12653 }
12654 else {
12655 $a = mb_substr($word,0,$i,'UTF-8');
12656 if ($this->GetStringWidth($a.'-') > $maxWidth) { break ; }
12657 $pre = $a;
12658 $post = mb_substr($word,$i,mb_strlen($word,'UTF-8'),'UTF-8');
12659 $prelength = mb_strlen($pre, 'UTF-8');
12660 }
12661 $success = true;
12662 }
12663 return array($success,$pre,$post,$prelength);
12664 }
12665
12666 ///////////////////
12667 // Word hyphenation
12668 function hyphenateWord($word, $maxWidth) {
12669 // Do everything inside this function in utf-8
12670 // Don't hyphenate web addresses
12671 if (preg_match('/^(http:|www\.)/',$word)) { return array(false,'','',''); }
12672
12673
12674 // Get dictionary
12675 if (!$this->loadedSHYdictionary) {
12676 if (file_exists(_MPDF_PATH.'patterns/dictionary.txt')) {
12677 $this->SHYdictionary = file(_MPDF_PATH.'patterns/dictionary.txt',FILE_SKIP_EMPTY_LINES);
12678 foreach($this->SHYdictionary as $entry) {
12679 $entry = trim($entry);
12680 $poss = array();
12681 $offset = 0;
12682 $p = true;
12683 $wl = mb_strlen($entry ,'UTF-8');
12684 while($offset < $wl) {
12685 $p = mb_strpos($entry, '/', $offset, 'UTF-8');
12686 if ($p !== false) { $poss[] = $p - count($poss); }
12687 else { break; }
12688 $offset = $p+1;
12689 }
12690 if (count($poss)) { $this->SHYdictionaryWords[str_replace('/', '', mb_strtolower($entry))] = $poss; }
12691 }
12692 }
12693 $this->loadedSHYdictionary = true;
12694 }
12695
12696 if (!in_array($this->SHYlang,$this->SHYlanguages)) { return array(false,'','',''); }
12697 // If no pattern loaded or not the best one
12698 if (count($this->SHYpatterns) < 1 || ($this->loadedSHYpatterns && $this->loadedSHYpatterns != $this->SHYlang)) {
12699 include(_MPDF_PATH."patterns/" . $this->SHYlang . ".php");
12700 $patterns = explode(' ', $patterns);
12701 $new_patterns = array();
12702 for($i = 0; $i < count($patterns); $i++) {
12703 $value = $patterns[$i];
12704 $new_patterns[preg_replace('/[0-9]/', '', $value)] = $value;
12705 }
12706 $this->SHYpatterns = $new_patterns;
12707 $this->loadedSHYpatterns = $this->SHYlang;
12708 }
12709
12710 if ($this->usingCoreFont) { $word = mb_convert_encoding($word,'UTF-8',$this->mb_enc); }
12711
12712 $prepre = '';
12713 $postpost = '';
12714 $startpunctuation = "\xc2\xab\xc2\xbf\xe2\x80\x98\xe2\x80\x9b\xe2\x80\x9c\xe2\x80\x9f";
12715 $endpunctuation = "\xe2\x80\x9e\xe2\x80\x9d\xe2\x80\x9a\xe2\x80\x99\xc2\xbb";
12716 $pre = '';
12717 $post = '';
12718
12719
12720 if (preg_match('/^(["\''.$startpunctuation .'])+(.{'.$this->SHYcharmin.',})$/u',$word,$m)) {
12721 $prepre = $m[1];
12722 $word = $m[2];
12723 }
12724 if (preg_match('/^(.{'.$this->SHYcharmin.',})([\'\.,;:!?"'.$endpunctuation .']+)$/u',$word,$m)) {
12725 $word = $m[1];
12726 $postpost = $m[2];
12727 }
12728 if(mb_strlen($word,'UTF-8') < $this->SHYcharmin) {
12729 return array(false,'','','');
12730 }
12731 $success = false;
12732
12733 if(isset($this->SHYdictionaryWords[mb_strtolower($word)])) {
12734 foreach($this->SHYdictionaryWords[mb_strtolower($word)] AS $i) {
12735 $a = $prepre . mb_substr($word,0,$i,'UTF-8');
12736 if ($this->usingCoreFont) { $testa = mb_convert_encoding($a,$this->mb_enc,'UTF-8'); }
12737 else { $testa = $a; }
12738 if ($this->GetStringWidth($testa.'-') > $maxWidth) { break ; }
12739 $pre = $a;
12740 $post = mb_substr($word,$i,mb_strlen($word,'UTF-8'),'UTF-8') . $postpost;
12741 $success = true;
12742 }
12743 }
12744
12745 if (!$success) {
12746 $text_word = '_' . $word . '_';
12747 $word_length = mb_strlen($text_word,'UTF-8');
12748
12749 $single_character = preg_split('//u', $text_word);
12750
12751 $text_word = mb_strtolower($text_word,'UTF-8');
12752 $hyphenated_word = array();
12753 $numb3rs = array('0' => true, '1' => true, '2' => true, '3' => true, '4' => true, '5' => true, '6' => true, '7' => true, '8' => true, '9' => true);
12754 for($position = 0; $position <= ($word_length - $this->SHYcharmin); $position++) {
12755 $maxwins = min(($word_length - $position), $this->SHYcharmax);
12756 for($win = $this->SHYcharmin; $win <= $maxwins; $win++) {
12757 if(isset($this->SHYpatterns[mb_substr($text_word, $position, $win,'UTF-8')])) {
12758 $pattern = $this->SHYpatterns[mb_substr($text_word, $position, $win,'UTF-8')];
12759 $digits = 1;
12760 $pattern_length = mb_strlen($pattern,'UTF-8');
12761 for($i = 0; $i < $pattern_length; $i++) {
12762 $char = $pattern[$i];
12763 if(isset($numb3rs[$char])) {
12764 $zero = ($i == 0) ? $position - 1 : $position + $i - $digits;
12765 if(!isset($hyphenated_word[$zero]) || $hyphenated_word[$zero] != $char) $hyphenated_word[$zero] = $char;
12766 $digits++;
12767 }
12768 }
12769 }
12770 }
12771 }
12772
12773 for($i = $this->SHYleftmin; $i <= (mb_strlen($word,'UTF-8') - $this->SHYrightmin); $i++) {
12774 if(isset($hyphenated_word[$i]) && $hyphenated_word[$i] % 2 != 0) {
12775 $a = $prepre . mb_substr($word,0,$i,'UTF-8');
12776 if ($this->usingCoreFont) { $testa = mb_convert_encoding($a,$this->mb_enc,'UTF-8'); }
12777 else { $testa = $a; }
12778 if ($this->GetStringWidth($testa.'-') > $maxWidth + 0.0001) { break ; }
12779 $pre = $a;
12780 $post = mb_substr($word,$i,mb_strlen($word,'UTF-8'),'UTF-8') . $postpost;
12781 $success = true;
12782 }
12783 }
12784 }
12785 if ($this->usingCoreFont) {
12786 $pre = mb_convert_encoding($pre,$this->mb_enc,'UTF-8');
12787 $post = mb_convert_encoding($post,$this->mb_enc,'UTF-8');
12788 $prelength = strlen($pre);
12789 }
12790 else {
12791 $prelength = mb_strlen($pre);
12792 }
12793 return array($success,$pre,$post,$prelength);
12794
12795 }
12796 /*-- END HYPHENATION --*/
12797
12798
12799 /*-- HTML-CSS --*/
12800 ///////////////////
12801 /// HTML parser ///
12802 ///////////////////
12803 function WriteHTML($html,$sub=0,$init=true,$close=true) {
12804 // $sub ADDED - 0 = default; 1=headerCSS only; 2=HTML body (parts) only; 3 - HTML parses only
12805 // 4 - writes HTML headers
12806 // $close Leaves buffers etc. in current state, so that it can continue a block etc.
12807 // $init - Clears and sets buffers to Top level block etc.
12808
12809 if (empty($html)) { $html = ''; }
12810 if ($this->progressBar) { $this->UpdateProgressBar(1,0,'Parsing CSS & Headers'); } // *PROGRESS-BAR*
12811
12812 if ($init) {
12813 $this->headerbuffer='';
12814 $this->textbuffer = array();
12815 $this->fixedPosBlockSave = array();
12816 }
12817 if ($sub == 1) { $html = '<style> '.$html.' </style>'; } // stylesheet only
12818
12819 if ($this->allow_charset_conversion) {
12820 if ($sub < 1) {
12821 $this->ReadCharset($html);
12822 }
12823 if ($this->charset_in && $sub!=4) { // mPDF 5.4.14
12824 $success = iconv($this->charset_in,'UTF-8//TRANSLIT',$html);
12825 if ($success) { $html = $success; }
12826 }
12827 }
12828 $html = $this->purify_utf8($html,false);
12829 if ($init) {
12830 $this->blklvl = 0;
12831 $this->lastblocklevelchange = 0;
12832 $this->blk = array();
12833 $this->initialiseBlock($this->blk[0]);
12834 $this->blk[0]['width'] =& $this->pgwidth;
12835 $this->blk[0]['inner_width'] =& $this->pgwidth;
12836 $this->blk[0]['blockContext'] = $this->blockContext;
12837 }
12838
12839 $zproperties = array();
12840 if ($sub < 2) {
12841 $this->ReadMetaTags($html);
12842
12843 // mPDF 5.6.18
12844 if (preg_match('/<base[^>]*href=["\']([^"\'>]*)["\']/i', $html, $m)) {
12845 $this->SetBasePath($m[1]);
12846 }
12847 // NB default stylesheet now in mPDF.css - read on initialising class
12848 $html = $this->cssmgr->ReadCSS($html);
12849
12850 if ($this->useLang && !$this->usingCoreFont && preg_match('/<html [^>]*lang=[\'\"](.*?)[\'\"]/ism',$html,$m)) {
12851 $html_lang = $m[1];
12852 }
12853
12854 if (preg_match('/<html [^>]*dir=[\'\"]\s*rtl\s*[\'\"]/ism',$html)) {
12855 $zproperties['DIRECTION'] = 'rtl';
12856 }
12857
12858 // allow in-line CSS for body tag to be parsed // Get <body> tag inline CSS
12859 if (preg_match('/<body([^>]*)>(.*?)<\/body>/ism',$html,$m) || preg_match('/<body([^>]*)>(.*)$/ism',$html,$m)) {
12860 $html = $m[2];
12861 // Changed to allow style="background: url('bg.jpg')"
12862 if (preg_match('/style=[\"](.*?)[\"]/ism',$m[1],$mm) || preg_match('/style=[\'](.*?)[\']/ism',$m[1],$mm)) {
12863 $zproperties = $this->cssmgr->readInlineCSS($mm[1]);
12864 }
12865 if (preg_match('/dir=[\'\"]\s*rtl\s*[\'\"]/ism',$m[1])) {
12866 $zproperties['DIRECTION'] = 'rtl';
12867 }
12868 if (isset($html_lang) && $html_lang) { $zproperties['LANG'] = $html_lang; }
12869 if ($this->useLang && !$this->onlyCoreFonts && preg_match('/lang=[\'\"](.*?)[\'\"]/ism',$m[1],$mm)) {
12870 $zproperties['LANG'] = $mm[1];
12871 }
12872
12873 }
12874 }
12875 $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
12876 if ($zproperties) { $properties = $this->cssmgr->array_merge_recursive_unique($properties,$zproperties); }
12877
12878 if (isset($properties['DIRECTION']) && $properties['DIRECTION']) {
12879 $this->cssmgr->CSS['BODY']['DIRECTION'] = $properties['DIRECTION'];
12880 }
12881 if (!isset($this->cssmgr->CSS['BODY']['DIRECTION'])) {
12882 $this->cssmgr->CSS['BODY']['DIRECTION'] = $this->directionality;
12883 }
12884 else { $this->SetDirectionality($this->cssmgr->CSS['BODY']['DIRECTION']); }
12885
12886 $this->setCSS($properties,'','BODY');
12887 $this->blk[0]['InlineProperties'] = $this->saveInlineProperties();
12888
12889 if ($sub == 1) { return ''; }
12890 if (!isset($this->cssmgr->CSS['BODY'])) { $this->cssmgr->CSS['BODY'] = array(); }
12891
12892 /*-- BACKGROUNDS --*/
12893 if (isset($properties['BACKGROUND-GRADIENT'])) {
12894 $this->bodyBackgroundGradient = $properties['BACKGROUND-GRADIENT'];
12895 }
12896
12897 if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE']) {
12898 $ret = $this->SetBackground($properties, $this->pgwidth);
12899 if ($ret) { $this->bodyBackgroundImage = $ret; }
12900 }
12901 /*-- END BACKGROUNDS --*/
12902
12903 /*-- CSS-PAGE --*/
12904 // If page-box is set
12905 if ($this->state==0 && isset($this->cssmgr->CSS['@PAGE']) && $this->cssmgr->CSS['@PAGE'] ) {
12906 $this->page_box['current'] = '';
12907 $this->page_box['using'] = true;
12908 list($pborientation,$pbmgl,$pbmgr,$pbmgt,$pbmgb,$pbmgh,$pbmgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS('', false, 'O');
12909 $this->DefOrientation = $this->CurOrientation = $pborientation;
12910 $this->orig_lMargin = $this->DeflMargin = $pbmgl;
12911 $this->orig_rMargin = $this->DefrMargin = $pbmgr;
12912 $this->orig_tMargin = $this->tMargin = $pbmgt;
12913 $this->orig_bMargin = $this->bMargin = $pbmgb;
12914 $this->orig_hMargin = $this->margin_header = $pbmgh;
12915 $this->orig_fMargin = $this->margin_footer = $pbmgf;
12916 list($pborientation,$pbmgl,$pbmgr,$pbmgt,$pbmgb,$pbmgh,$pbmgf,$hname,$fname,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat) = $this->SetPagedMediaCSS('', true, 'O'); // first page
12917 $this->show_marks = $marks;
12918 if ($hname && !preg_match('/^html_(.*)$/i',$hname)) $this->firstPageBoxHeader = $hname;
12919 if ($fname && !preg_match('/^html_(.*)$/i',$fname)) $this->firstPageBoxFooter = $fname;
12920 }
12921 /*-- END CSS-PAGE --*/
12922
12923 $parseonly = false;
12924 $this->bufferoutput = false;
12925 if ($sub == 3) {
12926 $parseonly = true;
12927 // Close any open block tags
12928 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
12929 // Output any text left in buffer
12930 if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); }
12931 $this->textbuffer=array();
12932 }
12933 else if ($sub == 4) {
12934 // Close any open block tags
12935 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
12936 // Output any text left in buffer
12937 if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); }
12938 $this->bufferoutput = true;
12939 $this->textbuffer=array();
12940 $this->headerbuffer='';
12941 $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
12942 $this->setCSS($properties,'','BODY');
12943 }
12944
12945 mb_internal_encoding('UTF-8');
12946
12947 $html = $this->AdjustHTML($html, $this->tabSpaces); //Try to make HTML look more like XHTML
12948
12949 if ($this->autoFontGroups) { $html = $this->AutoFont($html); }
12950
12951 /*-- HTMLHEADERS-FOOTERS --*/
12952 preg_match_all('/<htmlpageheader([^>]*)>(.*?)<\/htmlpageheader>/si',$html,$h);
12953 for($i=0;$i<count($h[1]);$i++) {
12954 if (preg_match('/name=[\'|\"](.*?)[\'|\"]/',$h[1][$i],$n)) {
12955 $this->pageHTMLheaders[$n[1]]['html'] = $h[2][$i];
12956 $this->pageHTMLheaders[$n[1]]['h'] = $this->_gethtmlheight($h[2][$i]);
12957 }
12958 }
12959 preg_match_all('/<htmlpagefooter([^>]*)>(.*?)<\/htmlpagefooter>/si',$html,$f);
12960 for($i=0;$i<count($f[1]);$i++) {
12961 if (preg_match('/name=[\'|\"](.*?)[\'|\"]/',$f[1][$i],$n)) {
12962 $this->pageHTMLfooters[$n[1]]['html'] = $f[2][$i];
12963 $this->pageHTMLfooters[$n[1]]['h'] = $this->_gethtmlheight($f[2][$i]);
12964 }
12965 }
12966 /*-- END HTMLHEADERS-FOOTERS --*/
12967 $html = preg_replace('/<htmlpageheader.*?<\/htmlpageheader>/si','',$html);
12968 $html = preg_replace('/<htmlpagefooter.*?<\/htmlpagefooter>/si','',$html);
12969
12970 if($this->state==0 && $sub!=1 && $sub!=3 && $sub!=4) {
12971 $this->AddPage($this->CurOrientation);
12972 }
12973
12974
12975 /*-- HTMLHEADERS-FOOTERS --*/
12976
12977 if (isset($hname) && preg_match('/^html_(.*)$/i',$hname,$n)) $this->SetHTMLHeader($this->pageHTMLheaders[$n[1]],'O',true);
12978 if (isset($fname) && preg_match('/^html_(.*)$/i',$fname,$n)) $this->SetHTMLFooter($this->pageHTMLfooters[$n[1]],'O');
12979
12980 /*-- END HTMLHEADERS-FOOTERS --*/
12981
12982 $html=str_replace('<?','< ',$html); //Fix '<?XML' bug from HTML code generated by MS Word
12983
12984 $this->checkSIP = false;
12985 $this->checkSMP = false;
12986 $this->checkCJK = false;
12987 if ($this->onlyCoreFonts) { $html = $this->SubstituteChars($html); }
12988 else {
12989 if (preg_match("/([".$this->pregRTLchars."])/u", $html)) { $this->biDirectional = true; } // *RTL*
12990 if (preg_match("/([\x{20000}-\x{2FFFF}])/u", $html)) { $this->checkSIP = true; }
12991 if (preg_match("/([\x{10000}-\x{1FFFF}])/u", $html)) { $this->checkSMP = true; }
12992 /*-- CJK-FONTS --*/
12993 if (preg_match("/([".$this->pregCJKchars."])/u", $html)) { $this->checkCJK = true; }
12994 /*-- END CJK-FONTS --*/
12995 }
12996
12997 // Don't allow non-breaking spaces that are converted to substituted chars or will break anyway and mess up table width calc.
12998 $html = str_replace('<tta>160</tta>',chr(32),$html);
12999 $html = str_replace('</tta><tta>','|',$html);
13000 $html = str_replace('</tts><tts>','|',$html);
13001 $html = str_replace('</ttz><ttz>','|',$html);
13002
13003 //Add new supported tags in the DisableTags function
13004 $html=strip_tags($html,$this->enabledtags); //remove all unsupported tags, but the ones inside the 'enabledtags' string
13005
13006 //Explode the string in order to parse the HTML code
13007 $a=preg_split('/<(.*?)>/ms',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
13008 // ? more accurate regexp that allows e.g. <a name="Silly <name>">
13009 // if changing - also change in fn.SubstituteChars()
13010 // $a = preg_split ('/<((?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+)>/ms', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
13011
13012 if ($this->mb_enc) {
13013 mb_internal_encoding($this->mb_enc);
13014 }
13015 $pbc = 0;
13016 if ($this->progressBar) { $this->UpdateProgressBar(1,0); } // *PROGRESS-BAR*
13017 $this->subPos = -1;
13018 $cnt = count($a);
13019 for($i=0;$i<$cnt; $i++) {
13020 $e = $a[$i];
13021 if($i%2==0) {
13022 //TEXT
13023 if ($this->blk[$this->blklvl]['hide']) { continue; }
13024 if ($this->inlineDisplayOff) { continue; }
13025 if ($this->inMeter) { continue; } // mPDF 5.5.09
13026
13027 if ($this->inFixedPosBlock) { $this->fixedPosBlock .= $e; continue; } // *CSS-POSITION*
13028 if (strlen($e) == 0) { continue; }
13029
13030 $e = strcode2utf($e);
13031 $e = $this->lesser_entity_decode($e);
13032
13033 if ($this->usingCoreFont) {
13034 // If core font is selected in document which is not onlyCoreFonts - substitute with non-core font
13035 if ($this->useSubstitutions && !$this->onlyCoreFonts && $this->subPos<$i && !$this->specialcontent) {
13036 $cnt += $this->SubstituteCharsNonCore($a, $i, $e);
13037 }
13038 // CONVERT ENCODING
13039 $e = mb_convert_encoding($e,$this->mb_enc,'UTF-8');
13040 // mPDF 5.6.41
13041 if ($this->toupper) { $e = mb_strtoupper($e,$this->mb_enc); }
13042 if ($this->tolower) { $e = mb_strtolower($e,$this->mb_enc); }
13043 if ($this->capitalize) { $e = mb_convert_case($e, MB_CASE_TITLE, "UTF-8"); }
13044 }
13045 else {
13046 if ($this->checkSIP && $this->CurrentFont['sipext'] && $this->subPos<$i && !$this->specialcontent) {
13047 $cnt += $this->SubstituteCharsSIP($a, $i, $e);
13048 }
13049
13050 if ($this->useSubstitutions && !$this->onlyCoreFonts && $this->CurrentFont['type']!='Type0' && $this->subPos<$i && !$this->specialcontent) {
13051 // mPDF 5.6.62 removes U+200E/U+200F LTR and RTL mark and U+200C/U+200D Zero-width Joiner and Non-joiner
13052 $e = preg_replace("/[\xe2\x80\x8c\xe2\x80\x8d\xe2\x80\x8e\xe2\x80\x8f]/u",'',$e);
13053 $cnt += $this->SubstituteCharsMB($a, $i, $e);
13054 }
13055 if ($this->biDirectional) { // *RTL*
13056 // mPDF 5.7+
13057 $e = preg_replace_callback("/([".$this->pregRTLchars."]+)/u", array($this, 'arabJoinPregCallback'), $e ); // *RTL*
13058 } // *RTL*
13059 // Font-specific ligature substitution for Indic fonts
13060 if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($e); // *INDIC*
13061
13062 // mPDF 5.6.62 removes U+200E/U+200F LTR and RTL mark and U+200C/U+200D Zero-width Joiner and Non-joiner
13063 $e = preg_replace("/[\xe2\x80\x8c\xe2\x80\x8d\xe2\x80\x8e\xe2\x80\x8f]/u",'',$e);
13064
13065 if ($this->toupper) { $e = mb_strtoupper($e,$this->mb_enc); }
13066 if ($this->tolower) { $e = mb_strtolower($e,$this->mb_enc); }
13067 if ($this->capitalize) { $e = mb_convert_case($e, MB_CASE_TITLE, "UTF-8"); }
13068 }
13069 if (($this->tts) || ($this->ttz) || ($this->tta)) {
13070 $es = explode('|',$e);
13071 $e = '';
13072 foreach($es AS $val) {
13073 $e .= chr($val);
13074 }
13075 }
13076 //Adjust lineheight
13077
13078 // FORM ELEMENTS
13079 if ($this->specialcontent) {
13080 /*-- FORMS --*/
13081 //SELECT tag (form element)
13082 if ($this->specialcontent == "type=select") {
13083 $e = ltrim($e);
13084 $stringwidth = $this->GetStringWidth($e);
13085 if (!isset($this->selectoption['MAXWIDTH']) || $stringwidth > $this->selectoption['MAXWIDTH']) { $this->selectoption['MAXWIDTH'] = $stringwidth; }
13086 if (!isset($this->selectoption['SELECTED']) || $this->selectoption['SELECTED'] == '') { $this->selectoption['SELECTED'] = $e; }
13087 // mPDD 1.4 Active Forms
13088 if (isset($this->selectoption['ACTIVE']) && $this->selectoption['ACTIVE']) {
13089 $this->selectoption['ITEMS'][]=array('exportValue'=>$this->selectoption['currentVAL'], 'content'=>$e, 'selected'=>$this->selectoption['currentSEL']);
13090 }
13091 }
13092 // TEXTAREA
13093 else {
13094 $objattr = unserialize($this->specialcontent);
13095 $objattr['text'] = $e;
13096 $te = "\xbb\xa4\xactype=textarea,objattr=".serialize($objattr)."\xbb\xa4\xac";
13097 if ($this->tdbegin) {
13098 $this->_saveCellTextBuffer($te, $this->HREF);
13099 }
13100 else {
13101 $this->_saveTextBuffer($te, $this->HREF);
13102 }
13103 }
13104 /*-- END FORMS --*/
13105 }
13106
13107 // TABLE
13108 else if ($this->tableLevel) {
13109 /*-- TABLES --*/
13110 if ($this->tdbegin) {
13111 if (($this->ignorefollowingspaces) && !$this->ispre) { $e = ltrim($e); }
13112 if ($e || $e==='0') {
13113 if (($this->blockjustfinished || $this->listjustfinished) && $this->cell[$this->row][$this->col]['s']>0) {
13114 $this->_saveCellTextBuffer("\n");
13115 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
13116 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
13117 }
13118 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
13119 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
13120 }
13121 $this->cell[$this->row][$this->col]['s'] = 0;// reset
13122 }
13123 $this->blockjustfinished=false;
13124 $this->listjustfinished=false;
13125
13126 $this->_saveCellTextBuffer($e, $this->HREF);
13127
13128 if (!isset($this->cell[$this->row][$this->col]['R']) || !$this->cell[$this->row][$this->col]['R']) {
13129 if (isset($this->cell[$this->row][$this->col]['s'])) {
13130 $this->cell[$this->row][$this->col]['s'] += $this->GetStringWidth($e, false);
13131 }
13132 else { $this->cell[$this->row][$this->col]['s'] = $this->GetStringWidth($e, false); }
13133 if (!empty($this->spanborddet)) {
13134 $this->cell[$this->row][$this->col]['s'] += $this->spanborddet['L']['w'] + $this->spanborddet['R']['w'];
13135 }
13136 }
13137
13138 if ($this->checkCJK && preg_match("/([".$this->pregCJKchars."])/u", $e)) { $this->tableCJK = true; } // *CJK-FONTS*
13139
13140 // mPDF 5.6.13 Decimal mark alignment
13141 if (substr($this->cell[$this->row][$this->col]['a'],0,1) == 'D') {
13142 $dp = $this->decimal_align[substr($this->cell[$this->row][$this->col]['a'],0,2)];
13143 $s = preg_split('/'.preg_quote($dp,'/').'/', $e, 2); // ? needs to be /u if not core
13144 $s0 = $this->GetStringWidth($s[0], false);
13145 if ($s[1]) { $s1 = $this->GetStringWidth(($s[1].$dp), false); }
13146 else $s1 = 0;
13147 if (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'])) {
13148 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'] = $s0;
13149 }
13150 else {
13151 $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']);
13152 }
13153 if (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'])) {
13154 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'] = $s1;
13155 }
13156 else {
13157 $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']);
13158 }
13159 }
13160
13161 if ($this->tableLevel==1 && $this->useGraphs) {
13162 $this->graphs[$this->currentGraphId]['data'][$this->row][$this->col] = $e;
13163 }
13164 $this->nestedtablejustfinished = false;
13165 $this->linebreakjustfinished=false;
13166 }
13167 }
13168 /*-- END TABLES --*/
13169 }
13170 // ALL ELSE
13171 else {
13172 if ($this->ignorefollowingspaces and !$this->ispre) { $e = ltrim($e); }
13173 if ($e || $e==='0') $this->_saveTextBuffer($e, $this->HREF);
13174 }
13175 }
13176
13177
13178 else { // TAG **
13179
13180 if($e[0]=='/') {
13181 /*-- PROGRESS-BAR --*/
13182 if ($this->progressBar) { // 10% increments
13183 if (intval($i*10/$cnt) != $pbc) { $pbc = intval($i*10/$cnt); $this->UpdateProgressBar(1,$pbc*10,$tag); }
13184 }
13185 /*-- END PROGRESS-BAR --*/
13186
13187
13188 // Check for tags where HTML specifies optional end tags,
13189 // and/or does not allow nesting e.g. P inside P, or
13190 $endtag = trim(strtoupper(substr($e,1))); // mPDF 5.4.20
13191 if($this->blk[$this->blklvl]['hide']) {
13192 if (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags)) {
13193 unset($this->blk[$this->blklvl]);
13194 $this->blklvl--;
13195 }
13196 continue;
13197 }
13198
13199 /*-- CSS-POSITION --*/
13200 if ($this->inFixedPosBlock) {
13201 if (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags)) { $this->fixedPosBlockDepth--; }
13202 if ($this->fixedPosBlockDepth == 0) {
13203 $this->fixedPosBlockSave[] = array($this->fixedPosBlock, $this->fixedPosBlockBBox, $this->page);
13204 $this->fixedPosBlock = '';
13205 $this->inFixedPosBlock = false;
13206 continue;
13207 }
13208 $this->fixedPosBlock .= '<'.$e.'>';
13209 continue;
13210 }
13211 /*-- END CSS-POSITION --*/
13212 if ($this->allow_html_optional_endtags && !$parseonly) {
13213 if (($endtag == 'DIV' || $endtag =='FORM' || $endtag =='CENTER') && $this->lastoptionaltag == 'P') { $this->CloseTag($this->lastoptionaltag ); }
13214 if ($this->lastoptionaltag == 'LI' && $endtag == 'OL') { $this->CloseTag($this->lastoptionaltag ); }
13215 if ($this->lastoptionaltag == 'LI' && $endtag == 'UL') { $this->CloseTag($this->lastoptionaltag ); }
13216 if ($this->lastoptionaltag == 'DD' && $endtag == 'DL') { $this->CloseTag($this->lastoptionaltag ); }
13217 if ($this->lastoptionaltag == 'DT' && $endtag == 'DL') { $this->CloseTag($this->lastoptionaltag ); }
13218 if ($this->lastoptionaltag == 'OPTION' && $endtag == 'SELECT') { $this->CloseTag($this->lastoptionaltag ); }
13219 /*-- TABLES --*/
13220 if ($endtag == 'TABLE') {
13221 if ($this->lastoptionaltag == 'THEAD' || $this->lastoptionaltag == 'TBODY' || $this->lastoptionaltag == 'TFOOT') {
13222 $this->CloseTag($this->lastoptionaltag);
13223 }
13224 if ($this->lastoptionaltag == 'TR') { $this->CloseTag('TR'); }
13225 if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag ); $this->CloseTag('TR'); }
13226 }
13227 if ($endtag == 'THEAD' || $endtag == 'TBODY' || $endtag == 'TFOOT') {
13228 if ($this->lastoptionaltag == 'TR') { $this->CloseTag('TR'); }
13229 if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag ); $this->CloseTag('TR'); }
13230 }
13231 if ($endtag == 'TR') {
13232 if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag ); }
13233 }
13234 /*-- END TABLES --*/
13235 }
13236 $this->CloseTag($endtag);
13237 }
13238
13239 else { // OPENING TAG
13240 if($this->blk[$this->blklvl]['hide']) {
13241 if (strpos($e,' ')) { $te = strtoupper(substr($e,0,strpos($e,' '))); }
13242 else { $te = strtoupper($e); }
13243 if (in_array($te, $this->outerblocktags) || in_array($te, $this->innerblocktags)) {
13244 $this->blklvl++;
13245 $this->blk[$this->blklvl]['hide']=true;
13246 }
13247 continue;
13248 }
13249
13250 /*-- CSS-POSITION --*/
13251 if ($this->inFixedPosBlock) {
13252 if (strpos($e,' ')) { $te = strtoupper(substr($e,0,strpos($e,' '))); }
13253 else { $te = strtoupper($e); }
13254 $this->fixedPosBlock .= '<'.$e.'>';
13255 if (in_array($te, $this->outerblocktags) || in_array($te, $this->innerblocktags)) { $this->fixedPosBlockDepth++; }
13256 continue;
13257 }
13258 /*-- END CSS-POSITION --*/
13259 $regexp = '|=\'(.*?)\'|s'; // eliminate single quotes, if any
13260 $e = preg_replace($regexp,"=\"\$1\"",$e);
13261 // changes anykey=anyvalue to anykey="anyvalue" (only do this inside [some] tags)
13262 if (substr($e,0,10)!='pageheader' && substr($e,0,10)!='pagefooter' && substr($e,0,12)!='tocpagebreak') { // mPDF 5.6.69
13263 $regexp = '| (\\w+?)=([^\\s>"]+)|si';
13264 $e = preg_replace($regexp," \$1=\"\$2\"",$e);
13265 }
13266
13267 $e = preg_replace('/ (\\S+?)\s*=\s*"/i', " \\1=\"", $e);
13268
13269 //Fix path values, if needed
13270 $orig_srcpath = '';
13271 if ((stristr($e,"href=") !== false) or (stristr($e,"src=") !== false) ) {
13272 $regexp = '/ (href|src)\s*=\s*"(.*?)"/i';
13273 preg_match($regexp,$e,$auxiliararray);
13274 if (isset($auxiliararray[2])) { $path = $auxiliararray[2]; }
13275 else { $path = ''; }
13276 if (trim($path) != '' && !(stristr($e,"src=") !== false && substr($path,0,4)=='var:')) {
13277 $orig_srcpath = $path;
13278 $this->GetFullPath($path);
13279 $regexp = '/ (href|src)="(.*?)"/i';
13280 $e = preg_replace($regexp,' \\1="'.$path.'"',$e);
13281 }
13282 }//END of Fix path values
13283
13284
13285 //Extract attributes
13286 $contents=array();
13287 $contents1=array(); // mPDF 5.5.17
13288 $contents2=array();
13289 // Changed to allow style="background: url('bg.jpg')"
13290 // mPDF 5.5.17 Changed to improve performance; maximum length of \S (attribute) = 16
13291 // mPDF 5.6.30 Increase allowed attribute name to 32 - cutting off "toc-even-header-name" etc.
13292 preg_match_all('/\\S{1,32}=["][^"]*["]/',$e,$contents1);
13293 preg_match_all('/\\S{1,32}=[\'][^\']*[\']/i',$e,$contents2);
13294
13295 $contents = array_merge($contents1, $contents2);
13296 preg_match('/\\S+/',$e,$a2);
13297 $tag=strtoupper($a2[0]);
13298 $attr=array();
13299 if ($orig_srcpath) { $attr['ORIG_SRC'] = $orig_srcpath; }
13300 if (!empty($contents)) {
13301 foreach($contents[0] as $v) {
13302 // Changed to allow style="background: url('bg.jpg')"
13303 if(preg_match('/^([^=]*)=["]?([^"]*)["]?$/',$v,$a3) || preg_match('/^([^=]*)=[\']?([^\']*)[\']?$/',$v,$a3)) {
13304 if (strtoupper($a3[1])=='ID' || strtoupper($a3[1])=='CLASS') { // 4.2.013 Omits STYLE
13305 $attr[strtoupper($a3[1])]=trim(strtoupper($a3[2]));
13306 }
13307 // includes header-style-right etc. used for <pageheader>
13308 else if (preg_match('/^(HEADER|FOOTER)-STYLE/i',$a3[1])) {
13309 $attr[strtoupper($a3[1])]=trim(strtoupper($a3[2]));
13310 }
13311 else {
13312 $attr[strtoupper($a3[1])]=trim($a3[2]);
13313 }
13314 }
13315 }
13316 }
13317 $this->OpenTag($tag,$attr);
13318 /*-- CSS-POSITION --*/
13319 if ($this->inFixedPosBlock) {
13320 $this->fixedPosBlockBBox = array($tag,$attr, $this->x, $this->y);
13321 $this->fixedPosBlock = '';
13322 $this->fixedPosBlockDepth = 1;
13323 }
13324 /*-- END CSS-POSITION --*/
13325 // mPDF 5.5.09
13326 if (preg_match('/\/$/',$e)) { $this->closeTag($tag); }
13327
13328 }
13329
13330 } // end TAG
13331 } //end of foreach($a as $i=>$e)
13332
13333 if ($close) {
13334
13335 // Close any open block tags
13336 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
13337
13338 // Output any text left in buffer
13339 if (count($this->textbuffer) && !$parseonly) { $this->printbuffer($this->textbuffer); }
13340 if (!$parseonly) $this->textbuffer=array();
13341
13342 /*-- CSS-FLOAT --*/
13343 // If ended with a float, need to move to end page
13344 $currpos = $this->page*1000 + $this->y;
13345 if (isset($this->blk[$this->blklvl]['float_endpos']) && $this->blk[$this->blklvl]['float_endpos'] > $currpos) {
13346 $old_page = $this->page;
13347 $new_page = intval($this->blk[$this->blklvl]['float_endpos'] /1000);
13348 if ($old_page != $new_page) {
13349 $s = $this->PrintPageBackgrounds();
13350 // Writes after the marker so not overwritten later by page background etc.
13351 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
13352 $this->pageBackgrounds = array();
13353 $this->page = $new_page;
13354 $this->ResetMargins();
13355 $this->Reset();
13356 $this->pageoutput[$this->page] = array();
13357 }
13358 $this->y = (($this->blk[$this->blklvl]['float_endpos'] *1000) % 1000000)/1000; // mod changes operands to integers before processing
13359 }
13360 /*-- END CSS-FLOAT --*/
13361
13362 /*-- CSS-IMAGE-FLOAT --*/
13363 $this->printfloatbuffer();
13364 /*-- END CSS-IMAGE-FLOAT --*/
13365
13366 //Create Internal Links, if needed
13367 if (!empty($this->internallink) ) {
13368 foreach($this->internallink as $k=>$v) {
13369 if (strpos($k,"#") !== false ) { continue; } //ignore
13370 $ypos = $v['Y'];
13371 $pagenum = $v['PAGE'];
13372 $sharp = "#";
13373 while (array_key_exists($sharp.$k,$this->internallink)) {
13374 $internallink = $this->internallink[$sharp.$k];
13375 $this->SetLink($internallink,$ypos,$pagenum);
13376 $sharp .= "#";
13377 }
13378 }
13379 }
13380
13381 $this->linemaxfontsize = '';
13382 $this->lineheight_correction = $this->default_lineheight_correction;
13383
13384 $this->bufferoutput = false;
13385
13386 /*-- CSS-POSITION --*/
13387 if (count($this->fixedPosBlockSave) && $sub != 4) {
13388 foreach($this->fixedPosBlockSave AS $fpbs) {
13389 $old_page = $this->page;
13390 $this->page = $fpbs[2];
13391 $this->WriteFixedPosHTML($fpbs[0], 0, 0, 100, 100,'auto', $fpbs[1]); // 0,0,10,10 are overwritten by bbox
13392 $this->page = $old_page;
13393 }
13394 }
13395 /*-- END CSS-POSITION --*/
13396
13397 }
13398 }
13399
13400 /*-- CSS-POSITION --*/
13401
13402 function WriteFixedPosHTML($html='',$x, $y, $w, $h, $overflow='visible', $bounding=array()) {
13403 // $overflow can be 'hidden', 'visible' or 'auto' - 'auto' causes autofit to size
13404 // Annotations disabled - enabled in mPDF 5.0
13405 // Links do work
13406 // Will always go on current page (or start Page 1 if required)
13407 // Probably INCOMPATIBLE WITH keep with table, columns etc.
13408 // Called externally or interally via <div style="position: [fixed|absolute]">
13409 // When used internally, $x $y $w $h and $overflow are all overridden by $bounding
13410
13411 $overflow = strtolower($overflow);
13412 if($this->state==0) {
13413 $this->AddPage($this->CurOrientation);
13414 }
13415 $save_y = $this->y;
13416 $save_x = $this->x;
13417 $this->fullImageHeight = $this->h;
13418 $save_cols = false;
13419 /*-- COLUMNS --*/
13420 if ($this->ColActive) {
13421 $save_cols = true;
13422 $save_nbcol = $this->NbCol; // other values of gap and vAlign will not change by setting Columns off
13423 $this->SetColumns(0);
13424 }
13425 /*-- END COLUMNS --*/
13426 $save_annots = $this->title2annots; // *ANNOTATIONS*
13427 $this->writingHTMLheader = true; // a FIX to stop pagebreaks etc.
13428 $this->writingHTMLfooter = true;
13429 $this->InFooter = true; // suppresses autopagebreaks
13430 $save_bgs = $this->pageBackgrounds;
13431 $checkinnerhtml = preg_replace('/\s/','',$html);
13432
13433 if ($w > $this->w) { $x = 0; $w = $this->w; }
13434 if ($h > $this->h) { $y = 0; $h = $this->h; }
13435 if ($x > $this->w) { $x = $this->w - $w; }
13436 if ($y > $this->h) { $y = $this->h - $h; }
13437
13438 if (!empty($bounding)) {
13439 // $cont_ containing block = full physical page (position: absolute) or page inside margins (position: fixed)
13440 // $bbox_ Bounding box is the <div> which is positioned absolutely/fixed
13441 // top/left/right/bottom/width/height/background*/border*/padding*/margin* are taken from bounding
13442 // font*[family/size/style/weight]/line-height/text*[align/decoration/transform/indent]/color are transferred to $inner
13443 // as an enclosing <div> (after having checked ID/CLASS)
13444 // $x, $y, $w, $h are inside of $bbox_ = containing box for $inner_
13445 // $inner_ InnerHTML is the contents of that block to be output
13446 $tag = $bounding[0];
13447 $attr = $bounding[1];
13448 $orig_x0 = $bounding[2];
13449 $orig_y0 = $bounding[3];
13450
13451 // As in WriteHTML() initialising
13452 $this->blklvl = 0;
13453 $this->lastblocklevelchange = 0;
13454 $this->blk = array();
13455 $this->initialiseBlock($this->blk[0]);
13456
13457 $this->blk[0]['width'] =& $this->pgwidth;
13458 $this->blk[0]['inner_width'] =& $this->pgwidth;
13459
13460 $this->blk[0]['blockContext'] = $this->blockContext;
13461
13462 $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
13463 $this->setCSS($properties,'','BODY');
13464 $this->blklvl = 1;
13465 $this->initialiseBlock($this->blk[1]);
13466 $this->blk[1]['tag'] = $tag;
13467 $this->blk[1]['attr'] = $attr;
13468 $this->Reset();
13469 $p = $this->cssmgr->MergeCSS('BLOCK',$tag,$attr);
13470 if (isset($p['ROTATE']) && ($p['ROTATE']==90 || $p['ROTATE']==-90)) { $rotate = $p['ROTATE']; }
13471 else { $rotate = 0; }
13472 if (isset($p['OVERFLOW'])) { $overflow = strtolower($p['OVERFLOW']); }
13473 if (strtolower($p['POSITION']) == 'fixed') {
13474 $cont_w = $this->pgwidth; // $this->blk[0]['inner_width'];
13475 $cont_h = $this->h - $this->tMargin - $this->bMargin;
13476 $cont_x = $this->lMargin;
13477 $cont_y = $this->tMargin;
13478 }
13479 else {
13480 $cont_w = $this->w; // ABSOLUTE;
13481 $cont_h = $this->h;
13482 $cont_x = 0;
13483 $cont_y = 0;
13484 }
13485
13486 // Pass on in-line properties to the innerhtml
13487 $css = '';
13488 if (isset($p['TEXT-ALIGN'])) { $css .= 'text-align: '.strtolower($p['TEXT-ALIGN']).'; '; }
13489 if (isset($p['TEXT-TRANSFORM'])) { $css .= 'text-transform: '.strtolower($p['TEXT-TRANSFORM']).'; '; }
13490 if (isset($p['TEXT-INDENT'])) { $css .= 'text-indent: '.strtolower($p['TEXT-INDENT']).'; '; }
13491 if (isset($p['TEXT-DECORATION'])) { $css .= 'text-decoration: '.strtolower($p['TEXT-DECORATION']).'; '; }
13492 if (isset($p['FONT-FAMILY'])) { $css .= 'font-family: '.strtolower($p['FONT-FAMILY']).'; '; }
13493 if (isset($p['FONT-STYLE'])) { $css .= 'font-style: '.strtolower($p['FONT-STYLE']).'; '; }
13494 if (isset($p['FONT-WEIGHT'])) { $css .= 'font-weight: '.strtolower($p['FONT-WEIGHT']).'; '; }
13495 if (isset($p['FONT-SIZE'])) { $css .= 'font-size: '.strtolower($p['FONT-SIZE']).'; '; }
13496 if (isset($p['LINE-HEIGHT'])) { $css .= 'line-height: '.strtolower($p['LINE-HEIGHT']).'; '; }
13497 if (isset($p['TEXT-SHADOW'])) { $css .= 'text-shadow: '.strtolower($p['TEXT-SHADOW']).'; '; }
13498 if (isset($p['LETTER-SPACING'])) { $css .= 'letter-spacing: '.strtolower($p['LETTER-SPACING']).'; '; }
13499 if (isset($p['FONT-VARIANT'])) { $css .= 'font-variant: '.strtolower($p['FONT-VARIANT']).'; '; }
13500 if (isset($p['COLOR'])) { $css .= 'color: '.strtolower($p['COLOR']).'; '; }
13501 if (isset($p['Z-INDEX'])) { $css .= 'z-index: '.$p['Z-INDEX'].'; '; } // mPDF 5.6.01
13502 if ($css) {
13503 $html = '<div style="'.$css.'">'.$html.'</div>';
13504 }
13505 // Copy over (only) the properties to set for border and background
13506 $pb = array();
13507 $pb['MARGIN-TOP'] = $p['MARGIN-TOP'];
13508 $pb['MARGIN-RIGHT'] = $p['MARGIN-RIGHT'];
13509 $pb['MARGIN-BOTTOM'] = $p['MARGIN-BOTTOM'];
13510 $pb['MARGIN-LEFT'] = $p['MARGIN-LEFT'];
13511 $pb['PADDING-TOP'] = $p['PADDING-TOP'];
13512 $pb['PADDING-RIGHT'] = $p['PADDING-RIGHT'];
13513 $pb['PADDING-BOTTOM'] = $p['PADDING-BOTTOM'];
13514 $pb['PADDING-LEFT'] = $p['PADDING-LEFT'];
13515 $pb['BORDER-TOP'] = $p['BORDER-TOP'];
13516 $pb['BORDER-RIGHT'] = $p['BORDER-RIGHT'];
13517 $pb['BORDER-BOTTOM'] = $p['BORDER-BOTTOM'];
13518 $pb['BORDER-LEFT'] = $p['BORDER-LEFT'];
13519 $pb['BORDER-TOP-LEFT-RADIUS-H'] = $p['BORDER-TOP-LEFT-RADIUS-H'];
13520 $pb['BORDER-TOP-LEFT-RADIUS-V'] = $p['BORDER-TOP-LEFT-RADIUS-V'];
13521 $pb['BORDER-TOP-RIGHT-RADIUS-H'] = $p['BORDER-TOP-RIGHT-RADIUS-H'];
13522 $pb['BORDER-TOP-RIGHT-RADIUS-V'] = $p['BORDER-TOP-RIGHT-RADIUS-V'];
13523 $pb['BORDER-BOTTOM-LEFT-RADIUS-H'] = $p['BORDER-BOTTOM-LEFT-RADIUS-H'];
13524 $pb['BORDER-BOTTOM-LEFT-RADIUS-V'] = $p['BORDER-BOTTOM-LEFT-RADIUS-V'];
13525 $pb['BORDER-BOTTOM-RIGHT-RADIUS-H'] = $p['BORDER-BOTTOM-RIGHT-RADIUS-H'];
13526 $pb['BORDER-BOTTOM-RIGHT-RADIUS-V'] = $p['BORDER-BOTTOM-RIGHT-RADIUS-V'];
13527 if (isset($p['BACKGROUND-COLOR'])) { $pb['BACKGROUND-COLOR'] = $p['BACKGROUND-COLOR']; }
13528 if (isset($p['BOX-SHADOW'])) { $pb['BOX-SHADOW'] = $p['BOX-SHADOW']; }
13529 /*-- BACKGROUNDS --*/
13530 if (isset($p['BACKGROUND-IMAGE'])) { $pb['BACKGROUND-IMAGE'] = $p['BACKGROUND-IMAGE']; }
13531 if (isset($p['BACKGROUND-IMAGE-RESIZE'])) { $pb['BACKGROUND-IMAGE-RESIZE'] = $p['BACKGROUND-IMAGE-RESIZE']; }
13532 if (isset($p['BACKGROUND-IMAGE-OPACITY'])) { $pb['BACKGROUND-IMAGE-OPACITY'] = $p['BACKGROUND-IMAGE-OPACITY']; }
13533 if (isset($p['BACKGROUND-REPEAT'])) { $pb['BACKGROUND-REPEAT'] = $p['BACKGROUND-REPEAT']; }
13534 if (isset($p['BACKGROUND-POSITION'])) { $pb['BACKGROUND-POSITION'] = $p['BACKGROUND-POSITION']; }
13535 if (isset($p['BACKGROUND-GRADIENT'])) { $pb['BACKGROUND-GRADIENT'] = $p['BACKGROUND-GRADIENT']; }
13536 if (isset($p['BACKGROUND-SIZE'])) { $pb['BACKGROUND-SIZE'] = $p['BACKGROUND-SIZE']; } // mPDF 5.6.12
13537 if (isset($p['BACKGROUND-ORIGIN'])) { $pb['BACKGROUND-ORIGIN'] = $p['BACKGROUND-ORIGIN']; } // mPDF 5.6.12
13538 if (isset($p['BACKGROUND-CLIP'])) { $pb['BACKGROUND-CLIP'] = $p['BACKGROUND-CLIP']; } // mPDF 5.6.12
13539
13540 /*-- END BACKGROUNDS --*/
13541
13542 $this->setCSS($pb,'BLOCK',$tag);
13543
13544 //================================================================
13545 $bbox_br = $this->blk[1]['border_right']['w'];
13546 $bbox_bl = $this->blk[1]['border_left']['w'];
13547 $bbox_bt = $this->blk[1]['border_top']['w'];
13548 $bbox_bb = $this->blk[1]['border_bottom']['w'];
13549 $bbox_pr = $this->blk[1]['padding_right'];
13550 $bbox_pl = $this->blk[1]['padding_left'];
13551 $bbox_pt = $this->blk[1]['padding_top'];
13552 $bbox_pb = $this->blk[1]['padding_bottom'];
13553 $bbox_mr = $this->blk[1]['margin_right'];
13554 if (strtolower($p['MARGIN-RIGHT'])=='auto') { $bbox_mr = 'auto'; }
13555 $bbox_ml = $this->blk[1]['margin_left'];
13556 if (strtolower($p['MARGIN-LEFT'])=='auto') { $bbox_ml = 'auto'; }
13557 $bbox_mt = $this->blk[1]['margin_top'];
13558 if (strtolower($p['MARGIN-TOP'])=='auto') { $bbox_mt = 'auto'; }
13559 $bbox_mb = $this->blk[1]['margin_bottom'];
13560 if (strtolower($p['MARGIN-BOTTOM'])=='auto') { $bbox_mb = 'auto'; }
13561 if (isset($p['LEFT']) && strtolower($p['LEFT'])!='auto') { $bbox_left = $this->ConvertSize($p['LEFT'], $cont_w, $this->FontSize,false); }
13562 else { $bbox_left = 'auto'; }
13563 if (isset($p['TOP']) && strtolower($p['TOP'])!='auto') { $bbox_top = $this->ConvertSize($p['TOP'], $cont_h, $this->FontSize,false); }
13564 else { $bbox_top = 'auto'; }
13565 if (isset($p['RIGHT']) && strtolower($p['RIGHT'])!='auto') { $bbox_right = $this->ConvertSize($p['RIGHT'], $cont_w, $this->FontSize,false); }
13566 else { $bbox_right = 'auto'; }
13567 if (isset($p['BOTTOM']) && strtolower($p['BOTTOM'])!='auto') { $bbox_bottom = $this->ConvertSize($p['BOTTOM'], $cont_h, $this->FontSize,false); }
13568 else { $bbox_bottom = 'auto'; }
13569 if (isset($p['WIDTH']) && strtolower($p['WIDTH'])!='auto') { $inner_w = $this->ConvertSize($p['WIDTH'], $cont_w, $this->FontSize,false); }
13570 else { $inner_w = 'auto'; }
13571 if (isset($p['HEIGHT']) && strtolower($p['HEIGHT'])!='auto') { $inner_h = $this->ConvertSize($p['HEIGHT'], $cont_h, $this->FontSize,false); }
13572 else { $inner_h = 'auto'; }
13573
13574 // If bottom or right pos are set and not left / top - save this to adjust rotated block later
13575 if ($rotate) {
13576 if ($bbox_left === 'auto' && $bbox_right !== 'auto') { $rot_rpos = $bbox_right; }
13577 else { $rot_rpos = false; }
13578 if ($bbox_top === 'auto' && $bbox_bottom !== 'auto') { $rot_bpos = $bbox_bottom; }
13579 else { $rot_bpos = false; }
13580 }
13581
13582 //================================================================
13583 if ($checkinnerhtml=='' && $inner_h==='auto') { $inner_h = 0.0001; }
13584 if ($checkinnerhtml=='' && $inner_w==='auto') { $inner_w = 2*$this->GetCharWidth('W',false); }
13585 //================================================================
13586 // Algorithm from CSS2.1 See http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-height
13587 // mPD 5.3.14
13588 // Special case (not CSS) if all not specified, centre vertically on page
13589 if ($bbox_top==='auto' && $inner_h==='auto' && $bbox_bottom==='auto' && $bbox_mt==='auto' && $bbox_mb==='auto') {
13590 $bbox_top_orig = $bbox_top;
13591 if ($bbox_mt==='auto') { $bbox_mt = 0; }
13592 if ($bbox_mb==='auto') { $bbox_mb = 0; }
13593 $bbox_top = $orig_y0 - $bbox_mt - $cont_y;
13594 // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto'
13595 }
13596 // mPD 5.3.14
13597 else if ($bbox_top==='auto' && $inner_h==='auto' && $bbox_bottom==='auto') {
13598 $bbox_top_orig = $bbox_top = $orig_y0 - $cont_y;
13599 if ($bbox_mt==='auto') { $bbox_mt = 0; }
13600 if ($bbox_mb==='auto') { $bbox_mb = 0; }
13601 // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto'
13602 }
13603 else if ($bbox_top!=='auto' && $inner_h!=='auto' && $bbox_bottom!=='auto') {
13604 if ($bbox_mt==='auto' && $bbox_mb==='auto') {
13605 $x = $cont_h - $bbox_top - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_bottom;
13606 $bbox_mt = $bbox_mb = ($x/2);
13607 }
13608 else if ($bbox_mt==='auto') {
13609 $bbox_mt = $cont_h - $bbox_top - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
13610 }
13611 else if ($bbox_mb==='auto') {
13612 $bbox_mb = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_bottom;
13613 }
13614 else {
13615 $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt;
13616 }
13617 }
13618 else {
13619 if ($bbox_mt==='auto') { $bbox_mt = 0; }
13620 if ($bbox_mb==='auto') { $bbox_mb = 0; }
13621 if ($bbox_top==='auto' && $inner_h==='auto' && $bbox_bottom!=='auto') {
13622 // solve for $bbox_top when content_h known - $inner_h=='auto' && $bbox_top =='auto'
13623 }
13624 else if ($bbox_top==='auto' && $bbox_bottom==='auto' && $inner_h!=='auto') {
13625 $bbox_top = $orig_y0 - $bbox_mt - $cont_y;
13626 $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt;
13627 }
13628 else if ($inner_h==='auto' && $bbox_bottom==='auto' && $bbox_top!=='auto') {
13629 // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto'
13630 }
13631 else if ($bbox_top==='auto' && $inner_h!=='auto' && $bbox_bottom!=='auto') {
13632 $bbox_top = $cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt - $bbox_bottom;
13633 }
13634 else if ($inner_h==='auto' && $bbox_top!=='auto' && $bbox_bottom!=='auto') {
13635 $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mt - $bbox_bottom;
13636 }
13637 else if ($bbox_bottom==='auto' && $bbox_top!=='auto' && $inner_h!=='auto') {
13638 $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt;
13639 }
13640 }
13641
13642 // THEN DO SAME FOR WIDTH
13643 // http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width
13644 if ($bbox_left==='auto' && $inner_w==='auto' && $bbox_right==='auto') {
13645 if ($bbox_ml==='auto') { $bbox_ml = 0; }
13646 if ($bbox_mr==='auto') { $bbox_mr = 0; }
13647 // IF containing element RTL, should set $bbox_right
13648 $bbox_left = $orig_x0 - $bbox_ml - $cont_x;
13649 // solve for $bbox_right when content_w known - $inner_w=='auto' && $bbox_right=='auto'
13650 }
13651 else if ($bbox_left!=='auto' && $inner_w!=='auto' && $bbox_right!=='auto') {
13652 if ($bbox_ml==='auto' && $bbox_mr==='auto') {
13653 $x = $cont_w - $bbox_left - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_right;
13654 $bbox_ml = $bbox_mr = ($x/2);
13655 }
13656 else if ($bbox_ml==='auto') {
13657 $bbox_ml = $cont_w - $bbox_left - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_mr - $bbox_right;
13658 }
13659 else if ($bbox_mr==='auto') {
13660 $bbox_mr = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_right;
13661 }
13662 else {
13663 $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
13664 }
13665 }
13666 else {
13667 if ($bbox_ml==='auto') { $bbox_ml = 0; }
13668 if ($bbox_mr==='auto') { $bbox_mr = 0; }
13669 if ($bbox_left==='auto' && $inner_w==='auto' && $bbox_right!=='auto') {
13670 // solve for $bbox_left when content_w known - $inner_w=='auto' && $bbox_left =='auto'
13671 }
13672 else if ($bbox_left==='auto' && $bbox_right==='auto' && $inner_w!=='auto') {
13673 // IF containing element RTL, should set $bbox_right
13674 $bbox_left = $orig_x0 - $bbox_ml - $cont_x;
13675 $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
13676 }
13677 else if ($inner_w==='auto' && $bbox_right==='auto' && $bbox_left!=='auto') {
13678 // solve for $bbox_right when content_w known - $inner_w=='auto' && $bbox_right=='auto'
13679 }
13680 else if ($bbox_left==='auto' && $inner_w!=='auto' && $bbox_right!=='auto') {
13681 $bbox_left = $cont_w - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right;
13682 }
13683 else if ($inner_w==='auto' && $bbox_left!=='auto' && $bbox_right!=='auto') {
13684 $inner_w = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right;
13685 }
13686 else if ($bbox_right==='auto' && $bbox_left!=='auto' && $inner_w!=='auto') {
13687 $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
13688 }
13689 }
13690
13691 //================================================================
13692 //================================================================
13693 /*-- BACKGROUNDS --*/
13694 if (isset($pb['BACKGROUND-IMAGE']) && $pb['BACKGROUND-IMAGE']) {
13695 $ret = $this->SetBackground($pb, $this->blk[1]['inner_width']);
13696 if ($ret) { $this->blk[1]['background-image'] = $ret; }
13697 }
13698 /*-- END BACKGROUNDS --*/
13699
13700 //================================================================
13701 $y = $cont_y + $bbox_top + $bbox_mt + $bbox_bt + $bbox_pt;
13702 $h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
13703 $x = $cont_x + $bbox_left + $bbox_ml + $bbox_bl + $bbox_pl;
13704 $w = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $bbox_pr - $bbox_br - $bbox_mr - $bbox_right;
13705 // Set (temporary) values for x y w h to do first paint, if values are auto
13706 if ($inner_h==='auto' && $bbox_top==='auto') {
13707 $y = $cont_y + $bbox_mt + $bbox_bt + $bbox_pt;
13708 $h = $cont_h - ($bbox_bottom + $bbox_mt + $bbox_mb + $bbox_bt + $bbox_bb + $bbox_pt + $bbox_pb);
13709 }
13710 else if ($inner_h==='auto' && $bbox_bottom==='auto') {
13711 $y = $cont_y + $bbox_top + $bbox_mt + $bbox_bt + $bbox_pt;
13712 $h = $cont_h - ($bbox_top + $bbox_mt + $bbox_mb + $bbox_bt + $bbox_bb + $bbox_pt + $bbox_pb);
13713 }
13714 if ($inner_w==='auto' && $bbox_left==='auto') {
13715 $x = $cont_x + $bbox_ml + $bbox_bl + $bbox_pl;
13716 $w = $cont_w - ($bbox_right + $bbox_ml + $bbox_mr + $bbox_bl + $bbox_br + $bbox_pl + $bbox_pr);
13717 }
13718 else if ($inner_w==='auto' && $bbox_right==='auto') {
13719 $x = $cont_x + $bbox_left + $bbox_ml + $bbox_bl + $bbox_pl;
13720 $w = $cont_w - ($bbox_left + $bbox_ml + $bbox_mr + $bbox_bl + $bbox_br + $bbox_pl + $bbox_pr);
13721 }
13722 $bbox_y = $cont_y + $bbox_top + $bbox_mt;
13723 $bbox_x = $cont_x + $bbox_left + $bbox_ml;
13724 $saved_block1 = $this->blk[1];
13725 unset($p);
13726 unset($pb);
13727 //================================================================
13728 if ($inner_w==='auto') { // do a first write
13729 $this->lMargin=$x;
13730 $this->rMargin=$this->w - $w - $x;
13731 // SET POSITION & FONT VALUES
13732 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
13733 $this->pageoutput[$this->page]=array();
13734 $this->x = $x;
13735 $this->y = $y;
13736 $this->HTMLheaderPageLinks = array();
13737 $this->HTMLheaderPageAnnots = array();
13738 $this->HTMLheaderPageForms = array();
13739 $this->pageBackgrounds = array();
13740 $this->maxPosR = 0;
13741 $this->maxPosL = $this->w; // For RTL
13742 $this->WriteHTML($html , 4);
13743 $inner_w = $this->maxPosR - $this->lMargin;
13744 if ($bbox_right==='auto') {
13745 $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml;
13746 }
13747 else if ($bbox_left==='auto') {
13748 $bbox_left = $cont_w - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right;
13749 $bbox_x = $cont_x + $bbox_left + $bbox_ml ;
13750 $inner_x = $bbox_x + $bbox_bl + $bbox_pl;
13751 $x = $inner_x;
13752 }
13753 $w = $inner_w;
13754 $bbox_y = $cont_y + $bbox_top + $bbox_mt;
13755 $bbox_x = $cont_x + $bbox_left + $bbox_ml;
13756 }
13757
13758 if ($inner_h==='auto') { // do a first write
13759 $this->lMargin=$x;
13760 $this->rMargin=$this->w - $w - $x;
13761 // SET POSITION & FONT VALUES
13762 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
13763 $this->pageoutput[$this->page]=array();
13764 $this->x = $x;
13765 $this->y = $y;
13766 $this->HTMLheaderPageLinks = array();
13767 $this->HTMLheaderPageAnnots = array();
13768 $this->HTMLheaderPageForms = array();
13769 $this->pageBackgrounds = array();
13770 $this->WriteHTML($html , 4);
13771 $inner_h = $this->y - $y;
13772 if ($overflow!='hidden' && $overflow!='visible') { // constrained
13773 if (($this->y + $bbox_pb + $bbox_bb) > ($cont_y + $cont_h)) {
13774 $adj = ($this->y + $bbox_pb + $bbox_bb) - ($cont_y + $cont_h);
13775 $inner_h -= $adj;
13776 }
13777 }
13778 if ($bbox_bottom==='auto' && $bbox_top_orig==='auto') {
13779 $bbox_bottom = $bbox_top = ($cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb)/2;
13780 if ($overflow!='hidden' && $overflow!='visible') { // constrained
13781 if ($bbox_top < 0) {
13782 $bbox_top = 0;
13783 $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
13784 }
13785 }
13786 $bbox_y = $cont_y + $bbox_top + $bbox_mt;
13787 $inner_y = $bbox_y + $bbox_bt + $bbox_pt;
13788 $y = $inner_y;
13789
13790 }
13791 else if ($bbox_bottom==='auto') {
13792 $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb;
13793 }
13794 else if ($bbox_top==='auto') {
13795 $bbox_top = $cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
13796 if ($overflow!='hidden' && $overflow!='visible') { // constrained
13797 if ($bbox_top < 0) {
13798 $bbox_top = 0;
13799 $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom;
13800 }
13801 }
13802 $bbox_y = $cont_y + $bbox_top + $bbox_mt;
13803 $inner_y = $bbox_y + $bbox_bt + $bbox_pt;
13804 $y = $inner_y;
13805 }
13806 $h = $inner_h;
13807 $bbox_y = $cont_y + $bbox_top + $bbox_mt;
13808 $bbox_x = $cont_x + $bbox_left + $bbox_ml;
13809 }
13810 $inner_w = $w;
13811 $inner_h = $h;
13812
13813 }
13814 $this->lMargin=$x;
13815 $this->rMargin=$this->w - $w - $x;
13816 // SET POSITION & FONT VALUES
13817 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
13818 $this->pageoutput[$this->page]=array();
13819 $this->x = $x;
13820 $this->y = $y;
13821 $this->HTMLheaderPageLinks = array();
13822 $this->HTMLheaderPageAnnots = array();
13823 $this->HTMLheaderPageForms = array();
13824 $this->pageBackgrounds = array();
13825 $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
13826 $actual_h = $this->y - $y;
13827 $use_w = $w;
13828 $use_h = $h;
13829 $ratio = $actual_h / $use_w;
13830
13831 if ($overflow!='hidden' && $overflow!='visible') {
13832 $target = $h/$w;
13833 if (($ratio / $target ) > 1) {
13834 $nl = CEIL($actual_h / $this->lineheight);
13835 $l = $use_w * $nl;
13836 $est_w = sqrt(($l * $this->lineheight) / $target) * 0.8;
13837 $use_w += ($est_w - $use_w) - ($w/100);
13838 }
13839 $bpcstart = ($ratio / $target);
13840 $bpcctr = 1;
13841 while(($ratio / $target ) > 1) {
13842
13843 if ($this->progressBar) { $this->UpdateProgressBar(4,intval(100/($ratio/$target)),('Auto-sizing fixed-position block: '.$bpcctr++)); } // *PROGRESS-BAR*
13844
13845 $this->x = $x;
13846 $this->y = $y;
13847
13848 if (($ratio / $target) > 1.5 || ($ratio / $target) < 0.6) {
13849 $use_w += ($w/$this->incrementFPR1);
13850 }
13851 else if (($ratio / $target) > 1.2 || ($ratio / $target) < 0.85) {
13852 $use_w += ($w/$this->incrementFPR2);
13853 }
13854 else if (($ratio / $target) > 1.1 || ($ratio / $target) < 0.91) {
13855 $use_w += ($w/$this->incrementFPR3);
13856 }
13857 else {
13858 $use_w += ($w/$this->incrementFPR4);
13859 }
13860
13861 $use_h = $use_w * $target ;
13862 $this->rMargin=$this->w - $use_w - $x;
13863 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
13864 $this->HTMLheaderPageLinks = array();
13865 $this->HTMLheaderPageAnnots = array();
13866 $this->HTMLheaderPageForms = array();
13867 $this->pageBackgrounds = array();
13868 $this->WriteHTML($html , 4); // parameter 4 saves output to $this->headerbuffer
13869 $actual_h = $this->y - $y;
13870 $ratio = $actual_h / $use_w;
13871 }
13872 if ($this->progressBar) { $this->UpdateProgressBar(4,'100',' '); } // *PROGRESS-BAR*
13873 }
13874 $shrink_f = $w/$use_w;
13875
13876 //================================================================
13877
13878 $this->pages[$this->page] .= '___BEFORE_BORDERS___';
13879 $block_s = $this->PrintPageBackgrounds(); // Save to print later inside clipping path
13880 $this->pageBackgrounds = array();
13881
13882 //================================================================
13883
13884 if ($rotate) {
13885 $prerotw = $bbox_bl + $bbox_pl + $inner_w + $bbox_pr + $bbox_br;
13886 $preroth = $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb;
13887 $rot_start = " q\n";
13888 if ($rotate == 90) {
13889 if ($rot_rpos !== false) { $adjw = $prerotw; } // width before rotation
13890 else { $adjw = $preroth; } // height before rotation
13891 if ($rot_bpos !== false) { $adjh = -$prerotw + $preroth; }
13892 else { $adjh = 0; }
13893 }
13894 else {
13895 if ($rot_rpos !== false) { $adjw = $prerotw - $preroth; }
13896 else { $adjw = 0; }
13897 if ($rot_bpos !== false) { $adjh = $preroth; } // height before rotation
13898 else { $adjh = $prerotw; } // width before rotation
13899 }
13900 $rot_start .= $this->transformTranslate($adjw, $adjh, true)."\n";
13901 $rot_start .= $this->transformRotate($rotate, $bbox_x, $bbox_y, true)."\n";
13902 $rot_end = " Q\n";
13903 }
13904 else {
13905 $rot_start = '';
13906 $rot_end = '';
13907 }
13908
13909 //================================================================
13910 if (!empty($bounding)) {
13911 // WHEN HEIGHT // BOTTOM EDGE IS KNOWN and $this->y is set to the bottom
13912 // Re-instate saved $this->blk[1]
13913 $this->blk[1] = $saved_block1;
13914
13915 // These are only needed when painting border/background
13916 $this->blk[1]['width'] = $bbox_w = $cont_w - $bbox_left - $bbox_ml - $bbox_mr - $bbox_right;
13917 $this->blk[1]['x0'] = $bbox_x;
13918 $this->blk[1]['y0'] = $bbox_y;
13919 $this->blk[1]['startpage'] = $this->page;
13920 $this->blk[1]['y1'] = $bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb ;
13921 $this->_out($rot_start); // mPDF 5.0
13922 $this->PaintDivBB('',0,1); // Prints borders and sets backgrounds in $this->pageBackgrounds
13923 $this->_out($rot_end);
13924 }
13925
13926 $s = $this->PrintPageBackgrounds();
13927 $s = $rot_start.$s.$rot_end;
13928 $this->pages[$this->page] = preg_replace('/___BEFORE_BORDERS___/', "\n".$s."\n", $this->pages[$this->page]);
13929 $this->pageBackgrounds = array();
13930
13931 $this->_out($rot_start);
13932
13933 // Clipping Output
13934 if ($overflow=='hidden') {
13935 //Bounding rectangle to clip
13936 $clip_y1 = $this->y;
13937 if (!empty($bounding) && ($this->y + $bbox_pb + $bbox_bb) > ($bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb )) {
13938 $clip_y1 = ($bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb ) - ($bbox_pb + $bbox_bb);
13939 }
13940 //$op = 'W* n'; // Clipping
13941 $op = 'W n'; // Clipping alternative mode
13942 $this->_out("q");
13943 $ch = $clip_y1 - $y;
13944 $this->_out(sprintf('%.3F %.3F %.3F %.3F re %s',$x*_MPDFK,($this->h-$y)*_MPDFK,$w*_MPDFK,-$ch*_MPDFK,$op));
13945 if (!empty($block_s)) {
13946 $tmp = "q\n".sprintf('%.3F %.3F %.3F %.3F re %s',$x*_MPDFK,($this->h-$y)*_MPDFK,$w*_MPDFK,-$ch*_MPDFK,$op);
13947 $tmp .= "\n".$block_s."\nQ";
13948 $block_s = $tmp ;
13949 }
13950 }
13951
13952
13953 if (!empty($block_s)) {
13954 if ($shrink_f != 1) { // i.e. autofit has resized the box
13955 $tmp = "q\n".$this->transformScale(($shrink_f*100),($shrink_f*100), $x, $y, true);
13956 $tmp .= "\n".$block_s."\nQ";
13957 $block_s = $tmp ;
13958 }
13959 $this->_out($block_s);
13960 }
13961
13962
13963
13964 if ($shrink_f != 1) { // i.e. autofit has resized the box
13965 $this->StartTransform();
13966 $this->transformScale(($shrink_f*100),($shrink_f*100), $x, $y);
13967 }
13968
13969 $this->_out($this->headerbuffer);
13970
13971 if ($shrink_f != 1) { // i.e. autofit has resized the box
13972 $this->StopTransform();
13973 }
13974
13975 if ($overflow=='hidden') {
13976 //End clipping
13977 $this->_out("Q");
13978 }
13979
13980 $this->_out($rot_end);
13981
13982
13983 // Page Links
13984 foreach($this->HTMLheaderPageLinks AS $lk) {
13985 if ($rotate) {
13986 $tmp = $lk[2]; // Switch h - w
13987 $lk[2] = $lk[3];
13988 $lk[3] = $tmp;
13989
13990 $lx1 = (($lk[0]/_MPDFK));
13991 $ly1 = (($this->h-($lk[1]/_MPDFK)));
13992 if ($rotate == 90) {
13993 $adjx = -($lx1-$bbox_x) + ($preroth - ($ly1-$bbox_y));
13994 $adjy = -($ly1-$bbox_y) + ($lx1-$bbox_x);
13995 $lk[2] = -$lk[2];
13996 }
13997 else if ($rotate == -90) {
13998 $adjx = -($lx1-$bbox_x) + ($ly1-$bbox_y);
13999 $adjy = -($ly1-$bbox_y) - ($lx1-$bbox_x) + $prerotw;
14000 $lk[3] = -$lk[3];
14001 }
14002 if ($rot_rpos !== false) { $adjx += $prerotw - $preroth; }
14003 if ($rot_bpos !== false) { $adjy += $preroth - $prerotw; }
14004 $lx1 += $adjx;
14005 $ly1 += $adjy;
14006
14007 $lk[0] = $lx1*_MPDFK;
14008 $lk[1] = ($this->h-$ly1)*_MPDFK;
14009 }
14010 if ($shrink_f != 1) { // i.e. autofit has resized the box
14011 $lx1 = (($lk[0]/_MPDFK)-$x);
14012 $lx2 = $x + ($lx1 * $shrink_f);
14013 $lk[0] = $lx2*_MPDFK;
14014 $ly1 = (($this->h-($lk[1]/_MPDFK))-$y);
14015 $ly2 = $y + ($ly1 * $shrink_f);
14016 $lk[1] = ($this->h-$ly2)*_MPDFK;
14017 $lk[2] *= $shrink_f; // width
14018 $lk[3] *= $shrink_f; // height
14019 }
14020 $this->PageLinks[$this->page][]=$lk;
14021 }
14022
14023 foreach($this->HTMLheaderPageForms AS $n=>$f) {
14024 if ($shrink_f != 1) { // i.e. autofit has resized the box
14025 $f['x'] = $x + (($f['x'] -$x) * $shrink_f);
14026 $f['y'] = $y + (($f['y'] -$y) * $shrink_f);
14027 $f['w'] *= $shrink_f;
14028 $f['h'] *= $shrink_f;
14029 $f['style']['fontsize'] *= $shrink_f;
14030 }
14031 $this->form->forms[$f['n']] = $f;
14032 }
14033 // Page Annotations
14034 foreach($this->HTMLheaderPageAnnots AS $lk) {
14035 if ($rotate) {
14036 if ($rotate == 90) {
14037 $adjx = -($lk['x']-$bbox_x) + ($preroth - ($lk['y']-$bbox_y));
14038 $adjy = -($lk['y']-$bbox_y) + ($lk['x']-$bbox_x);
14039 }
14040 else if ($rotate == -90) {
14041 $adjx = -($lk['x']-$bbox_x) + ($lk['y']-$bbox_y);
14042 $adjy = -($lk['y']-$bbox_y) - ($lk['x']-$bbox_x) + $prerotw;
14043 }
14044 if ($rot_rpos !== false) { $adjx += $prerotw - $preroth; }
14045 if ($rot_bpos !== false) { $adjy += $preroth - $prerotw; }
14046 $lk['x'] += $adjx;
14047 $lk['y'] += $adjy;
14048 }
14049 if ($shrink_f != 1) { // i.e. autofit has resized the box
14050 $lk['x'] = $x + (($lk['x']-$x) * $shrink_f);
14051 $lk['y'] = $y + (($lk['y']-$y) * $shrink_f);
14052 }
14053 $this->PageAnnots[$this->page][]=$lk;
14054 }
14055
14056 // Restore
14057 $this->headerbuffer = '';
14058 $this->HTMLheaderPageLinks = array();
14059 $this->HTMLheaderPageAnnots = array();
14060 $this->HTMLheaderPageForms = array();
14061 $this->pageBackgrounds = $save_bgs;
14062 $this->writingHTMLheader = false;
14063
14064 $this->writingHTMLfooter = false;
14065 $this->fullImageHeight = false;
14066 $this->ResetMargins();
14067 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
14068 $this->SetXY($save_x,$save_y) ;
14069 $this->title2annots = $save_annots; // *ANNOTATIONS*
14070 $this->InFooter = false; // turns back on autopagebreaks
14071 $this->pageoutput[$this->page]=array();
14072 $this->pageoutput[$this->page]['Font']='';
14073 /*-- COLUMNS --*/
14074 if ($save_cols) {
14075 $this->SetColumns($save_nbcol,$this->colvAlign,$this->ColGap);
14076 }
14077 /*-- END COLUMNS --*/
14078 }
14079 /*-- END CSS-POSITION --*/
14080
14081
14082
14083 function initialiseBlock(&$blk) {
14084 $blk['margin_top'] = 0;
14085 $blk['margin_left'] = 0;
14086 $blk['margin_bottom'] = 0;
14087 $blk['margin_right'] = 0;
14088 $blk['padding_top'] = 0;
14089 $blk['padding_left'] = 0;
14090 $blk['padding_bottom'] = 0;
14091 $blk['padding_right'] = 0;
14092 $blk['border_top']['w'] = 0;
14093 $blk['border_left']['w'] = 0;
14094 $blk['border_bottom']['w'] = 0;
14095 $blk['border_right']['w'] = 0;
14096 $blk['hide'] = false;
14097 $blk['outer_left_margin'] = 0;
14098 $blk['outer_right_margin'] = 0;
14099 $blk['cascadeCSS'] = array();
14100 $blk['block-align'] = false;
14101 $blk['bgcolor'] = false;
14102 $blk['page_break_after_avoid'] = false;
14103 $blk['keep_block_together'] = false;
14104 $blk['float'] = false;
14105 $blk['line_height'] = '';
14106 $blk['margin_collapse'] = false;
14107 }
14108
14109
14110 function border_details($bd) {
14111 $prop = preg_split('/\s+/',trim($bd));
14112
14113 if (isset($this->blk[$this->blklvl]['inner_width'])) { $refw = $this->blk[$this->blklvl]['inner_width']; }
14114 else if (isset($this->blk[$this->blklvl-1]['inner_width'])) { $refw = $this->blk[$this->blklvl-1]['inner_width']; }
14115 else { $refw = $this->w; }
14116 if ( count($prop) == 1 ) {
14117 $bsize = $this->ConvertSize($prop[0],$refw,$this->FontSize,false);
14118 if ($bsize > 0) {
14119 return array('s' => 1, 'w' => $bsize, 'c' => $this->ConvertColor(0), 'style'=>'solid');
14120 }
14121 else { return array('w' => 0, 's' => 0); }
14122 }
14123
14124 else if (count($prop) == 2 ) {
14125 // 1px solid
14126 if (in_array($prop[1],$this->borderstyles) || $prop[1] == 'none' || $prop[1] == 'hidden' ) { $prop[2] = ''; }
14127 // solid #000000
14128 else if (in_array($prop[0],$this->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) { $prop[0] = ''; $prop[1] = $prop[0]; $prop[2] = $prop[1]; }
14129 // 1px #000000
14130 else { $prop[1] = ''; $prop[2] = $prop[1]; }
14131 }
14132 else if ( count($prop) == 3 ) {
14133 // Change #000000 1px solid to 1px solid #000000 (proper)
14134 if (substr($prop[0],0,1) == '#') { $tmp = $prop[0]; $prop[0] = $prop[1]; $prop[1] = $prop[2]; $prop[2] = $tmp; }
14135 // Change solid #000000 1px to 1px solid #000000 (proper)
14136 else if (substr($prop[0],1,1) == '#') { $tmp = $prop[1]; $prop[0] = $prop[2]; $prop[1] = $prop[0]; $prop[2] = $tmp; }
14137 // Change solid 1px #000000 to 1px solid #000000 (proper)
14138 else if (in_array($prop[0],$this->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden' ) {
14139 $tmp = $prop[0]; $prop[0] = $prop[1]; $prop[1] = $tmp;
14140 }
14141 }
14142 else { return array(); }
14143 // Size
14144 $bsize = $this->ConvertSize($prop[0],$refw,$this->FontSize,false);
14145 //color
14146 $coul = $this->ConvertColor($prop[2]); // returns array
14147 // Style
14148 $prop[1] = strtolower($prop[1]);
14149 if (in_array($prop[1],$this->borderstyles) && $bsize > 0) { $on = 1; }
14150 else if ($prop[1] == 'hidden') { $on = 1; $bsize = 0; $coul = ''; }
14151 else if ($prop[1] == 'none') { $on = 0; $bsize = 0; $coul = ''; }
14152 else { $on = 0; $bsize = 0; $coul = ''; $prop[1] = ''; }
14153 return array('s' => $on, 'w' => $bsize, 'c' => $coul, 'style'=> $prop[1] );
14154 }
14155
14156
14157
14158 /*-- END HTML-CSS --*/
14159
14160
14161 // Return either a number (factor) - based on current set fontsize (if % or em) - or exact lineheight (with 'mm' after it)
14162 function fixLineheight($v) {
14163 $lh = false;
14164 if (preg_match('/^[0-9\.,]*$/',$v) && $v >= 0) { return ($v + 0); }
14165 else if (strtoupper($v) == 'NORMAL') {
14166 return $this->normalLineheight;
14167 }
14168 else {
14169 $tlh = $this->ConvertSize($v,$this->FontSize,$this->FontSize,true);
14170 if ($tlh) { return ($tlh.'mm'); }
14171 }
14172 return $this->normalLineheight;
14173 }
14174
14175
14176 /*-- BORDER-RADIUS --*/
14177 function _borderPadding($a, $b, &$px, &$py) {
14178 // $px and py are padding long axis (x) and short axis (y)
14179 $added = 0; // extra padding
14180
14181 $x = $a-$px;
14182 $y = $b-$py;
14183 // Check if Falls within ellipse of border radius
14184 if ( ( (($x+$added)*($x+$added))/($a*$a) + (($y+$added)*($y+$added))/($b*$b) ) <=1 ) { return false; }
14185
14186 $t = atan2($y,$x);
14187
14188 $newx = $b / sqrt((($b*$b)/($a*$a)) + ( tan($t) * tan($t) ) );
14189 $newy = $a / sqrt((($a*$a)/($b*$b)) + ( (1/tan($t)) * (1/tan($t)) ) );
14190 $px = max($px, $a - $newx + $added);
14191 $py = max($py, $b - $newy + $added);
14192 }
14193 /*-- END BORDER-RADIUS --*/
14194
14195
14196
14197 /*-- HTML-CSS --*/
14198
14199
14200 /*-- CSS-PAGE --*/
14201 function SetPagedMediaCSS($name='', $first, $oddEven) {
14202 if ($oddEven == 'E') {
14203 if ($this->directionality=='rtl') { $side = 'R'; }
14204 else { $side = 'L'; }
14205 }
14206 else {
14207 if ($this->directionality=='rtl') { $side = 'L'; }
14208 else { $side = 'R'; }
14209 }
14210 $name = strtoupper($name);
14211 $p = array();
14212 $p['SIZE'] = 'AUTO';
14213
14214 // Uses mPDF original margins as default
14215 $p['MARGIN-RIGHT'] = strval($this->orig_rMargin).'mm';
14216 $p['MARGIN-LEFT'] = strval($this->orig_lMargin).'mm';
14217 $p['MARGIN-TOP'] = strval($this->orig_tMargin).'mm';
14218 $p['MARGIN-BOTTOM'] = strval($this->orig_bMargin).'mm';
14219 $p['MARGIN-HEADER'] = strval($this->orig_hMargin).'mm';
14220 $p['MARGIN-FOOTER'] = strval($this->orig_fMargin).'mm';
14221
14222 // Basic page + selector
14223 if (isset($this->cssmgr->CSS['@PAGE'])) { $zp = $this->cssmgr->CSS['@PAGE']; }
14224 else { $zp = array(); }
14225 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
14226
14227 if (isset($p['EVEN-HEADER-NAME']) && $oddEven=='E') {
14228 $p['HEADER'] = $p['EVEN-HEADER-NAME']; unset($p['EVEN-HEADER-NAME']);
14229 }
14230 if (isset($p['ODD-HEADER-NAME']) && $oddEven!='E') {
14231 $p['HEADER'] = $p['ODD-HEADER-NAME']; unset($p['ODD-HEADER-NAME']);
14232 }
14233 if (isset($p['EVEN-FOOTER-NAME']) && $oddEven=='E') {
14234 $p['FOOTER'] = $p['EVEN-FOOTER-NAME']; unset($p['EVEN-FOOTER-NAME']);
14235 }
14236 if (isset($p['ODD-FOOTER-NAME']) && $oddEven!='E') {
14237 $p['FOOTER'] = $p['ODD-FOOTER-NAME']; unset($p['ODD-FOOTER-NAME']);
14238 }
14239
14240 // If right/Odd page
14241 if (isset($this->cssmgr->CSS['@PAGE>>PSEUDO>>RIGHT']) && $side=='R') {
14242 $zp = $this->cssmgr->CSS['@PAGE>>PSEUDO>>RIGHT'];
14243 }
14244 else { $zp = array(); }
14245 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
14246 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
14247 // Disallow margin-left or -right on :LEFT or :RIGHT
14248 if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
14249 if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
14250 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
14251
14252 // If left/Even page
14253 if (isset($this->cssmgr->CSS['@PAGE>>PSEUDO>>LEFT']) && $side=='L') {
14254 $zp = $this->cssmgr->CSS['@PAGE>>PSEUDO>>LEFT'];
14255 }
14256 else { $zp = array(); }
14257 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
14258 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
14259 // Disallow margin-left or -right on :LEFT or :RIGHT
14260 if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
14261 if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
14262 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
14263
14264 // If first page
14265 if (isset($this->cssmgr->CSS['@PAGE>>PSEUDO>>FIRST']) && $first) { $zp = $this->cssmgr->CSS['@PAGE>>PSEUDO>>FIRST']; }
14266 else { $zp = array(); }
14267 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
14268 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
14269 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
14270
14271 // If named page
14272 if ($name) {
14273 if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name])) { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name]; }
14274 else { $zp = array(); }
14275 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
14276
14277 if (isset($p['EVEN-HEADER-NAME']) && $oddEven=='E') {
14278 $p['HEADER'] = $p['EVEN-HEADER-NAME']; unset($p['EVEN-HEADER-NAME']);
14279 }
14280 if (isset($p['ODD-HEADER-NAME']) && $oddEven!='E') {
14281 $p['HEADER'] = $p['ODD-HEADER-NAME']; unset($p['ODD-HEADER-NAME']);
14282 }
14283 if (isset($p['EVEN-FOOTER-NAME']) && $oddEven=='E') {
14284 $p['FOOTER'] = $p['EVEN-FOOTER-NAME']; unset($p['EVEN-FOOTER-NAME']);
14285 }
14286 if (isset($p['ODD-FOOTER-NAME']) && $oddEven!='E') {
14287 $p['FOOTER'] = $p['ODD-FOOTER-NAME']; unset($p['ODD-FOOTER-NAME']);
14288 }
14289
14290 // If named right/Odd page
14291 if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>RIGHT']) && $side=='R') { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>RIGHT']; }
14292 else { $zp = array(); }
14293 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
14294 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
14295 // Disallow margin-left or -right on :LEFT or :RIGHT
14296 if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
14297 if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
14298 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
14299
14300 // If named left/Even page
14301 if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>LEFT']) && $side=='L') { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>LEFT']; }
14302 else { $zp = array(); }
14303 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
14304 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
14305 // Disallow margin-left or -right on :LEFT or :RIGHT
14306 if (isset($zp['MARGIN-LEFT'])) { unset($zp['MARGIN-LEFT']); }
14307 if (isset($zp['MARGIN-RIGHT'])) { unset($zp['MARGIN-RIGHT']); }
14308 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
14309
14310 // If named first page
14311 if (isset($this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>FIRST']) && $first) { $zp = $this->cssmgr->CSS['@PAGE>>NAMED>>'.$name.'>>PSEUDO>>FIRST']; }
14312 else { $zp = array(); }
14313 if (isset($zp['SIZE'])) { unset($zp['SIZE']); }
14314 if (isset($zp['SHEET-SIZE'])) { unset($zp['SHEET-SIZE']); }
14315 if (is_array($zp) && !empty($zp)) { $p = array_merge($p,$zp); }
14316 }
14317
14318 $orientation = $mgl = $mgr = $mgt = $mgb = $mgh = $mgf = '';
14319 $header = $footer = '';
14320 $resetpagenum = $pagenumstyle = $suppress = '';
14321 $marks = '';
14322 $bg = array();
14323
14324 $newformat = '';
14325
14326
14327 if (isset($p['SHEET-SIZE']) && is_array($p['SHEET-SIZE'])) {
14328 $newformat = $p['SHEET-SIZE'];
14329 if ($newformat[0] > $newformat[1]) { // landscape
14330 $newformat = array_reverse($newformat);
14331 $p['ORIENTATION'] = 'L';
14332 }
14333 else { $p['ORIENTATION'] = 'P'; }
14334 $this->_setPageSize($newformat, $p['ORIENTATION']);
14335 }
14336
14337 if (isset($p['SIZE']) && is_array($p['SIZE']) && !$newformat) {
14338 if ($p['SIZE']['W'] > $p['SIZE']['H']) { $p['ORIENTATION'] = 'L'; }
14339 else { $p['ORIENTATION'] = 'P'; }
14340 }
14341 if (is_array($p['SIZE'])) {
14342 if ($p['SIZE']['W'] > $this->fw) { $p['SIZE']['W'] = $this->fw; } // mPD 4.2 use fw not fPt
14343 if ($p['SIZE']['H'] > $this->fh) { $p['SIZE']['H'] = $this->fh; }
14344 if (($p['ORIENTATION']==$this->DefOrientation && !$newformat) || ($newformat && $p['ORIENTATION']=='P')) {
14345 $outer_width_LR = ($this->fw - $p['SIZE']['W'])/2;
14346 $outer_width_TB = ($this->fh - $p['SIZE']['H'])/2;
14347 }
14348 else {
14349 $outer_width_LR = ($this->fh - $p['SIZE']['W'])/2;
14350 $outer_width_TB = ($this->fw - $p['SIZE']['H'])/2;
14351 }
14352 $pgw = $p['SIZE']['W'];
14353 $pgh = $p['SIZE']['H'];
14354 }
14355 else { // AUTO LANDSCAPE PORTRAIT
14356 $outer_width_LR = 0;
14357 $outer_width_TB = 0;
14358 if (!$newformat) {
14359 if (strtoupper($p['SIZE']) == 'AUTO') { $p['ORIENTATION']=$this->DefOrientation; }
14360 else if (strtoupper($p['SIZE']) == 'LANDSCAPE') { $p['ORIENTATION']='L'; }
14361 else { $p['ORIENTATION']='P'; }
14362 }
14363 if (($p['ORIENTATION']==$this->DefOrientation && !$newformat) || ($newformat && $p['ORIENTATION']=='P')) {
14364 $pgw = $this->fw;
14365 $pgh = $this->fh;
14366 }
14367 else {
14368 $pgw = $this->fh;
14369 $pgh = $this->fw;
14370 }
14371 }
14372
14373 if (isset($p['HEADER']) && $p['HEADER']) { $header = $p['HEADER']; }
14374 if (isset($p['FOOTER']) && $p['FOOTER']) { $footer = $p['FOOTER']; }
14375 if (isset($p['RESETPAGENUM']) && $p['RESETPAGENUM']) { $resetpagenum = $p['RESETPAGENUM']; }
14376 if (isset($p['PAGENUMSTYLE']) && $p['PAGENUMSTYLE']) { $pagenumstyle = $p['PAGENUMSTYLE']; }
14377 if (isset($p['SUPPRESS']) && $p['SUPPRESS']) { $suppress = $p['SUPPRESS']; }
14378
14379 if (preg_match('/cross/i', $p['MARKS']) && preg_match('/crop/i', $p['MARKS'])) { $marks = 'CROPCROSS'; }
14380 else if (strtoupper($p['MARKS']) == 'CROP') { $marks = 'CROP'; }
14381 else if (strtoupper($p['MARKS']) == 'CROSS') { $marks = 'CROSS'; }
14382
14383
14384 if (isset($p['BACKGROUND-COLOR']) && $p['BACKGROUND-COLOR']) { $bg['BACKGROUND-COLOR'] = $p['BACKGROUND-COLOR']; }
14385 /*-- BACKGROUNDS --*/
14386 if (isset($p['BACKGROUND-GRADIENT']) && $p['BACKGROUND-GRADIENT']) { $bg['BACKGROUND-GRADIENT'] = $p['BACKGROUND-GRADIENT']; }
14387 if (isset($p['BACKGROUND-IMAGE']) && $p['BACKGROUND-IMAGE']) { $bg['BACKGROUND-IMAGE'] = $p['BACKGROUND-IMAGE']; }
14388 if (isset($p['BACKGROUND-REPEAT']) && $p['BACKGROUND-REPEAT']) { $bg['BACKGROUND-REPEAT'] = $p['BACKGROUND-REPEAT']; }
14389 if (isset($p['BACKGROUND-POSITION']) && $p['BACKGROUND-POSITION']) { $bg['BACKGROUND-POSITION'] = $p['BACKGROUND-POSITION']; }
14390 if (isset($p['BACKGROUND-IMAGE-RESIZE']) && $p['BACKGROUND-IMAGE-RESIZE']) { $bg['BACKGROUND-IMAGE-RESIZE'] = $p['BACKGROUND-IMAGE-RESIZE']; }
14391 if (isset($p['BACKGROUND-IMAGE-OPACITY'])) { $bg['BACKGROUND-IMAGE-OPACITY'] = $p['BACKGROUND-IMAGE-OPACITY']; }
14392 /*-- END BACKGROUNDS --*/
14393
14394 if (isset($p['MARGIN-LEFT'])) { $mgl = $this->ConvertSize($p['MARGIN-LEFT'],$pgw) + $outer_width_LR; }
14395 if (isset($p['MARGIN-RIGHT'])) { $mgr = $this->ConvertSize($p['MARGIN-RIGHT'],$pgw) + $outer_width_LR; }
14396 if (isset($p['MARGIN-BOTTOM'])) { $mgb = $this->ConvertSize($p['MARGIN-BOTTOM'],$pgh) + $outer_width_TB; }
14397 if (isset($p['MARGIN-TOP'])) { $mgt = $this->ConvertSize($p['MARGIN-TOP'],$pgh) + $outer_width_TB; }
14398 if (isset($p['MARGIN-HEADER'])) { $mgh = $this->ConvertSize($p['MARGIN-HEADER'],$pgh) + $outer_width_TB; }
14399 if (isset($p['MARGIN-FOOTER'])) { $mgf = $this->ConvertSize($p['MARGIN-FOOTER'],$pgh) + $outer_width_TB; }
14400
14401 if (isset($p['ORIENTATION']) && $p['ORIENTATION']) { $orientation = $p['ORIENTATION']; }
14402 $this->page_box['outer_width_LR'] = $outer_width_LR; // Used in MARKS:crop etc.
14403 $this->page_box['outer_width_TB'] = $outer_width_TB;
14404
14405 return array($orientation,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$header,$footer,$bg,$resetpagenum,$pagenumstyle,$suppress,$marks,$newformat);
14406 }
14407 /*-- END CSS-PAGE --*/
14408
14409
14410
14411 /*-- CSS-FLOAT --*/
14412 // Added mPDF 3.0 Float DIV - CLEAR
14413 function ClearFloats($clear, $blklvl=0) {
14414 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($blklvl,true);
14415 $end = $currpos = ($this->page*1000 + $this->y);
14416 if ($clear == 'BOTH' && ($l_exists || $r_exists)) {
14417 $this->pageoutput[$this->page] = array();
14418 $end = max($l_max, $r_max, $currpos);
14419 }
14420 else if ($clear == 'RIGHT' && $r_exists) {
14421 $this->pageoutput[$this->page] = array();
14422 $end = max($r_max, $currpos);
14423 }
14424 else if ($clear == 'LEFT' && $l_exists ) {
14425 $this->pageoutput[$this->page] = array();
14426 $end = max($l_max, $currpos);
14427 }
14428 else { return; }
14429 $old_page = $this->page;
14430 $new_page = intval($end/1000);
14431 if ($old_page != $new_page) {
14432 $s = $this->PrintPageBackgrounds();
14433 // Writes after the marker so not overwritten later by page background etc.
14434 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
14435 $this->pageBackgrounds = array();
14436 $this->page = $new_page;
14437 }
14438 $this->ResetMargins();
14439 $this->pageoutput[$this->page] = array();
14440 $this->y = (($end*1000) % 1000000)/1000; // mod changes operands to integers before processing
14441 }
14442
14443
14444 // Added mPDF 3.0 Float DIV
14445 function GetFloatDivInfo($blklvl=0,$clear=false) {
14446 // If blklvl specified, only returns floats at that level - for ClearFloats
14447 $l_exists = false;
14448 $r_exists = false;
14449 $l_max = 0;
14450 $r_max = 0;
14451 $l_width = 0;
14452 $r_width = 0;
14453 if (count($this->floatDivs)) {
14454 $currpos = ($this->page*1000 + $this->y);
14455 foreach($this->floatDivs AS $f) {
14456 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'])) {
14457 if ($f['side']=='L') {
14458 $l_exists= true;
14459 $l_max = max($l_max, $f['endpos']);
14460 $l_width = max($l_width , $f['w']);
14461 }
14462 if ($f['side']=='R') {
14463 $r_exists= true;
14464 $r_max = max($r_max, $f['endpos']);
14465 $r_width = max($r_width , $f['w']);
14466 }
14467 }
14468 }
14469 }
14470 return array($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width);
14471 }
14472 /*-- END CSS-FLOAT --*/
14473
14474
14475
14476
14477 function OpenTag($tag,$attr)
14478 {
14479
14480 // What this gets: < $tag $attr['WIDTH']="90px" > does not get content here </closeTag here>
14481 // Correct tags where HTML specifies optional end tags,
14482 // and/or does not allow nesting e.g. P inside P, or
14483 if ($this->allow_html_optional_endtags) {
14484 if (($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' ) && $this->lastoptionaltag == 'P') { $this->CloseTag($this->lastoptionaltag ); }
14485 if ($tag == 'DD' && $this->lastoptionaltag == 'DD') { $this->CloseTag($this->lastoptionaltag ); }
14486 if ($tag == 'DD' && $this->lastoptionaltag == 'DT') { $this->CloseTag($this->lastoptionaltag ); }
14487 if ($tag == 'DT' && $this->lastoptionaltag == 'DD') { $this->CloseTag($this->lastoptionaltag ); }
14488 if ($tag == 'DT' && $this->lastoptionaltag == 'DT') { $this->CloseTag($this->lastoptionaltag ); }
14489 if ($tag == 'LI' && $this->lastoptionaltag == 'LI') { $this->CloseTag($this->lastoptionaltag ); }
14490 if (($tag == 'TD' || $tag == 'TH') && $this->lastoptionaltag == 'TD') { $this->CloseTag($this->lastoptionaltag ); } // *TABLES*
14491 if (($tag == 'TD' || $tag == 'TH') && $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag ); } // *TABLES*
14492 if ($tag == 'TR' && $this->lastoptionaltag == 'TR') { $this->CloseTag($this->lastoptionaltag ); } // *TABLES*
14493 if ($tag == 'TR' && $this->lastoptionaltag == 'TD') { $this->CloseTag($this->lastoptionaltag ); $this->CloseTag('TR'); $this->CloseTag('THEAD'); } // *TABLES*
14494 if ($tag == 'TR' && $this->lastoptionaltag == 'TH') { $this->CloseTag($this->lastoptionaltag ); $this->CloseTag('TR'); $this->CloseTag('THEAD'); } // *TABLES*
14495 if ($tag == 'OPTION' && $this->lastoptionaltag == 'OPTION') { $this->CloseTag($this->lastoptionaltag ); }
14496 }
14497
14498 $align = array('left'=>'L','center'=>'C','right'=>'R','top'=>'T','text-top'=>'TT','middle'=>'M','baseline'=>'BS','bottom'=>'B','text-bottom'=>'TB','justify'=>'J');
14499
14500 $this->ignorefollowingspaces=false;
14501
14502 //Opening tag
14503 switch($tag){
14504
14505 case 'DOTTAB':
14506 $objattr = array();
14507 $objattr['type'] = 'dottab';
14508 $dots=str_repeat('.', 3)." "; // minimum number of dots
14509 $objattr['width'] = $this->GetStringWidth($dots);
14510 $objattr['margin_top'] = 0;
14511 $objattr['margin_bottom'] = 0;
14512 $objattr['margin_left'] = 0;
14513 $objattr['margin_right'] = 0;
14514 $objattr['height'] = 0;
14515 $objattr['colorarray'] = $this->colorarray;
14516 $objattr['border_top']['w'] = 0;
14517 $objattr['border_bottom']['w'] = 0;
14518 $objattr['border_left']['w'] = 0;
14519 $objattr['border_right']['w'] = 0;
14520
14521 // mPDF 5.6.19
14522 $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr); // mPDF 5.6.33
14523 if (isset($properties['OUTDENT'])) { // mPDF 5.6.33
14524 $objattr['outdent'] = $this->ConvertSize($properties['OUTDENT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14525 }
14526 else if (isset($attr['OUTDENT'])) {
14527 $objattr['outdent'] = $this->ConvertSize($attr['OUTDENT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
14528 }
14529 else { $objattr['outdent'] = 0; }
14530
14531 $objattr['fontfamily'] = $this->FontFamily;
14532 $objattr['fontsize'] = $this->FontSizePt;
14533
14534 $e = "\xbb\xa4\xactype=dottab,objattr=".serialize($objattr)."\xbb\xa4\xac";
14535 /*-- TABLES --*/
14536 // Output it to buffers
14537 if ($this->tableLevel) {
14538 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
14539 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
14540 }
14541 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
14542 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
14543 }
14544 $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
14545 $this->_saveCellTextBuffer($e);
14546 }
14547 else {
14548 /*-- END TABLES --*/
14549 $this->_saveTextBuffer($e);
14550 } // *TABLES*
14551 break;
14552
14553 case 'PAGEHEADER':
14554 case 'PAGEFOOTER':
14555 $this->ignorefollowingspaces = true;
14556 if ($attr['NAME']) { $pname = $attr['NAME']; }
14557 else { $pname = '_default'; }
14558
14559 if ($tag=='PAGEHEADER') { $p = &$this->pageheaders[$pname]; }
14560 else { $p = &$this->pagefooters[$pname]; }
14561
14562 $p['L']=array();
14563 $p['C']=array();
14564 $p['R']=array();
14565 $p['L']['font-style'] = '';
14566 $p['C']['font-style'] = '';
14567 $p['R']['font-style'] = '';
14568
14569 if (isset($attr['CONTENT-LEFT'])) {
14570 $p['L']['content'] = $attr['CONTENT-LEFT'];
14571 }
14572 if (isset($attr['CONTENT-CENTER'])) {
14573 $p['C']['content'] = $attr['CONTENT-CENTER'];
14574 }
14575 if (isset($attr['CONTENT-RIGHT'])) {
14576 $p['R']['content'] = $attr['CONTENT-RIGHT'];
14577 }
14578
14579 if (isset($attr['HEADER-STYLE']) || isset($attr['FOOTER-STYLE'])) { // font-family,size,weight,style,color
14580 if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE']); }
14581 else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE']); }
14582 if (isset($properties['FONT-FAMILY'])) {
14583 $p['L']['font-family'] = $properties['FONT-FAMILY'];
14584 $p['C']['font-family'] = $properties['FONT-FAMILY'];
14585 $p['R']['font-family'] = $properties['FONT-FAMILY'];
14586 }
14587 if (isset($properties['FONT-SIZE'])) {
14588 $p['L']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK;
14589 $p['C']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK;
14590 $p['R']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK;
14591 }
14592 if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') {
14593 $p['L']['font-style'] = 'B';
14594 $p['C']['font-style'] = 'B';
14595 $p['R']['font-style'] = 'B';
14596 }
14597 if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') {
14598 $p['L']['font-style'] .= 'I';
14599 $p['C']['font-style'] .= 'I';
14600 $p['R']['font-style'] .= 'I';
14601 }
14602 if (isset($properties['COLOR'])) {
14603 $p['L']['color'] = $properties['COLOR'];
14604 $p['C']['color'] = $properties['COLOR'];
14605 $p['R']['color'] = $properties['COLOR'];
14606 }
14607 }
14608 if (isset($attr['HEADER-STYLE-LEFT']) || isset($attr['FOOTER-STYLE-LEFT'])) {
14609 if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE-LEFT']); }
14610 else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE-LEFT']); }
14611 if (isset($properties['FONT-FAMILY'])) { $p['L']['font-family'] = $properties['FONT-FAMILY']; }
14612 if (isset($properties['FONT-SIZE'])) { $p['L']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK; }
14613 if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') { $p['L']['font-style'] ='B'; }
14614 if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') { $p['L']['font-style'] .='I'; }
14615 if (isset($properties['COLOR'])) { $p['L']['color'] = $properties['COLOR']; }
14616 }
14617 if (isset($attr['HEADER-STYLE-CENTER']) || isset($attr['FOOTER-STYLE-CENTER'])) {
14618 if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE-CENTER']); }
14619 else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE-CENTER']); }
14620 if (isset($properties['FONT-FAMILY'])) { $p['C']['font-family'] = $properties['FONT-FAMILY']; }
14621 if (isset($properties['FONT-SIZE'])) { $p['C']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK; }
14622 if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') { $p['C']['font-style'] = 'B'; }
14623 if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') { $p['C']['font-style'] .= 'I'; }
14624 if (isset($properties['COLOR'])) { $p['C']['color'] = $properties['COLOR']; }
14625 }
14626 if (isset($attr['HEADER-STYLE-RIGHT']) || isset($attr['FOOTER-STYLE-RIGHT'])) {
14627 if ($tag=='PAGEHEADER') { $properties = $this->cssmgr->readInlineCSS($attr['HEADER-STYLE-RIGHT']); }
14628 else { $properties = $this->cssmgr->readInlineCSS($attr['FOOTER-STYLE-RIGHT']); }
14629 if (isset($properties['FONT-FAMILY'])) { $p['R']['font-family'] = $properties['FONT-FAMILY']; }
14630 if (isset($properties['FONT-SIZE'])) { $p['R']['font-size'] = $this->ConvertSize($properties['FONT-SIZE']) * _MPDFK; }
14631 if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT']=='bold') { $p['R']['font-style'] = 'B'; }
14632 if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE']=='italic') { $p['R']['font-style'] .= 'I'; }
14633 if (isset($properties['COLOR'])) { $p['R']['color'] = $properties['COLOR']; }
14634 }
14635 if (isset($attr['LINE']) && $attr['LINE']) { // 0|1|on|off
14636 if ($attr['LINE']=='1' || strtoupper($attr['LINE'])=='ON') { $lineset=1; }
14637 else { $lineset=0; }
14638 $p['line'] = $lineset;
14639 }
14640 break;
14641
14642
14643 /*-- HTMLHEADERS-FOOTERS --*/
14644 case 'SETHTMLPAGEHEADER':
14645 case 'SETHTMLPAGEFOOTER':
14646 $this->ignorefollowingspaces = true;
14647 if (isset($attr['NAME']) && $attr['NAME']) { $pname = $attr['NAME']; }
14648 else { $pname = '_default'; }
14649 if (isset($attr['PAGE']) && $attr['PAGE']) { // O|odd|even|E|ALL|[blank]
14650 if (strtoupper($attr['PAGE'])=='O' || strtoupper($attr['PAGE'])=='ODD') { $side='odd'; }
14651 else if (strtoupper($attr['PAGE'])=='E' || strtoupper($attr['PAGE'])=='EVEN') { $side='even'; }
14652 else if (strtoupper($attr['PAGE'])=='ALL') { $side='both'; }
14653 else { $side='odd'; }
14654 }
14655 else { $side='odd'; }
14656 if (isset($attr['VALUE']) && $attr['VALUE']) { // -1|1|on|off
14657 if ($attr['VALUE']=='1' || strtoupper($attr['VALUE'])=='ON') { $set=1; }
14658 else if ($attr['VALUE']=='-1' || strtoupper($attr['VALUE'])=='OFF') { $set=0; }
14659 else { $set=1; }
14660 }
14661 else { $set=1; }
14662 if (isset($attr['SHOW-THIS-PAGE']) && $attr['SHOW-THIS-PAGE'] && $tag=='SETHTMLPAGEHEADER') { $write = 1; }
14663 else { $write = 0; }
14664 if ($side=='odd' || $side=='both') {
14665 if ($set && $tag=='SETHTMLPAGEHEADER') { $this->SetHTMLHeader($this->pageHTMLheaders[$pname],'O',$write); }
14666 else if ($set && $tag=='SETHTMLPAGEFOOTER') { $this->SetHTMLFooter($this->pageHTMLfooters[$pname],'O'); }
14667 else if ($tag=='SETHTMLPAGEHEADER') { $this->SetHTMLHeader('','O'); }
14668 else { $this->SetHTMLFooter('','O'); }
14669 }
14670 if ($side=='even' || $side=='both') {
14671 if ($set && $tag=='SETHTMLPAGEHEADER') { $this->SetHTMLHeader($this->pageHTMLheaders[$pname],'E',$write); }
14672 else if ($set && $tag=='SETHTMLPAGEFOOTER') { $this->SetHTMLFooter($this->pageHTMLfooters[$pname],'E'); }
14673 else if ($tag=='SETHTMLPAGEHEADER') { $this->SetHTMLHeader('','E'); }
14674 else { $this->SetHTMLFooter('','E'); }
14675 }
14676 break;
14677 /*-- END HTMLHEADERS-FOOTERS --*/
14678
14679 case 'SETPAGEHEADER':
14680 case 'SETPAGEFOOTER':
14681 $this->ignorefollowingspaces = true;
14682 if (isset($attr['NAME']) && $attr['NAME']) { $pname = $attr['NAME']; }
14683 else { $pname = '_default'; }
14684 if (isset($attr['PAGE']) && $attr['PAGE']) { // O|odd|even|E|ALL|[blank]
14685 if (strtoupper($attr['PAGE'])=='O' || strtoupper($attr['PAGE'])=='ODD') { $side='odd'; }
14686 else if (strtoupper($attr['PAGE'])=='E' || strtoupper($attr['PAGE'])=='EVEN') { $side='even'; }
14687 else if (strtoupper($attr['PAGE'])=='ALL') { $side='both'; }
14688 else { $side='odd'; }
14689 }
14690 else { $side='odd'; }
14691 if (isset($attr['VALUE']) && $attr['VALUE']) { // -1|1|on|off
14692 if ($attr['VALUE']=='1' || strtoupper($attr['VALUE'])=='ON') { $set=1; }
14693 else if ($attr['VALUE']=='-1' || strtoupper($attr['VALUE'])=='OFF') { $set=0; }
14694 else { $set=1; }
14695 }
14696 else { $set=1; }
14697 if ($side=='odd' || $side=='both') {
14698 if ($set && $tag=='SETPAGEHEADER') { $this->headerDetails['odd'] = $this->pageheaders[$pname]; }
14699 else if ($set && $tag=='SETPAGEFOOTER') { $this->footerDetails['odd'] = $this->pagefooters[$pname]; }
14700 else if ($tag=='SETPAGEHEADER') { $this->headerDetails['odd'] = array(); }
14701 else { $this->footerDetails['odd'] = array(); }
14702 if (!$this->mirrorMargins || ($this->page)%2!=0) { // ODD
14703 if ($tag=='SETPAGEHEADER') { $this->_setAutoHeaderHeight($this->headerDetails['odd'],$this->HTMLHeader); }
14704 if ($tag=='SETPAGEFOOTER') { $this->_setAutoFooterHeight($this->footerDetails['odd'],$this->HTMLFooter); }
14705 }
14706 }
14707 if ($side=='even' || $side=='both') {
14708 if ($set && $tag=='SETPAGEHEADER') { $this->headerDetails['even'] = $this->pageheaders[$pname]; }
14709 else if ($set && $tag=='SETPAGEFOOTER') { $this->footerDetails['even'] = $this->pagefooters[$pname]; }
14710 else if ($tag=='SETPAGEHEADER') { $this->headerDetails['even'] = array(); }
14711 else { $this->footerDetails['even'] = array(); }
14712 if ($this->mirrorMargins && ($this->page)%2==0) { // EVEN
14713 if ($tag=='SETPAGEHEADER') { $this->_setAutoHeaderHeight($this->headerDetails['even'],$this->HTMLHeaderE); }
14714 if ($tag=='SETPAGEFOOTER') { $this->_setAutoFooterHeight($this->footerDetails['even'],$this->HTMLFooterE); }
14715 }
14716 }
14717 if (isset($attr['SHOW-THIS-PAGE']) && $attr['SHOW-THIS-PAGE'] && $tag=='SETPAGEHEADER') {
14718 $this->Header();
14719 }
14720 break;
14721
14722
14723 /*-- TOC --*/
14724 case 'TOC': //added custom-tag - set Marker for insertion later of ToC
14725 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
14726 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
14727 $this->tocontents->openTagTOC($attr);
14728 break;
14729
14730
14731
14732 case 'TOCPAGEBREAK': // custom-tag - set Marker for insertion later of ToC AND adds PAGEBREAK
14733 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
14734 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
14735 list($isbreak,$toc_id) = $this->tocontents->openTagTOCPAGEBREAK($attr);
14736 if ($isbreak) break;
14737 // No break - continues as PAGEBREAK...
14738 /*-- END TOC --*/
14739
14740
14741 case 'PAGE_BREAK': //custom-tag
14742 case 'PAGEBREAK': //custom-tag
14743 case 'NEWPAGE': //custom-tag
14744 case 'FORMFEED': //custom-tag
14745
14746 $save_blklvl = $this->blklvl;
14747 $save_blk = $this->blk;
14748 $save_silp = $this->saveInlineProperties();
14749 $save_spanlvl = $this->spanlvl;
14750 $save_ilp = $this->InlineProperties;
14751
14752 // Close any open block tags
14753 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
14754 if(!empty($this->textbuffer)) { //Output previously buffered content
14755 $this->printbuffer($this->textbuffer);
14756 $this->textbuffer=array();
14757 }
14758 $this->ignorefollowingspaces = true;
14759 $save_cols = false;
14760 /*-- COLUMNS --*/
14761 if ($this->ColActive) {
14762 $save_cols = true;
14763 $save_nbcol = $this->NbCol; // other values of gap and vAlign will not change by setting Columns off
14764 $this->SetColumns(0);
14765 }
14766 /*-- END COLUMNS --*/
14767
14768
14769 if (isset($attr['SHEET-SIZE']) && $tag != 'FORMFEED' && !$this->restoreBlockPageBreaks) {
14770 // Convert to same types as accepted in initial mPDF() A4, A4-L, or array(w,h)
14771 $prop = preg_split('/\s+/',trim($attr['SHEET-SIZE']));
14772 if (count($prop) == 2 ) {
14773 $newformat = array($this->ConvertSize($prop[0]), $this->ConvertSize($prop[1]));
14774 }
14775 else { $newformat = $attr['SHEET-SIZE']; }
14776 }
14777 else { $newformat = ''; }
14778
14779 $mgr = $mgl = $mgt = $mgb = $mgh = $mgf = '';
14780 if (isset($attr['MARGIN-RIGHT'])) { $mgr = $this->ConvertSize($attr['MARGIN-RIGHT'],$this->w,$this->FontSize,false); }
14781 if (isset($attr['MARGIN-LEFT'])) { $mgl = $this->ConvertSize($attr['MARGIN-LEFT'],$this->w,$this->FontSize,false); }
14782 if (isset($attr['MARGIN-TOP'])) { $mgt = $this->ConvertSize($attr['MARGIN-TOP'],$this->w,$this->FontSize,false); }
14783 if (isset($attr['MARGIN-BOTTOM'])) { $mgb = $this->ConvertSize($attr['MARGIN-BOTTOM'],$this->w,$this->FontSize,false); }
14784 if (isset($attr['MARGIN-HEADER'])) { $mgh = $this->ConvertSize($attr['MARGIN-HEADER'],$this->w,$this->FontSize,false); }
14785 if (isset($attr['MARGIN-FOOTER'])) { $mgf = $this->ConvertSize($attr['MARGIN-FOOTER'],$this->w,$this->FontSize,false); }
14786 $ohname = $ehname = $ofname = $efname = '';
14787 if (isset($attr['ODD-HEADER-NAME'])) { $ohname = $attr['ODD-HEADER-NAME']; }
14788 if (isset($attr['EVEN-HEADER-NAME'])) { $ehname = $attr['EVEN-HEADER-NAME']; }
14789 if (isset($attr['ODD-FOOTER-NAME'])) { $ofname = $attr['ODD-FOOTER-NAME']; }
14790 if (isset($attr['EVEN-FOOTER-NAME'])) { $efname = $attr['EVEN-FOOTER-NAME']; }
14791 $ohvalue = $ehvalue = $ofvalue = $efvalue = 0;
14792 if (isset($attr['ODD-HEADER-VALUE']) && ($attr['ODD-HEADER-VALUE']=='1' || strtoupper($attr['ODD-HEADER-VALUE'])=='ON')) { $ohvalue = 1; }
14793 else if (isset($attr['ODD-HEADER-VALUE']) && ($attr['ODD-HEADER-VALUE']=='-1' || strtoupper($attr['ODD-HEADER-VALUE'])=='OFF')) { $ohvalue = -1; }
14794 if (isset($attr['EVEN-HEADER-VALUE']) && ($attr['EVEN-HEADER-VALUE']=='1' || strtoupper($attr['EVEN-HEADER-VALUE'])=='ON')) { $ehvalue = 1; }
14795 else if (isset($attr['EVEN-HEADER-VALUE']) && ($attr['EVEN-HEADER-VALUE']=='-1' || strtoupper($attr['EVEN-HEADER-VALUE'])=='OFF')) { $ehvalue = -1; }
14796 if (isset($attr['ODD-FOOTER-VALUE']) && ($attr['ODD-FOOTER-VALUE']=='1' || strtoupper($attr['ODD-FOOTER-VALUE'])=='ON')) { $ofvalue = 1; }
14797 else if (isset($attr['ODD-FOOTER-VALUE']) && ($attr['ODD-FOOTER-VALUE']=='-1' || strtoupper($attr['ODD-FOOTER-VALUE'])=='OFF')) { $ofvalue = -1; }
14798 if (isset($attr['EVEN-FOOTER-VALUE']) && ($attr['EVEN-FOOTER-VALUE']=='1' || strtoupper($attr['EVEN-FOOTER-VALUE'])=='ON')) { $efvalue = 1; }
14799 else if (isset($attr['EVEN-FOOTER-VALUE']) && ($attr['EVEN-FOOTER-VALUE']=='-1' || strtoupper($attr['EVEN-FOOTER-VALUE'])=='OFF')) { $efvalue = -1; }
14800
14801 if (isset($attr['ORIENTATION']) && (strtoupper($attr['ORIENTATION'])=='L' || strtoupper($attr['ORIENTATION'])=='LANDSCAPE')) { $orient = 'L'; }
14802 else if (isset($attr['ORIENTATION']) && (strtoupper($attr['ORIENTATION'])=='P' || strtoupper($attr['ORIENTATION'])=='PORTRAIT')) { $orient = 'P'; }
14803 else { $orient = $this->CurOrientation; }
14804
14805 if (isset($attr['PAGE-SELECTOR']) && $attr['PAGE-SELECTOR']) { $pagesel = $attr['PAGE-SELECTOR']; }
14806 else { $pagesel = ''; }
14807
14808 $resetpagenum = '';
14809 $pagenumstyle = '';
14810 $suppress = '';
14811 if (isset($attr['RESETPAGENUM'])) { $resetpagenum = $attr['RESETPAGENUM']; }
14812 if (isset($attr['PAGENUMSTYLE'])) { $pagenumstyle = $attr['PAGENUMSTYLE']; }
14813 if (isset($attr['SUPPRESS'])) { $suppress = $attr['SUPPRESS']; }
14814
14815 if ($tag == 'TOCPAGEBREAK') { $type = 'NEXT-ODD'; }
14816 else if(isset($attr['TYPE'])) { $type = strtoupper($attr['TYPE']); }
14817 else { $type = ''; }
14818
14819 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); }
14820 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); }
14821 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); }
14822 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); }
14823 else { $this->AddPage($orient,'', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$newformat); }
14824
14825 /*-- TOC --*/
14826 if ($tag == 'TOCPAGEBREAK') {
14827 if ($toc_id) { $this->tocontents->m_TOC[$toc_id]['TOCmark'] = $this->page; }
14828 else { $this->tocontents->TOCmark = $this->page; }
14829 }
14830 /*-- END TOC --*/
14831
14832 /*-- COLUMNS --*/
14833 if ($save_cols) {
14834 // Restore columns
14835 $this->SetColumns($save_nbcol,$this->colvAlign,$this->ColGap);
14836 }
14837 /*-- END COLUMNS --*/
14838 if (($tag == 'FORMFEED' || $this->restoreBlockPagebreaks) && !$this->tableLevel && !$this->listlvl) {
14839 $this->blk = $save_blk;
14840 // Re-open block tags
14841 $t = $this->blk[0]['tag'];
14842 $a = $this->blk[0]['attr'];
14843 $this->blklvl = 0;
14844 for ($b=0; $b<=$save_blklvl;$b++) {
14845 $tc = $t;
14846 $ac = $a;
14847 $t = $this->blk[$b+1]['tag'];
14848 $a = $this->blk[$b+1]['attr'];
14849 unset($this->blk[$b+1]);
14850 $this->OpenTag($tc,$ac);
14851 }
14852 $this->spanlvl = $save_spanlvl;
14853 $this->InlineProperties = $save_ilp;
14854 $this->restoreInlineProperties($save_silp);
14855 }
14856
14857 break;
14858
14859
14860 /*-- TOC --*/
14861 case 'TOCENTRY':
14862 if (isset($attr['CONTENT']) && $attr['CONTENT']) {
14863 $objattr = array();
14864 $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES);
14865 $objattr['type'] = 'toc';
14866 if (isset($attr['LEVEL']) && $attr['LEVEL']) { $objattr['toclevel'] = $attr['LEVEL']; } else { $objattr['toclevel'] = 0; }
14867 if (isset($attr['NAME']) && $attr['NAME']) { $objattr['toc_id'] = $attr['NAME']; } else { $objattr['toc_id'] = 0; }
14868 $e = "\xbb\xa4\xactype=toc,objattr=".serialize($objattr)."\xbb\xa4\xac";
14869 if($this->tableLevel) { $this->cell[$this->row][$this->col]['textbuffer'][] = array($e); } // *TABLES*
14870 else { // *TABLES*
14871 $this->textbuffer[] = array($e);
14872 } // *TABLES*
14873 }
14874 break;
14875 /*-- END TOC --*/
14876
14877 /*-- INDEX --*/
14878 case 'INDEXENTRY':
14879 if (isset($attr['CONTENT']) && $attr['CONTENT']) {
14880 if (isset($attr['XREF']) && $attr['XREF']) {
14881 $this->IndexEntry(htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES),$attr['XREF']);
14882 break;
14883 }
14884 $objattr = array();
14885 $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES);
14886 $objattr['type'] = 'indexentry';
14887 $e = "\xbb\xa4\xactype=indexentry,objattr=".serialize($objattr)."\xbb\xa4\xac";
14888 if($this->tableLevel) { $this->cell[$this->row][$this->col]['textbuffer'][] = array($e); } // *TABLES*
14889 else { // *TABLES*
14890 $this->textbuffer[] = array($e);
14891 } // *TABLES*
14892 }
14893 break;
14894
14895
14896 case 'INDEXINSERT':
14897 if (isset($attr['FONT-SIZE'])) { $reffontsize = $attr['FONT-SIZE']; } else { $reffontsize = ''; }
14898 if (isset($attr['LINE-SPACING']) && $attr['LINE-SPACING']) { $linespacing = $attr['LINE-SPACING']; } else { $linespacing = ''; }
14899 if (isset($attr['DIV-FONT-SIZE']) && $attr['DIV-FONT-SIZE']) { $divlettfontsize = $attr['DIV-FONT-SIZE']; } else { $divlettfontsize = ''; }
14900 if (isset($attr['FONT']) && $attr['FONT']) { $reffont = $attr['FONT']; } else { $reffont = ''; }
14901 if (isset($attr['DIV-FONT']) && $attr['DIV-FONT']) { $divlettfont = $attr['DIV-FONT']; } else { $divlettfont = ''; }
14902 if (isset($attr['COLS']) && $attr['COLS']) { $cols = $attr['COLS']; } else { $cols = 1; }
14903 if (isset($attr['OFFSET']) && $attr['OFFSET']) { $offset = $attr['OFFSET']; } else { $offset = 3; }
14904 if (isset($attr['GAP']) && $attr['GAP']) { $gap = $attr['GAP']; } else { $gap = 5; }
14905
14906 if (isset($attr['USEDIVLETTERS']) && (strtoupper($attr['USEDIVLETTERS'])=='OFF' || $attr['USEDIVLETTERS']==-1 || $attr['USEDIVLETTERS']==='0')) { $usedivletters = 0; }
14907 else { $usedivletters = 1; }
14908
14909 if (isset($attr['LINKS']) && (strtoupper($attr['LINKS'])=='ON' || $attr['LINKS']==1)) { $links = true; }
14910 else { $links = false; }
14911 $this->CreateIndex($cols, $reffontsize, $linespacing, $offset, $usedivletters, $divlettfontsize, $gap, $reffont,$divlettfont, $links);
14912 break;
14913 /*-- END INDEX --*/
14914
14915 /*-- WATERMARK --*/
14916
14917 case 'WATERMARKTEXT':
14918 if (isset($attr['CONTENT']) && $attr['CONTENT']) { $txt = htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES); } else { $txt = ''; }
14919 if (isset($attr['ALPHA']) && $attr['ALPHA']>0) { $alpha = $attr['ALPHA']; } else { $alpha = -1; }
14920 $this->SetWatermarkText($txt, $alpha);
14921 break;
14922
14923
14924 case 'WATERMARKIMAGE':
14925 if (isset($attr['SRC'])) { $src = $attr['SRC']; } else { $src = ''; }
14926 if (isset($attr['ALPHA']) && $attr['ALPHA']>0) { $alpha = $attr['ALPHA']; } else { $alpha = -1; }
14927 if (isset($attr['SIZE']) && $attr['SIZE']) {
14928 $size = $attr['SIZE'];
14929 if (strpos($size,',')) { $size = explode(',',$size); }
14930 }
14931 else { $size = 'D'; }
14932 if (isset($attr['POS']) && $attr['POS']) {
14933 $pos = $attr['POS'];
14934 if (strpos($pos,',')) { $pos = explode(',',$pos); }
14935 }
14936 else { $pos = 'P'; }
14937 $this->SetWatermarkImage($src, $alpha, $size, $pos);
14938 break;
14939 /*-- END WATERMARK --*/
14940
14941 /*-- BOOKMARKS --*/
14942 case 'BOOKMARK':
14943 if (isset($attr['CONTENT'])) {
14944 $objattr = array();
14945 $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES);
14946 $objattr['type'] = 'bookmark';
14947 if (isset($attr['LEVEL']) && $attr['LEVEL']) { $objattr['bklevel'] = $attr['LEVEL']; } else { $objattr['bklevel'] = 0; }
14948 $e = "\xbb\xa4\xactype=bookmark,objattr=".serialize($objattr)."\xbb\xa4\xac";
14949 if($this->tableLevel) { $this->cell[$this->row][$this->col]['textbuffer'][] = array($e); } // *TABLES*
14950 else { // *TABLES*
14951 $this->textbuffer[] = array($e);
14952 } // *TABLES*
14953 }
14954 break;
14955 /*-- END BOOKMARKS --*/
14956
14957 /*-- ANNOTATIONS --*/
14958 case 'ANNOTATION':
14959
14960 //if (isset($attr['CONTENT']) && !$this->writingHTMLheader && !$this->writingHTMLfooter) { // Stops annotations in FixedPos
14961 if (isset($attr['CONTENT'])) {
14962 $objattr = array();
14963 $objattr['margin_top'] = 0;
14964 $objattr['margin_bottom'] = 0;
14965 $objattr['margin_left'] = 0;
14966 $objattr['margin_right'] = 0;
14967 $objattr['width'] = 0;
14968 $objattr['height'] = 0;
14969 $objattr['border_top']['w'] = 0;
14970 $objattr['border_bottom']['w'] = 0;
14971 $objattr['border_left']['w'] = 0;
14972 $objattr['border_right']['w'] = 0;
14973 $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'],ENT_QUOTES);
14974 $objattr['type'] = 'annot';
14975 $objattr['POPUP'] = '';
14976 }
14977 else { break; }
14978 if (isset($attr['POS-X'])) { $objattr['POS-X'] = $attr['POS-X']; } else { $objattr['POS-X'] = 0; }
14979 if (isset($attr['POS-Y'])) { $objattr['POS-Y'] = $attr['POS-Y']; } else { $objattr['POS-Y'] = 0; }
14980 if (isset($attr['ICON'])) { $objattr['ICON'] = $attr['ICON']; } else { $objattr['ICON'] = 'Note'; }
14981 if (isset($attr['AUTHOR'])) { $objattr['AUTHOR'] = $attr['AUTHOR']; }
14982 else if (isset($attr['TITLE'])) { $objattr['AUTHOR'] = $attr['TITLE']; } else { $objattr['AUTHOR'] = ''; }
14983 if (isset($attr['FILE'])) { $objattr['FILE'] = $attr['FILE']; } else { $objattr['FILE'] = ''; }
14984 if (isset($attr['SUBJECT'])) { $objattr['SUBJECT'] = $attr['SUBJECT']; } else { $objattr['SUBJECT'] = ''; }
14985 if (isset($attr['OPACITY']) && $attr['OPACITY']>0 && $attr['OPACITY']<=1) { $objattr['OPACITY'] = $attr['OPACITY']; }
14986 else if ($this->annotMargin) { $objattr['OPACITY'] = 1; }
14987 else { $objattr['OPACITY'] = $this->annotOpacity; }
14988 if (isset($attr['COLOR'])) {
14989 $cor = $this->ConvertColor($attr['COLOR']);
14990 if ($cor) { $objattr['COLOR'] = $cor; }
14991 else { $objattr['COLOR'] = $this->ConvertColor('yellow'); }
14992 }
14993 else { $objattr['COLOR'] = $this->ConvertColor('yellow'); }
14994
14995 if (isset($attr['POPUP']) && !empty($attr['POPUP'])) {
14996 $pop = preg_split('/\s+/',trim($attr['POPUP']));
14997 if (count($pop)>1) { $objattr['POPUP'] = $pop; }
14998 else { $objattr['POPUP'] = true; }
14999 }
15000 $e = "\xbb\xa4\xactype=annot,objattr=".serialize($objattr)."\xbb\xa4\xac";
15001 if($this->tableLevel) { $this->cell[$this->row][$this->col]['textbuffer'][] = array($e); } // *TABLES*
15002 else { // *TABLES*
15003 $this->textbuffer[] = array($e);
15004 } // *TABLES*
15005 break;
15006 /*-- END ANNOTATIONS --*/
15007
15008
15009 /*-- COLUMNS --*/
15010 case 'COLUMNS': //added custom-tag
15011 if (isset($attr['COLUMN-COUNT']) && ($attr['COLUMN-COUNT'] || $attr['COLUMN-COUNT']==='0')) {
15012 // Close any open block tags
15013 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
15014 if(!empty($this->textbuffer)) { //Output previously buffered content
15015 $this->printbuffer($this->textbuffer);
15016 $this->textbuffer=array();
15017 }
15018
15019 if (isset($attr['VALIGN']) && $attr['VALIGN']) {
15020 if ($attr['VALIGN'] == 'J') { $valign = 'J'; }
15021 else { $valign = $align[$attr['VALIGN']]; }
15022 }
15023 else { $valign = ''; }
15024 if (isset($attr['COLUMN-GAP']) && $attr['COLUMN-GAP']) { $this->SetColumns($attr['COLUMN-COUNT'],$valign,$attr['COLUMN-GAP']); }
15025 else { $this->SetColumns($attr['COLUMN-COUNT'],$valign); }
15026 }
15027 $this->ignorefollowingspaces = true;
15028 break;
15029
15030 case 'COLUMN_BREAK': //custom-tag
15031 case 'COLUMNBREAK': //custom-tag
15032 case 'NEWCOLUMN': //custom-tag
15033 $this->ignorefollowingspaces = true;
15034 $this->NewColumn();
15035 $this->ColumnAdjust = false; // disables all column height adjustment for the page.
15036 break;
15037
15038 /*-- END COLUMNS --*/
15039
15040
15041 case 'BDO':
15042 // $this->biDirectional = true;
15043 break;
15044
15045
15046 case 'TTZ':
15047 $this->ttz = true;
15048 $this->InlineProperties[$tag] = $this->saveInlineProperties();
15049 $this->setCSS(array('FONT-FAMILY'=>'czapfdingbats','FONT-WEIGHT'=>'normal','FONT-STYLE'=>'normal'),'INLINE');
15050 break;
15051
15052 case 'TTS':
15053 $this->tts = true;
15054 $this->InlineProperties[$tag] = $this->saveInlineProperties();
15055 $this->setCSS(array('FONT-FAMILY'=>'csymbol','FONT-WEIGHT'=>'normal','FONT-STYLE'=>'normal'),'INLINE');
15056 break;
15057
15058 case 'TTA':
15059 $this->tta = true;
15060 $this->InlineProperties[$tag] = $this->saveInlineProperties();
15061
15062 if (in_array($this->FontFamily,$this->mono_fonts)) {
15063 $this->setCSS(array('FONT-FAMILY'=>'ccourier'),'INLINE');
15064 }
15065 else if (in_array($this->FontFamily,$this->serif_fonts)) {
15066 $this->setCSS(array('FONT-FAMILY'=>'ctimes'),'INLINE');
15067 }
15068 else {
15069 $this->setCSS(array('FONT-FAMILY'=>'chelvetica'),'INLINE');
15070 }
15071 break;
15072
15073
15074
15075 // INLINE PHRASES OR STYLES
15076 case 'SUB':
15077 case 'SUP':
15078 case 'ACRONYM':
15079 case 'BIG':
15080 case 'SMALL':
15081 case 'INS':
15082 case 'S':
15083 case 'STRIKE':
15084 case 'DEL':
15085 case 'STRONG':
15086 case 'CITE':
15087 case 'Q':
15088 case 'EM':
15089 case 'B':
15090 case 'I':
15091 case 'U':
15092 case 'SAMP':
15093 case 'CODE':
15094 case 'KBD':
15095 case 'TT':
15096 case 'VAR':
15097 case 'FONT':
15098 case 'MARK': // mPDF 5.5.09
15099 case 'TIME':
15100
15101 case 'SPAN':
15102 /*-- ANNOTATIONS --*/
15103 if ($this->title2annots && isset($attr['TITLE'])) {
15104 $objattr = array();
15105 $objattr['margin_top'] = 0;
15106 $objattr['margin_bottom'] = 0;
15107 $objattr['margin_left'] = 0;
15108 $objattr['margin_right'] = 0;
15109 $objattr['width'] = 0;
15110 $objattr['height'] = 0;
15111 $objattr['border_top']['w'] = 0;
15112 $objattr['border_bottom']['w'] = 0;
15113 $objattr['border_left']['w'] = 0;
15114 $objattr['border_right']['w'] = 0;
15115
15116 $objattr['CONTENT'] = $attr['TITLE'];
15117 $objattr['type'] = 'annot';
15118 $objattr['POS-X'] = 0;
15119 $objattr['POS-Y'] = 0;
15120 $objattr['ICON'] = 'Comment';
15121 $objattr['AUTHOR'] = '';
15122 $objattr['SUBJECT'] = '';
15123 $objattr['OPACITY'] = $this->annotOpacity;
15124 $objattr['COLOR'] = $this->ConvertColor('yellow');
15125 $annot = "\xbb\xa4\xactype=annot,objattr=".serialize($objattr)."\xbb\xa4\xac";
15126 }
15127 /*-- END ANNOTATIONS --*/
15128
15129 if ($tag == 'SPAN') {
15130 $this->spanlvl++;
15131 $this->InlineProperties['SPAN'][$this->spanlvl] = $this->saveInlineProperties();
15132 if (isset($annot)) { $this->InlineAnnots[$tag][$this->spanlvl] = $annot; } // *ANNOTATIONS*
15133 }
15134 else {
15135 if (!isset($this->InlineProperties[$tag])) $this->InlineProperties[$tag] = $this->saveInlineProperties(); // mPDF 5.4.13
15136 if (isset($annot)) { $this->InlineAnnots[$tag] = $annot; } // *ANNOTATIONS*
15137 }
15138 $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr);
15139 if (!empty($properties)) $this->setCSS($properties,'INLINE');
15140 break;
15141
15142
15143 case 'A':
15144 if (isset($attr['NAME']) and $attr['NAME'] != '') {
15145 $e = '';
15146 /*-- BOOKMARKS --*/
15147 if ($this->anchor2Bookmark) {
15148 $objattr = array();
15149 $objattr['CONTENT'] = htmlspecialchars_decode($attr['NAME'],ENT_QUOTES);
15150 $objattr['type'] = 'bookmark';
15151 if (isset($attr['LEVEL']) && $attr['LEVEL']) { $objattr['bklevel'] = $attr['LEVEL']; } else { $objattr['bklevel'] = 0; }
15152 $e = "\xbb\xa4\xactype=bookmark,objattr=".serialize($objattr)."\xbb\xa4\xac";
15153 }
15154 /*-- END BOOKMARKS --*/
15155 if($this->tableLevel) { // *TABLES*
15156 $this->_saveCellTextBuffer($e, '', $attr['NAME']); // *TABLES*
15157 } // *TABLES*
15158 else { // *TABLES*
15159 $this->_saveTextBuffer($e, '', $attr['NAME']); //an internal link (adds a space for recognition)
15160 } // *TABLES*
15161 }
15162 if (isset($attr['HREF'])) {
15163 $this->InlineProperties['A'] = $this->saveInlineProperties();
15164 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
15165 if (!empty($properties)) $this->setCSS($properties,'INLINE');
15166 $this->HREF=htmlspecialchars_decode(urldecode($attr['HREF']));
15167 }
15168 break;
15169
15170 case 'LEGEND': // mPDF 5.4.18
15171 $this->InlineProperties['LEGEND'] = $this->saveInlineProperties();
15172 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
15173 if (!empty($properties)) $this->setCSS($properties,'INLINE');
15174 break;
15175
15176
15177
15178 case 'PROGRESS': // mPDF 5.5.09
15179 case 'METER': // mPDF 5.5.09
15180 $this->inMeter = true; // mPDF 5.5.09
15181
15182 if (isset($attr['MAX']) && $attr['MAX']) { $max = $attr['MAX']; }
15183 else { $max = 1; }
15184 if (isset($attr['MIN']) && $attr['MIN'] && $tag=='METER') { $min = $attr['MIN']; }
15185 else { $min = 0; }
15186 if ($max < $min) { $max = $min; }
15187
15188 if (isset($attr['VALUE']) && ($attr['VALUE'] || $attr['VALUE']==='0')) {
15189 $value = $attr['VALUE'];
15190 if ($value < $min) { $value = $min; }
15191 else if ($value > $max) { $value = $max; }
15192 }
15193 else { $value = ''; }
15194
15195 if (isset($attr['LOW']) && $attr['LOW']) { $low = $attr['LOW']; }
15196 else { $low = $min; }
15197 if ($low < $min) { $low = $min; }
15198 else if ($low > $max) { $low = $max; }
15199 if (isset($attr['HIGH']) && $attr['HIGH']) { $high = $attr['HIGH']; }
15200 else { $high = $max; }
15201 if ($high < $low) { $high = $low; }
15202 else if ($high > $max) { $high = $max; }
15203 if (isset($attr['OPTIMUM']) && $attr['OPTIMUM']) { $optimum = $attr['OPTIMUM']; }
15204 else { $optimum = $min + (($max-$min)/2); }
15205 if ($optimum < $min) { $optimum = $min; }
15206 else if ($optimum > $max) { $optimum = $max; }
15207 if (isset($attr['TYPE']) && $attr['TYPE']) { $type = $attr['TYPE']; }
15208 else { $type = ''; }
15209 $objattr = array();
15210 $objattr['margin_top'] = 0;
15211 $objattr['margin_bottom'] = 0;
15212 $objattr['margin_left'] = 0;
15213 $objattr['margin_right'] = 0;
15214 $objattr['padding_top'] = 0;
15215 $objattr['padding_bottom'] = 0;
15216 $objattr['padding_left'] = 0;
15217 $objattr['padding_right'] = 0;
15218 $objattr['width'] = 0;
15219 $objattr['height'] = 0;
15220 $objattr['border_top']['w'] = 0;
15221 $objattr['border_bottom']['w'] = 0;
15222 $objattr['border_left']['w'] = 0;
15223 $objattr['border_right']['w'] = 0;
15224
15225 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
15226 if(isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY'])=='none') {
15227 return;
15228 }
15229 $objattr['visibility'] = 'visible';
15230 if (isset($properties['VISIBILITY'])) {
15231 $v = strtolower($properties['VISIBILITY']);
15232 if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible') {
15233 $objattr['visibility'] = $v;
15234 }
15235 }
15236
15237 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15238 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15239 if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15240 if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15241
15242 if (isset($properties['PADDING-TOP'])) { $objattr['padding_top']=$this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15243 if (isset($properties['PADDING-BOTTOM'])) { $objattr['padding_bottom'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15244 if (isset($properties['PADDING-LEFT'])) { $objattr['padding_left'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15245 if (isset($properties['PADDING-RIGHT'])) { $objattr['padding_right'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15246
15247 if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
15248 if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
15249 if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
15250 if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
15251
15252 if (isset($properties['VERTICAL-ALIGN'])) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
15253 $w = 0;
15254 $h = 0;
15255 if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15256 else if(isset($attr['WIDTH'])) $w = $this->ConvertSize($attr['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15257
15258 if(isset($properties['HEIGHT'])) $h = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15259 else if(isset($attr['HEIGHT'])) $h = $this->ConvertSize($attr['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15260
15261 if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { $objattr['opacity'] = $properties['OPACITY']; }
15262 if ($this->HREF) {
15263 if (strpos($this->HREF,".") === false && strpos($this->HREF,"@") !== 0) {
15264 $href = $this->HREF;
15265 while(array_key_exists($href,$this->internallink)) $href="#".$href;
15266 $this->internallink[$href] = $this->AddLink();
15267 $objattr['link'] = $this->internallink[$href];
15268 }
15269 else { $objattr['link'] = $this->HREF; }
15270 }
15271 $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
15272 $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
15273
15274 // Image file
15275 if (!class_exists('meter', false)) {
15276 include(_MPDF_PATH.'classes/meter.php');
15277 }
15278 $this->meter = new meter();
15279 $svg = $this->meter->makeSVG(strtolower($tag), $type, $value, $max, $min, $optimum, $low, $high);
15280 //Save to local file
15281 $srcpath= _MPDF_TEMP_PATH.'_tempSVG'.RAND(1,10000).'_'.strtolower($tag).'.svg';
15282 file_put_contents($srcpath, $svg);
15283 $orig_srcpath = $srcpath;
15284 $this->GetFullPath($srcpath);
15285
15286 $info=$this->_getImage($srcpath, true, true, $orig_srcpath);
15287 if(!$info) {
15288 $info = $this->_getImage($this->noImageFile);
15289 if ($info) {
15290 $srcpath = $this->noImageFile;
15291 $w = ($info['w'] * (25.4/$this->dpi));
15292 $h = ($info['h'] * (25.4/$this->dpi));
15293 }
15294 }
15295 if(!$info) break;
15296
15297 $objattr['file'] = $srcpath;
15298 //Default width and height calculation if needed
15299 if($w==0 and $h==0) {
15300 // SVG units are pixels
15301 $w = $this->FontSize/(10/_MPDFK) * abs($info['w'])/_MPDFK; // mPDF 5.5.21
15302 $h = $this->FontSize/(10/_MPDFK) * abs($info['h'])/_MPDFK;
15303 }
15304 // IF WIDTH OR HEIGHT SPECIFIED
15305 if($w==0) $w=abs($h*$info['w']/$info['h']);
15306 if($h==0) $h=abs($w*$info['h']/$info['w']);
15307
15308 // Resize to maximum dimensions of page
15309 $maxWidth = $this->blk[$this->blklvl]['inner_width'];
15310 $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 1) ;
15311 if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
15312 if ($w + $extrawidth > $maxWidth ) {
15313 $w = $maxWidth - $extrawidth;
15314 $h=abs($w*$info['h']/$info['w']);
15315 }
15316
15317 if ($h + $extraheight > $maxHeight ) {
15318 $h = $maxHeight - $extraheight;
15319 $w=abs($h*$info['w']/$info['h']);
15320 }
15321 $objattr['type'] = 'image';
15322 $objattr['itype'] = $info['type'];
15323
15324 $objattr['orig_h'] = $info['h'];
15325 $objattr['orig_w'] = $info['w'];
15326 $objattr['wmf_x'] = $info['x'];
15327 $objattr['wmf_y'] = $info['y'];
15328 $objattr['height'] = $h + $extraheight;
15329 $objattr['width'] = $w + $extrawidth;
15330 $objattr['image_height'] = $h;
15331 $objattr['image_width'] = $w;
15332 $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
15333 $properties = array();
15334 if ($this->tableLevel) {
15335 $this->_saveCellTextBuffer($e, $this->HREF);
15336 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
15337 }
15338 else {
15339 $this->_saveTextBuffer($e, $this->HREF);
15340 }
15341
15342 break;
15343
15344
15345 case 'BR':
15346 // Added mPDF 3.0 Float DIV - CLEAR
15347 if (isset($attr['STYLE'])) {
15348 $properties = $this->cssmgr->readInlineCSS($attr['STYLE']);
15349 if (isset($properties['CLEAR'])) { $this->ClearFloats(strtoupper($properties['CLEAR']),$this->blklvl); } // *CSS-FLOAT*
15350 }
15351
15352
15353 /*-- TABLES --*/
15354 if($this->tableLevel) {
15355
15356 if ($this->blockjustfinished || $this->listjustfinished) {
15357 $this->_saveCellTextBuffer("\n");
15358 }
15359
15360 $this->_saveCellTextBuffer("\n");
15361 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
15362 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
15363 }
15364 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
15365 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
15366 }
15367 $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
15368 }
15369 else {
15370 /*-- END TABLES --*/
15371 if (count($this->textbuffer)) {
15372 $this->textbuffer[count($this->textbuffer)-1][0] = preg_replace('/ $/','',$this->textbuffer[count($this->textbuffer)-1][0]);
15373 }
15374 $this->_saveTextBuffer("\n");
15375 } // *TABLES*
15376 $this->ignorefollowingspaces = true;
15377 $this->blockjustfinished=false;
15378 $this->listjustfinished=false;
15379
15380 $this->linebreakjustfinished=true;
15381 break;
15382
15383
15384 // *********** BLOCKS ********************
15385
15386
15387 case 'PRE':
15388 $this->ispre=true; // ADDED - Prevents left trim of textbuffer in printbuffer()
15389
15390 case 'DIV':
15391 case 'FORM':
15392 case 'CENTER':
15393
15394 case 'BLOCKQUOTE':
15395 case 'ADDRESS':
15396
15397 case 'CAPTION':
15398 case 'P':
15399 case 'H1':
15400 case 'H2':
15401 case 'H3':
15402 case 'H4':
15403 case 'H5':
15404 case 'H6':
15405 case 'DL':
15406 case 'DT':
15407 case 'DD':
15408 case 'FIELDSET':
15409 // mPDF 5.5.22
15410 case 'DETAILS':
15411 case 'SUMMARY':
15412 // mPDF 5.5.09
15413 case 'ARTICLE':
15414 case 'ASIDE':
15415 case 'FIGURE':
15416 case 'FIGCAPTION':
15417 case 'FOOTER':
15418 case 'HEADER':
15419 case 'HGROUP':
15420 case 'NAV':
15421 case 'SECTION':
15422 $p = $this->cssmgr->PreviewBlockCSS($tag,$attr);
15423 if(isset($p['DISPLAY']) && strtolower($p['DISPLAY'])=='none') {
15424 $this->blklvl++;
15425 $this->blk[$this->blklvl]['hide'] = true;
15426 return;
15427 }
15428 if($tag == 'CAPTION') {
15429 // position is written in AdjstHTML
15430 if (isset($attr['POSITION']) && strtolower($attr['POSITION'])=='bottom') { $divpos = 'B'; }
15431 else { $divpos = 'T'; }
15432 if (isset($attr['ALIGN']) && strtolower($attr['ALIGN'])=='bottom') { $cappos = 'B'; }
15433 else if (isset($p['CAPTION-SIDE']) && strtolower($p['CAPTION-SIDE'])=='bottom') { $cappos = 'B'; }
15434 else { $cappos = 'T'; }
15435 if (isset($attr['ALIGN'])) { unset($attr['ALIGN']); }
15436 if ($cappos != $divpos) {
15437 $this->blklvl++;
15438 $this->blk[$this->blklvl]['hide'] = true;
15439 return;
15440 }
15441 }
15442
15443 /*-- FORMS --*/
15444 if($tag == 'FORM') {
15445 if (isset($attr['METHOD']) && strtolower($attr['METHOD'])=='get') { $this->form->formMethod = 'GET'; }
15446 else { $this->form->formMethod = 'POST'; }
15447 if (isset($attr['ACTION'])) { $this->form->formAction = $attr['ACTION']; }
15448 else { $this->form->formAction = ''; }
15449 }
15450 /*-- END FORMS --*/
15451
15452
15453 /*-- CSS-POSITION --*/
15454 if ((isset($p['POSITION']) && (strtolower($p['POSITION'])=='fixed' || strtolower($p['POSITION'])=='absolute')) && $this->blklvl==0) {
15455 if ($this->inFixedPosBlock) {
15456 $this->Error("Cannot nest block with position:fixed or position:absolute");
15457 }
15458 $this->inFixedPosBlock = true;
15459 return;
15460 }
15461 /*-- END CSS-POSITION --*/
15462 // Start Block
15463 $this->ignorefollowingspaces = true;
15464
15465 if ($this->blockjustfinished && !count($this->textbuffer) && $this->y != $this->tMargin && $this->collapseBlockMargins) { $lastbottommargin = $this->lastblockbottommargin; }
15466 else { $lastbottommargin = 0; }
15467 $this->lastblockbottommargin = 0;
15468 $this->blockjustfinished=false;
15469
15470 /*-- LISTS --*/
15471 if ($this->listlvl>0) { return; }
15472 /*-- END LISTS --*/
15473
15474 $this->InlineProperties = array();
15475 $this->spanlvl = 0;
15476 $this->listjustfinished=false;
15477 $this->divbegin=true;
15478
15479 $this->linebreakjustfinished=false;
15480
15481 /*-- TABLES --*/
15482 if ($this->tableLevel) {
15483
15484 // If already something on the line
15485 if ($this->cell[$this->row][$this->col]['s'] > 0 && !$this->nestedtablejustfinished ) {
15486 $this->_saveCellTextBuffer("\n");
15487 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
15488 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
15489 }
15490 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
15491 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
15492 }
15493 $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
15494 }
15495 // Cannot set block properties inside table - use Bold to indicate h1-h6
15496 if ($tag == 'CENTER' && $this->tdbegin) { $this->cell[$this->row][$this->col]['a'] = $align['center']; }
15497
15498 $this->InlineProperties['BLOCKINTABLE'] = $this->saveInlineProperties();
15499 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
15500 if (!empty($properties)) $this->setCSS($properties,'INLINE');
15501
15502
15503 break;
15504 }
15505 /*-- END TABLES --*/
15506
15507 if ($tag == 'P' || $tag == 'DT' || $tag == 'DD') { $this->lastoptionaltag = $tag; } // Save current HTML specified optional endtag
15508 else { $this->lastoptionaltag = ''; }
15509
15510 if ($this->lastblocklevelchange == 1) { $blockstate = 1; } // Top margins/padding only
15511 else if ($this->lastblocklevelchange < 1) { $blockstate = 0; } // NO margins/padding
15512 $this->printbuffer($this->textbuffer,$blockstate);
15513 $this->textbuffer=array();
15514
15515 $save_blklvl = $this->blklvl;
15516 $save_blk = $this->blk;
15517 $save_silp = $this->saveInlineProperties();
15518 $save_spanlvl = $this->spanlvl;
15519 $save_ilp = $this->InlineProperties;
15520
15521 $this->blklvl++;
15522
15523 $currblk =& $this->blk[$this->blklvl];
15524 $this->initialiseBlock($currblk);
15525 $prevblk =& $this->blk[$this->blklvl-1];
15526
15527 $currblk['tag'] = $tag;
15528 $currblk['attr'] = $attr;
15529
15530 $this->Reset();
15531 $properties = $this->cssmgr->MergeCSS('BLOCK',$tag,$attr);
15532 $pagesel = '';
15533 /*-- CSS-PAGE --*/
15534
15535 if (isset($properties['PAGE'])) { $pagesel = $properties['PAGE']; }
15536 /*-- END CSS-PAGE --*/
15537
15538 // If page-box has changed AND/OR PAGE-BREAK-BEFORE
15539 $save_cols = false;
15540 if (($pagesel && $pagesel != $this->page_box['current']) || (isset($properties['PAGE-BREAK-BEFORE']) && $properties['PAGE-BREAK-BEFORE'])) {
15541 if ($this->blklvl>1) {
15542 // Close any open block tags
15543 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
15544 // Output any text left in buffer
15545 if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); $this->textbuffer=array(); }
15546 }
15547 /*-- COLUMNS --*/
15548 if ($this->ColActive) {
15549 $save_cols = true;
15550 $save_nbcol = $this->NbCol; // other values of gap and vAlign will not change by setting Columns off
15551 $this->SetColumns(0);
15552 }
15553 /*-- END COLUMNS --*/
15554
15555
15556 // Must Add new page if changed page properties
15557 if (isset($properties['PAGE-BREAK-BEFORE'])) {
15558 if (strtoupper($properties['PAGE-BREAK-BEFORE']) == 'RIGHT') { $this->AddPage($this->CurOrientation,'NEXT-ODD','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
15559 else if (strtoupper($properties['PAGE-BREAK-BEFORE']) == 'LEFT') { $this->AddPage($this->CurOrientation,'NEXT-EVEN','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
15560 else if (strtoupper($properties['PAGE-BREAK-BEFORE']) == 'ALWAYS') { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
15561 else if ($this->page_box['current'] != $pagesel) { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); } // *CSS-PAGE*
15562 }
15563 /*-- CSS-PAGE --*/
15564 else if ($pagesel != $this->page_box['current']) { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
15565 /*-- END CSS-PAGE --*/
15566
15567 // if using htmlheaders, the headers need to be rewritten when new page
15568 // done by calling WriteHTML() within resethtmlheaders
15569 // so block is reset to 0 - now we need to resurrect it
15570 // As in WriteHTML() initialising
15571 if (!($this->restoreBlockPagebreaks && isset($properties['PAGE-BREAK-BEFORE']) && $properties['PAGE-BREAK-BEFORE'])) {
15572 $this->blklvl = 0;
15573 $this->lastblocklevelchange = 0;
15574 $this->blk = array();
15575 $this->initialiseBlock($this->blk[0]);
15576 $this->blk[0]['width'] =& $this->pgwidth;
15577 $this->blk[0]['inner_width'] =& $this->pgwidth;
15578 $this->blk[0]['blockContext'] = $this->blockContext;
15579 $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
15580 $this->setCSS($properties,'','BODY');
15581 $this->blklvl++;
15582 $currblk =& $this->blk[$this->blklvl];
15583 $prevblk =& $this->blk[$this->blklvl-1];
15584
15585 $this->initialiseBlock($currblk);
15586 $currblk['tag'] = $tag;
15587 $currblk['attr'] = $attr;
15588
15589 $this->Reset();
15590 $properties = $this->cssmgr->MergeCSS('BLOCK',$tag,$attr);
15591 }
15592 /*-- COLUMNS --*/
15593 if ($save_cols) {
15594 // Restore columns
15595 $this->SetColumns($save_nbcol,$this->colvAlign,$this->ColGap);
15596 }
15597 /*-- END COLUMNS --*/
15598 if ($this->restoreBlockPagebreaks && isset($properties['PAGE-BREAK-BEFORE']) && $properties['PAGE-BREAK-BEFORE']) {
15599 $this->blk = $save_blk;
15600 // Re-open block tags
15601 $t = $this->blk[0]['tag'];
15602 $a = $this->blk[0]['attr'];
15603 $this->blklvl = 0;
15604 for ($b=0; $b<=$save_blklvl;$b++) {
15605 $tc = $t;
15606 $ac = $a;
15607 $t = $this->blk[$b+1]['tag'];
15608 $a = $this->blk[$b+1]['attr'];
15609 unset($this->blk[$b+1]);
15610 $this->OpenTag($tc,$ac);
15611 }
15612 $this->spanlvl = $save_spanlvl;
15613 $this->InlineProperties = $save_ilp;
15614 $this->restoreInlineProperties($save_silp);
15615 }
15616 }
15617
15618 if (isset($properties['PAGE-BREAK-INSIDE']) && strtoupper($properties['PAGE-BREAK-INSIDE']) == 'AVOID' && !$this->ColActive && !$this->keep_block_together) {
15619 $currblk['keep_block_together'] = 1;
15620 $this->kt_y00 = $this->y;
15621 $this->kt_p00 = $this->page;
15622 $this->keep_block_together = 1;
15623 $this->divbuffer = array();
15624 $this->ktLinks = array();
15625 $this->ktAnnots = array();
15626 $this->ktForms = array();
15627 $this->ktBlock = array();
15628 $this->ktReference = array();
15629 $this->ktBMoutlines = array();
15630 $this->_kttoc = array();
15631 }
15632 if ($lastbottommargin && isset($properties['MARGIN-TOP']) && $properties['MARGIN-TOP'] && empty($properties['FLOAT'])) { $currblk['lastbottommargin'] = $lastbottommargin; }
15633
15634 // mPDF 5.6.01 - LAYERS
15635 if (isset($properties['Z-INDEX']) && $this->currentlayer==0) {
15636 $v = intval($properties['Z-INDEX']);
15637 if ($v > 0) {
15638 $currblk['z-index'] = $v;
15639 $this->BeginLayer($v);
15640 }
15641 }
15642
15643 $this->setCSS($properties,'BLOCK',$tag); //name(id/class/style) found in the CSS array!
15644 $currblk['InlineProperties'] = $this->saveInlineProperties();
15645
15646 if (isset($properties['VISIBILITY'])) {
15647 $v = strtolower($properties['VISIBILITY']);
15648 if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible' && !$this->tableLevel) {
15649 $currblk['visibility'] = $v;
15650 $this->SetVisibility($v);
15651 }
15652 }
15653
15654 if(isset($attr['DIR']) && $attr['DIR']) { $currblk['direction'] = strtolower($attr['DIR']); }
15655 if(isset($attr['ALIGN']) && $attr['ALIGN']) { $currblk['block-align'] = $align[strtolower($attr['ALIGN'])]; }
15656
15657 if (isset($properties['HEIGHT'])) {
15658 $currblk['css_set_height'] = $this->ConvertSize($properties['HEIGHT'],($this->h - $this->tMargin - $this->bMargin),$this->FontSize,false);
15659 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); }
15660 }
15661 else { $currblk['css_set_height'] = false; }
15662
15663
15664 // Added mPDF 3.0 Float DIV
15665 if (isset($prevblk['blockContext'])) { $currblk['blockContext'] = $prevblk['blockContext'] ; } // *CSS-FLOAT*
15666
15667 if (isset($properties['CLEAR'])) { $this->ClearFloats(strtoupper($properties['CLEAR']), $this->blklvl-1); } // *CSS-FLOAT*
15668
15669 $container_w = $prevblk['inner_width'];
15670 $bdr = $currblk['border_right']['w'];
15671 $bdl = $currblk['border_left']['w'];
15672 $pdr = $currblk['padding_right'];
15673 $pdl = $currblk['padding_left'];
15674
15675 if (isset($currblk['css_set_width'])) { $setwidth = $currblk['css_set_width']; }
15676 else { $setwidth = 0; }
15677
15678 /*-- CSS-FLOAT --*/
15679 if (isset($properties['FLOAT']) && strtoupper($properties['FLOAT']) == 'RIGHT' && !$this->ColActive) {
15680 // Cancel Keep-Block-together
15681 $currblk['keep_block_together'] = false;
15682 $this->kt_y00 = '';
15683 $this->keep_block_together = 0;
15684
15685 $this->blockContext++;
15686 $currblk['blockContext'] = $this->blockContext;
15687
15688 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
15689
15690 // DIV is too narrow for text to fit!
15691 $maxw = $container_w - $l_width - $r_width;
15692 if (($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) > $maxw || ($maxw - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) < (2*$this->GetCharWidth('W',false))) {
15693 // Too narrow to fit - try to move down past L or R float
15694 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))) {
15695 $this->ClearFloats('LEFT', $this->blklvl-1);
15696 }
15697 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))) {
15698 $this->ClearFloats('RIGHT', $this->blklvl-1);
15699 }
15700 else { $this->ClearFloats('BOTH', $this->blklvl-1); }
15701 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
15702 }
15703
15704 if ($r_exists) { $currblk['margin_right'] += $r_width; }
15705
15706 $currblk['float'] = 'R';
15707 $currblk['float_start_y'] = $this->y;
15708 if ($currblk['css_set_width']) {
15709 $currblk['margin_left'] = $container_w - ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
15710 $currblk['float_width'] = ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
15711 }
15712 else {
15713 // *** If no width set - would need to buffer and keep track of max width, then Right-align if not full width
15714 // and do borders and backgrounds - For now - just set to maximum width left
15715
15716 if ($l_exists) { $currblk['margin_left'] += $l_width; }
15717 $currblk['css_set_width'] = $container_w - ($currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr);
15718
15719 $currblk['float_width'] = ($currblk['css_set_width'] + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
15720 }
15721 }
15722 else if (isset($properties['FLOAT']) && strtoupper($properties['FLOAT']) == 'LEFT' && !$this->ColActive) {
15723 // Cancel Keep-Block-together
15724 $currblk['keep_block_together'] = false;
15725 $this->kt_y00 = '';
15726 $this->keep_block_together = 0;
15727
15728 $this->blockContext++;
15729 $currblk['blockContext'] = $this->blockContext;
15730
15731 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
15732
15733 // DIV is too narrow for text to fit!
15734 $maxw = $container_w - $l_width - $r_width;
15735 if (($setwidth + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr) > $maxw || ($maxw - ($currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) < (2*$this->GetCharWidth('W',false))) {
15736 // Too narrow to fit - try to move down past L or R float
15737 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))) {
15738 $this->ClearFloats('LEFT', $this->blklvl-1);
15739 }
15740 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))) {
15741 $this->ClearFloats('RIGHT', $this->blklvl-1);
15742 }
15743 else { $this->ClearFloats('BOTH', $this->blklvl-1); }
15744 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
15745 }
15746
15747 if ($l_exists) { $currblk['margin_left'] += $l_width; }
15748
15749 $currblk['float'] = 'L';
15750 $currblk['float_start_y'] = $this->y;
15751 if ($setwidth) {
15752 $currblk['margin_right'] = $container_w - ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
15753 $currblk['float_width'] = ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
15754 }
15755 else {
15756 // *** If no width set - would need to buffer and keep track of max width, then Right-align if not full width
15757 // and do borders and backgrounds - For now - just set to maximum width left
15758
15759 if ($r_exists) { $currblk['margin_right'] += $r_width; }
15760 $currblk['css_set_width'] = $container_w - ($currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr);
15761
15762 $currblk['float_width'] = ($currblk['css_set_width'] + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
15763 }
15764 }
15765
15766 else {
15767 // Don't allow overlap - if floats present - adjust padding to avoid overlap with Floats
15768 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
15769 $maxw = $container_w - $l_width - $r_width;
15770 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))) {
15771 // Too narrow to fit - try to move down past L or R float
15772 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))) {
15773 $this->ClearFloats('LEFT', $this->blklvl-1);
15774 }
15775 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))) {
15776 $this->ClearFloats('RIGHT', $this->blklvl-1);
15777 }
15778 else { $this->ClearFloats('BOTH', $this->blklvl-1); }
15779 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl-1);
15780 }
15781 if ($r_exists) { $currblk['padding_right'] = max(($r_width-$currblk['margin_right']-$bdr), $pdr); }
15782 if ($l_exists) { $currblk['padding_left'] = max(($l_width-$currblk['margin_left']-$bdl), $pdl); }
15783 }
15784 /*-- END CSS-FLOAT --*/
15785
15786
15787 /*-- BORDER-RADIUS --*/
15788 // Automatically increase padding if required for border-radius
15789 if ($this->autoPadding && !$this->ColActive && !$this->keep_block_together) {
15790 if ($currblk['border_radius_TL_H']>$currblk['padding_left'] && $currblk['border_radius_TL_V']>$currblk['padding_top']) {
15791 if ($currblk['border_radius_TL_H']>$currblk['border_radius_TL_V']) {
15792 $this->_borderPadding($currblk['border_radius_TL_H'],$currblk['border_radius_TL_V'], $currblk['padding_left'], $currblk['padding_top']);
15793 }
15794 else {
15795 $this->_borderPadding($currblk['border_radius_TL_V'],$currblk['border_radius_TL_H'], $currblk['padding_top'], $currblk['padding_left']);
15796 }
15797 }
15798 if ($currblk['border_radius_TR_H']>$currblk['padding_right'] && $currblk['border_radius_TR_V']>$currblk['padding_top']) {
15799 if ($currblk['border_radius_TR_H']>$currblk['border_radius_TR_V']) {
15800 $this->_borderPadding($currblk['border_radius_TR_H'],$currblk['border_radius_TR_V'], $currblk['padding_right'], $currblk['padding_top']);
15801 }
15802 else {
15803 $this->_borderPadding($currblk['border_radius_TR_V'],$currblk['border_radius_TR_H'], $currblk['padding_top'], $currblk['padding_right']);
15804 }
15805 }
15806 if ($currblk['border_radius_BL_H']>$currblk['padding_left'] && $currblk['border_radius_BL_V']>$currblk['padding_bottom']) {
15807 if ($currblk['border_radius_BL_H']>$currblk['border_radius_BL_V']) {
15808 $this->_borderPadding($currblk['border_radius_BL_H'],$currblk['border_radius_BL_V'], $currblk['padding_left'], $currblk['padding_bottom']);
15809 }
15810 else {
15811 $this->_borderPadding($currblk['border_radius_BL_V'],$currblk['border_radius_BL_H'], $currblk['padding_bottom'], $currblk['padding_left']);
15812 }
15813 }
15814 if ($currblk['border_radius_BR_H']>$currblk['padding_right'] && $currblk['border_radius_BR_V']>$currblk['padding_bottom']) {
15815 if ($currblk['border_radius_BR_H']>$currblk['border_radius_BR_V']) {
15816 $this->_borderPadding($currblk['border_radius_BR_H'],$currblk['border_radius_BR_V'], $currblk['padding_right'], $currblk['padding_bottom']);
15817 }
15818 else {
15819 $this->_borderPadding($currblk['border_radius_BR_V'],$currblk['border_radius_BR_H'], $currblk['padding_bottom'], $currblk['padding_right']);
15820 }
15821 }
15822 }
15823 /*-- END BORDER-RADIUS --*/
15824
15825
15826 // Hanging indent - if negative indent: ensure padding is >= indent
15827 if(!isset($currblk['text_indent'])) { $currblk['text_indent'] = null; }
15828 if(!isset($currblk['inner_width'])) { $currblk['inner_width'] = null; }
15829 $cbti = $this->ConvertSize($currblk['text_indent'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
15830 if ($cbti < 0) {
15831 $hangind = -($cbti);
15832 if ($currblk['direction'] == 'rtl') { // *RTL*
15833 $currblk['padding_right'] = max($currblk['padding_right'],$hangind); // *RTL*
15834 } // *RTL*
15835 else { // *RTL*
15836 $currblk['padding_left'] = max($currblk['padding_left'],$hangind);
15837 } // *RTL*
15838 }
15839
15840 if (isset($currblk['css_set_width'])) {
15841 if (isset($properties['MARGIN-LEFT']) && isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-LEFT'])=='auto' && strtolower($properties['MARGIN-RIGHT'])=='auto') {
15842 // Try to reduce margins to accomodate - if still too wide, set margin-right/left=0 (reduces width)
15843 $anyextra = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']);
15844 if ($anyextra>0) {
15845 $currblk['margin_left'] = $currblk['margin_right'] = $anyextra /2;
15846 }
15847 else {
15848 $currblk['margin_left'] = $currblk['margin_right'] = 0;
15849 }
15850 }
15851 else if (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
15852 // Try to reduce margin-left to accomodate - if still too wide, set margin-left=0 (reduces width)
15853 $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']);
15854 if ($currblk['margin_left'] < 0) {
15855 $currblk['margin_left'] = 0;
15856 }
15857 }
15858 else if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto') {
15859 // Try to reduce margin-right to accomodate - if still too wide, set margin-right=0 (reduces width)
15860 $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']);
15861 if ($currblk['margin_right'] < 0) {
15862 $currblk['margin_right'] = 0;
15863 }
15864 }
15865 else {
15866 if ($currblk['direction'] == 'rtl') { // *RTL*
15867 // Try to reduce margin-left to accomodate - if still too wide, set margin-left=0 (reduces width)
15868 $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']); // *RTL*
15869 if ($currblk['margin_left'] < 0) { // *RTL*
15870 $currblk['margin_left'] = 0; // *RTL*
15871 } // *RTL*
15872 } // *RTL*
15873 else { // *RTL*
15874 // Try to reduce margin-right to accomodate - if still too wide, set margin-right=0 (reduces width)
15875 $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']);
15876 if ($currblk['margin_right'] < 0) {
15877 $currblk['margin_right'] = 0;
15878 }
15879 } // *RTL*
15880 }
15881 }
15882
15883 $currblk['outer_left_margin'] = $prevblk['outer_left_margin'] + $currblk['margin_left'] + $prevblk['border_left']['w'] + $prevblk['padding_left'];
15884 $currblk['outer_right_margin'] = $prevblk['outer_right_margin'] + $currblk['margin_right'] + $prevblk['border_right']['w'] + $prevblk['padding_right'];
15885
15886 $currblk['width'] = $this->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin']);
15887 $currblk['inner_width'] = $currblk['width'] - ($currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']);
15888
15889 // Check DIV is not now too narrow to fit text
15890 $mw = 2*$this->GetCharWidth('W',false);
15891 if ($currblk['inner_width'] < $mw) {
15892 $currblk['padding_left'] = 0;
15893 $currblk['padding_right'] = 0;
15894 $currblk['border_left']['w'] = 0.2;
15895 $currblk['border_right']['w'] = 0.2;
15896 $currblk['margin_left'] = 0;
15897 $currblk['margin_right'] = 0;
15898 $currblk['outer_left_margin'] = $prevblk['outer_left_margin'] + $currblk['margin_left'] + $prevblk['border_left']['w'] + $prevblk['padding_left'];
15899 $currblk['outer_right_margin'] = $prevblk['outer_right_margin'] + $currblk['margin_right'] + $prevblk['border_right']['w'] + $prevblk['padding_right'];
15900 $currblk['width'] = $this->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin']);
15901 $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']);
15902 // if ($currblk['inner_width'] < $mw) { $this->Error("DIV is too narrow for text to fit!"); }
15903 }
15904
15905 $this->x = $this->lMargin + $currblk['outer_left_margin'];
15906
15907 /*-- BACKGROUNDS --*/
15908 if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->kwt && !$this->ColActive && !$this->keep_block_together) {
15909 $ret = $this->SetBackground($properties, $currblk['inner_width']);
15910 if ($ret) { $currblk['background-image'] = $ret; }
15911 }
15912 /*-- END BACKGROUNDS --*/
15913
15914 /*-- TABLES --*/
15915 if ($this->use_kwt && isset($attr['KEEP-WITH-TABLE']) && !$this->ColActive && !$this->keep_block_together) {
15916 $this->kwt = true;
15917 $this->kwt_y0 = $this->y;
15918 $this->kwt_x0 = $this->x;
15919 $this->kwt_height = 0;
15920 $this->kwt_buffer = array();
15921 $this->kwt_Links = array();
15922 $this->kwt_Annots = array();
15923 $this->kwt_moved = false;
15924 $this->kwt_saved = false;
15925 $this->kwt_Reference = array();
15926 $this->kwt_BMoutlines = array();
15927 $this->kwt_toc = array();
15928 }
15929 else {
15930 /*-- END TABLES --*/
15931 $this->kwt = false;
15932 } // *TABLES*
15933
15934 //Save x,y coords in case we need to print borders...
15935 $currblk['y0'] = $this->y;
15936 $currblk['x0'] = $this->x;
15937 $currblk['startpage'] = $this->page;
15938 $this->oldy = $this->y;
15939
15940 $this->lastblocklevelchange = 1 ;
15941
15942 break;
15943
15944 case 'HR':
15945 // Added mPDF 3.0 Float DIV - CLEAR
15946 if (isset($attr['STYLE'])) {
15947 $properties = $this->cssmgr->readInlineCSS($attr['STYLE']);
15948 if (isset($properties['CLEAR'])) { $this->ClearFloats(strtoupper($properties['CLEAR']),$this->blklvl); } // *CSS-FLOAT*
15949 }
15950
15951 $this->ignorefollowingspaces = true;
15952
15953 $objattr = array();
15954 $objattr['margin_top'] = 0;
15955 $objattr['margin_bottom'] = 0;
15956 $objattr['margin_left'] = 0;
15957 $objattr['margin_right'] = 0;
15958 $objattr['width'] = 0;
15959 $objattr['height'] = 0;
15960 $objattr['border_top']['w'] = 0;
15961 $objattr['border_bottom']['w'] = 0;
15962 $objattr['border_left']['w'] = 0;
15963 $objattr['border_right']['w'] = 0;
15964 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
15965 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top'] = $this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15966 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15967 if (isset($properties['WIDTH'])) { $objattr['width'] = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width']); }
15968 else if(isset($attr['WIDTH']) && $attr['WIDTH'] != '') $objattr['width'] = $this->ConvertSize($attr['WIDTH'],$this->blk[$this->blklvl]['inner_width']);
15969 if (isset($properties['TEXT-ALIGN'])) { $objattr['align'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
15970 else if(isset($attr['ALIGN']) && $attr['ALIGN'] != '') $objattr['align'] = $align[strtolower($attr['ALIGN'])];
15971
15972 if (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
15973 $objattr['align'] = 'R';
15974 }
15975 if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto') {
15976 $objattr['align'] = 'L';
15977 if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto' && isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
15978 $objattr['align'] = 'C';
15979 }
15980 }
15981 if (isset($properties['COLOR'])) { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
15982 else if(isset($attr['COLOR']) && $attr['COLOR'] != '') $objattr['color'] = $this->ConvertColor($attr['COLOR']);
15983 if (isset($properties['HEIGHT'])) { $objattr['linewidth'] = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
15984
15985
15986 /*-- TABLES --*/
15987 if ($this->tableLevel) {
15988 $objattr['W-PERCENT'] = 100;
15989 if (isset($properties['WIDTH']) && stristr($properties['WIDTH'],'%')) {
15990 $properties['WIDTH'] += 0; //make "90%" become simply "90"
15991 $objattr['W-PERCENT'] = $properties['WIDTH'];
15992 }
15993 if (isset($attr['WIDTH']) && stristr($attr['WIDTH'],'%')) {
15994 $attr['WIDTH'] += 0; //make "90%" become simply "90"
15995 $objattr['W-PERCENT'] = $attr['WIDTH'];
15996 }
15997 }
15998 /*-- END TABLES --*/
15999
16000 $objattr['type'] = 'hr';
16001 $objattr['height'] = $objattr['linewidth'] + $objattr['margin_top'] + $objattr['margin_bottom'];
16002 $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
16003
16004 // Clear properties - tidy up
16005 $properties = array();
16006
16007 /*-- TABLES --*/
16008 // Output it to buffers
16009 if ($this->tableLevel) {
16010 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
16011 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
16012 }
16013 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
16014 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
16015 }
16016 $this->cell[$this->row][$this->col]['s'] = 0 ;// reset
16017 $this->_saveCellTextBuffer($e, $this->HREF);
16018 }
16019 else {
16020 /*-- END TABLES --*/
16021 $this->_saveTextBuffer($e, $this->HREF);
16022 } // *TABLES*
16023
16024 break;
16025
16026
16027 /*-- BARCODES --*/
16028
16029 case 'BARCODE':
16030 if(isset($attr['CODE']) && $attr['CODE']) {
16031 $objattr = array();
16032 $objattr['margin_top'] = 0;
16033 $objattr['margin_bottom'] = 0;
16034 $objattr['margin_left'] = 0;
16035 $objattr['margin_right'] = 0;
16036 $objattr['padding_top'] = 0;
16037 $objattr['padding_bottom'] = 0;
16038 $objattr['padding_left'] = 0;
16039 $objattr['padding_right'] = 0;
16040 $objattr['width'] = 0;
16041 $objattr['height'] = 0;
16042 $objattr['border_top']['w'] = 0;
16043 $objattr['border_bottom']['w'] = 0;
16044 $objattr['border_left']['w'] = 0;
16045 $objattr['border_right']['w'] = 0;
16046 $objattr['code'] = $attr['CODE'];
16047
16048 if(isset($attr['TYPE'])) {
16049 $objattr['btype'] = trim(strtoupper($attr['TYPE']));
16050 }
16051 else { $objattr['btype'] = 'EAN13'; } // default
16052 if (preg_match('/^(EAN13|ISBN|ISSN|EAN8|UPCA|UPCE)P([25])$/',$objattr['btype'],$m)) {
16053 $objattr['btype'] = $m[1];
16054 $objattr['bsupp'] = $m[2];
16055 if (preg_match('/^(\S+)\s+(.*)$/',$objattr['code'],$mm)) {
16056 $objattr['code'] = $mm[1];
16057 $objattr['bsupp_code'] = $mm[2];
16058 }
16059 }
16060 else { $objattr['bsupp'] = 0; }
16061
16062 if(isset($attr['TEXT']) && $attr['TEXT']==1) { $objattr['showtext'] = 1; }
16063 else { $objattr['showtext'] = 0; }
16064 if(isset($attr['SIZE']) && $attr['SIZE']>0) { $objattr['bsize'] = $attr['SIZE']; }
16065 else { $objattr['bsize'] = 1; }
16066 if(isset($attr['HEIGHT']) && $attr['HEIGHT']>0) { $objattr['bheight'] = $attr['HEIGHT']; }
16067 else { $objattr['bheight'] = 1; }
16068 if(isset($attr['PR']) && $attr['PR']>0) { $objattr['pr_ratio'] = $attr['PR']; }
16069 else { $objattr['pr_ratio'] = ''; }
16070 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
16071 if(isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY'])=='none') {
16072 return;
16073 }
16074 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16075 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16076 if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16077 if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16078
16079 if (isset($properties['PADDING-TOP'])) { $objattr['padding_top']=$this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16080 if (isset($properties['PADDING-BOTTOM'])) { $objattr['padding_bottom'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16081 if (isset($properties['PADDING-LEFT'])) { $objattr['padding_left'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16082 if (isset($properties['PADDING-RIGHT'])) { $objattr['padding_right'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16083
16084 if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
16085 if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
16086 if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
16087 if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
16088
16089 if (isset($properties['VERTICAL-ALIGN'])) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
16090 if (isset($properties['COLOR']) && $properties['COLOR'] != '') { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
16091 else { $objattr['color'] = false; }
16092 if (isset($properties['BACKGROUND-COLOR']) && $properties['BACKGROUND-COLOR'] != '') { $objattr['bgcolor'] = $this->ConvertColor($properties['BACKGROUND-COLOR']); }
16093 else { $objattr['bgcolor'] = false; }
16094
16095 if (!class_exists('PDFBarcode', false)) {
16096 include(_MPDF_PATH.'classes/barcode.php');
16097 }
16098 $this->barcode = new PDFBarcode();
16099
16100 if ($objattr['btype'] == 'EAN13' || $objattr['btype'] == 'ISBN' || $objattr['btype'] == 'ISSN' || $objattr['btype'] == 'UPCA' || $objattr['btype'] == 'UPCE' || $objattr['btype'] == 'EAN8') {
16101 $code = preg_replace('/\-/','',$objattr['code']);
16102 if ($objattr['btype'] == 'ISSN' || $objattr['btype'] == 'ISBN') {
16103 $arrcode = $this->barcode->getBarcodeArray($code, 'EAN13');
16104 }
16105 else { $arrcode = $this->barcode->getBarcodeArray($code, $objattr['btype'] ); }
16106 if ($arrcode === false) { $this->Error('Error in barcode string.'); }
16107
16108 if ($objattr['bsupp'] == 2 || $objattr['bsupp'] == 5) { // EAN-2 or -5 Supplement
16109 $supparrcode = $this->barcode->getBarcodeArray($objattr['bsupp_code'], 'EAN'.$objattr['bsupp'] );
16110 $w = ($arrcode["maxw"] + $arrcode['lightmL'] + $arrcode['lightmR'] + $supparrcode["maxw"] + $supparrcode['sepM']) * $arrcode['nom-X'] * $objattr['bsize'];
16111 }
16112 else {
16113 $w = ($arrcode["maxw"] + $arrcode['lightmL'] + $arrcode['lightmR']) * $arrcode['nom-X'] * $objattr['bsize'];
16114 }
16115 $h = $arrcode['nom-H'] * $objattr['bsize'] * $objattr['bheight'];
16116 // Add height for ISBN string + margin from top of bars
16117 if (($objattr['showtext'] && $objattr['btype'] == 'EAN13') || $objattr['btype'] == 'ISBN' || $objattr['btype'] == 'ISSN') {
16118 $tisbnm = 1.5 * $objattr['bsize']; // Top margin between TOP TEXT (isbn - if shown) & bars
16119 $isbn_fontsize = 2.1 * $objattr['bsize'];
16120 $h += $isbn_fontsize + $tisbnm ;
16121 }
16122 }
16123 // QR-code
16124 else if ($objattr['btype'] == 'QR') {
16125 $w = $h = $objattr['bsize']*25; // Factor of 25mm (default)
16126 $objattr['errorlevel'] = 'L';
16127 if (isset($attr['ERROR'])) { $objattr['errorlevel'] = $attr['ERROR']; }
16128 }
16129 else if ($objattr['btype'] == 'IMB' || $objattr['btype'] == 'RM4SCC' || $objattr['btype'] == 'KIX' || $objattr['btype'] == 'POSTNET' || $objattr['btype'] == 'PLANET') {
16130 $arrcode = $this->barcode->getBarcodeArray($objattr['code'], $objattr['btype'] );
16131 if ($arrcode === false) { $this->Error('Error in barcode string.'); }
16132 $w = ($arrcode["maxw"] * $arrcode['nom-X'] * $objattr['bsize']) + $arrcode['quietL'] + $arrcode['quietR'];
16133 $h = ($arrcode['nom-H'] * $objattr['bsize']) + (2*$arrcode['quietTB']);
16134 }
16135 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'))) {
16136 $arrcode = $this->barcode->getBarcodeArray($objattr['code'], $objattr['btype'], $objattr['pr_ratio'] );
16137 if ($arrcode === false) { $this->Error('Error in barcode string.'); }
16138 $w = ($arrcode["maxw"] + $arrcode['lightmL'] + $arrcode['lightmR']) * $arrcode['nom-X'] * $objattr['bsize'];
16139 $h = ((2*$arrcode['lightTB'] * $arrcode['nom-X']) + $arrcode['nom-H']) * $objattr['bsize'] * $objattr['bheight'];
16140 }
16141 else { break; }
16142
16143 $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
16144 $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
16145
16146 $objattr['type'] = 'barcode';
16147 $objattr['height'] = $h + $extraheight;
16148 $objattr['width'] = $w + $extrawidth;
16149 $objattr['barcode_height'] = $h;
16150 $objattr['barcode_width'] = $w;
16151 /*-- CSS-IMAGE-FLOAT --*/
16152 if (!$this->ColActive && !$this->tableLevel && !$this->listlvl && !$this->kwt && !$this->keep_block_together) {
16153 if (isset($properties['FLOAT']) && (strtoupper($properties['FLOAT']) == 'RIGHT' || strtoupper($properties['FLOAT']) == 'LEFT')) {
16154 $objattr['float'] = substr(strtoupper($properties['FLOAT']),0,1);
16155 }
16156 }
16157 /*-- END CSS-IMAGE-FLOAT --*/
16158
16159 $e = "\xbb\xa4\xactype=barcode,objattr=".serialize($objattr)."\xbb\xa4\xac";
16160
16161 // Clear properties - tidy up
16162 $properties = array();
16163
16164 /*-- TABLES --*/
16165 // Output it to buffers
16166 if ($this->tableLevel) {
16167 $this->_saveCellTextBuffer($e, $this->HREF);
16168 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
16169 }
16170 else {
16171 /*-- END TABLES --*/
16172 $this->_saveTextBuffer($e, $this->HREF);
16173
16174 } // *TABLES*
16175 }
16176 break;
16177 /*-- END BARCODES --*/
16178
16179
16180 // *********** FORM ELEMENTS ********************
16181
16182 /*-- FORMS --*/
16183 case 'SELECT':
16184 $this->lastoptionaltag = ''; // Save current HTML specified optional endtag
16185 $this->InlineProperties[$tag] = $this->saveInlineProperties();
16186 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
16187 if (isset($properties['FONT-FAMILY'])) {
16188 $this->SetFont($properties['FONT-FAMILY'],$this->FontStyle,0,false);
16189 }
16190 if (isset($properties['FONT-SIZE'])) {
16191 $mmsize = $this->ConvertSize($properties['FONT-SIZE'],$this->default_font_size/_MPDFK);
16192 $this->SetFontSize($mmsize*_MPDFK,false);
16193 }
16194 if (isset($attr['SPELLCHECK']) && strtolower($attr['SPELLCHECK'])=='true') {
16195 $this->selectoption['SPELLCHECK'] = true;
16196 }
16197
16198 if (isset($properties['COLOR'])) { $this->selectoption['COLOR'] = $this->ConvertColor($properties['COLOR']); }
16199 $this->specialcontent = "type=select";
16200 if(isset($attr['DISABLED'])) { $this->selectoption['DISABLED'] = $attr['DISABLED']; }
16201 if(isset($attr['READONLY'])) { $this->selectoption['READONLY'] = $attr['READONLY']; }
16202 if(isset($attr['REQUIRED'])) { $this->selectoption['REQUIRED'] = $attr['REQUIRED']; }
16203 if(isset($attr['EDITABLE'])) { $this->selectoption['EDITABLE'] = $attr['EDITABLE']; }
16204 if(isset($attr['TITLE'])) { $this->selectoption['TITLE'] = $attr['TITLE']; }
16205 if(isset($attr['MULTIPLE'])) { $this->selectoption['MULTIPLE'] = $attr['MULTIPLE']; }
16206 if(isset($attr['SIZE']) && $attr['SIZE']>1) { $this->selectoption['SIZE'] = $attr['SIZE']; }
16207 if ($this->useActiveForms) {
16208 if(isset($attr['NAME'])) { $this->selectoption['NAME'] = $attr['NAME']; }
16209 if (isset($attr['ONCHANGE'])) { $this->selectoption['ONCHANGE'] = $attr['ONCHANGE']; }
16210 }
16211
16212 $properties = array();
16213 break;
16214
16215 case 'OPTION':
16216 $this->lastoptionaltag = 'OPTION'; // Save current HTML specified optional endtag
16217 $this->selectoption['ACTIVE'] = true;
16218 $this->selectoption['currentSEL'] = false;
16219 if (empty($this->selectoption)) {
16220 $this->selectoption['MAXWIDTH'] = '';
16221 $this->selectoption['SELECTED'] = '';
16222 }
16223 if (isset($attr['SELECTED'])) {
16224 $this->selectoption['SELECTED'] = '';
16225 $this->selectoption['currentSEL'] = true;
16226 }
16227 if(isset($attr['VALUE'])) {
16228 $attr['VALUE'] = strcode2utf($attr['VALUE']);
16229 $attr['VALUE'] = $this->lesser_entity_decode($attr['VALUE']);
16230 if ($this->onlyCoreFonts)
16231 $attr['VALUE'] = mb_convert_encoding($attr['VALUE'], $this->mb_enc,'UTF-8');
16232 }
16233 $this->selectoption['currentVAL'] = $attr['VALUE'];
16234 break;
16235
16236 case 'TEXTAREA':
16237 $objattr = array();
16238 $objattr['margin_top'] = 0;
16239 $objattr['margin_bottom'] = 0;
16240 $objattr['margin_left'] = 0;
16241 $objattr['margin_right'] = 0;
16242 $objattr['width'] = 0;
16243 $objattr['height'] = 0;
16244 $objattr['border_top']['w'] = 0;
16245 $objattr['border_bottom']['w'] = 0;
16246 $objattr['border_left']['w'] = 0;
16247 $objattr['border_right']['w'] = 0;
16248 if(isset($attr['DISABLED'])) { $objattr['disabled'] = true; }
16249 if(isset($attr['READONLY'])) { $objattr['readonly'] = true; }
16250 if(isset($attr['REQUIRED'])) { $objattr['required'] = true; }
16251 if(isset($attr['SPELLCHECK']) && strtolower($attr['SPELLCHECK'])=='true') { $objattr['spellcheck'] = true; }
16252 if(isset($attr['TITLE'])) { $objattr['title'] = $attr['TITLE']; }
16253 if ($this->onlyCoreFonts)
16254 $objattr['title'] = mb_convert_encoding($objattr['title'], $this->mb_enc,'UTF-8');
16255 if ($this->useActiveForms) {
16256 if(isset($attr['NAME'])) { $objattr['fieldname'] = $attr['NAME']; }
16257 $this->form->form_element_spacing['textarea']['outer']['v'] = 0;
16258 $this->form->form_element_spacing['textarea']['inner']['v'] = 0;
16259 if (isset($attr['ONCALCULATE'])) { $objattr['onCalculate'] = $attr['ONCALCULATE']; }
16260 else if (isset($attr['ONCHANGE'])) { $objattr['onCalculate'] = $attr['ONCHANGE']; }
16261 if (isset($attr['ONVALIDATE'])) { $objattr['onValidate'] = $attr['ONVALIDATE']; }
16262 if (isset($attr['ONKEYSTROKE'])) { $objattr['onKeystroke'] = $attr['ONKEYSTROKE']; }
16263 if (isset($attr['ONFORMAT'])) { $objattr['onFormat'] = $attr['ONFORMAT']; }
16264 }
16265 $this->InlineProperties[$tag] = $this->saveInlineProperties();
16266 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
16267 if (isset($properties['FONT-FAMILY'])) {
16268 $this->SetFont($properties['FONT-FAMILY'],'',0,false);
16269 }
16270 if (isset($properties['FONT-SIZE'])) {
16271 $mmsize = $this->ConvertSize($properties['FONT-SIZE'],$this->default_font_size/_MPDFK);
16272 $this->SetFontSize($mmsize*_MPDFK,false);
16273 }
16274 if (isset($properties['COLOR'])) { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
16275 $objattr['fontfamily'] = $this->FontFamily;
16276 $objattr['fontsize'] = $this->FontSizePt;
16277 if ($this->useActiveForms) {
16278 if(isset($properties['TEXT-ALIGN'])) { $objattr['text_align'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
16279 else if(isset($attr['ALIGN'])) { $objattr['text_align'] = $align[strtolower($attr['ALIGN'])]; }
16280 if (isset($properties['OVERFLOW']) && strtolower($properties['OVERFLOW'])=='hidden') { $objattr['donotscroll'] = true; }
16281 if (isset($properties['BORDER-TOP-COLOR'])) { $objattr['border-col'] = $this->ConvertColor($properties['BORDER-TOP-COLOR']); }
16282 if (isset($properties['BACKGROUND-COLOR'])) { $objattr['background-col'] = $this->ConvertColor($properties['BACKGROUND-COLOR']); }
16283 }
16284 $this->SetLineHeight('',$this->form->textarea_lineheight);
16285 $formLineHeight = $this->lineheight;
16286
16287 $w = 0;
16288 $h = 0;
16289 if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16290 if(isset($properties['HEIGHT'])) $h = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16291 if ($properties['VERTICAL-ALIGN']) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
16292
16293 $colsize = 20; //HTML default value
16294 $rowsize = 2; //HTML default value
16295 if (isset($attr['COLS'])) $colsize = intval($attr['COLS']);
16296 if (isset($attr['ROWS'])) $rowsize = intval($attr['ROWS']);
16297
16298 $charsize = $this->GetCharWidth('w',false);
16299 if ($w) { $colsize = round(($w-($this->form->form_element_spacing['textarea']['outer']['h']*2)-($this->form->form_element_spacing['textarea']['inner']['h']*2))/$charsize); }
16300 if ($h) { $rowsize = round(($h-($this->form->form_element_spacing['textarea']['outer']['v']*2)-($this->form->form_element_spacing['textarea']['inner']['v']*2))/$formLineHeight); }
16301
16302 $objattr['type'] = 'textarea';
16303 $objattr['width'] = ($colsize * $charsize) + ($this->form->form_element_spacing['textarea']['outer']['h']*2)+($this->form->form_element_spacing['textarea']['inner']['h']*2);
16304 $objattr['height'] = ($rowsize * $formLineHeight) + ($this->form->form_element_spacing['textarea']['outer']['v']*2)+($this->form->form_element_spacing['textarea']['inner']['v']*2);
16305 $objattr['rows'] = $rowsize;
16306 $objattr['cols'] = $colsize;
16307
16308 $this->specialcontent = serialize($objattr);
16309
16310 if ($this->tableLevel) { // *TABLES*
16311 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ; // *TABLES*
16312 } // *TABLES*
16313
16314 // Clear properties - tidy up
16315 $properties = array();
16316 break;
16317
16318
16319
16320 // *********** FORM - INPUT ********************
16321
16322 case 'INPUT':
16323 if (!isset($attr['TYPE'])) $attr['TYPE'] == 'TEXT';
16324 $objattr = array();
16325 $objattr['margin_top'] = 0;
16326 $objattr['margin_bottom'] = 0;
16327 $objattr['margin_left'] = 0;
16328 $objattr['margin_right'] = 0;
16329 $objattr['width'] = 0;
16330 $objattr['height'] = 0;
16331 $objattr['border_top']['w'] = 0;
16332 $objattr['border_bottom']['w'] = 0;
16333 $objattr['border_left']['w'] = 0;
16334 $objattr['border_right']['w'] = 0;
16335 $objattr['type'] = 'input';
16336 if(isset($attr['DISABLED'])) { $objattr['disabled'] = true; }
16337 if(isset($attr['READONLY'])) { $objattr['readonly'] = true; }
16338 if(isset($attr['REQUIRED'])) { $objattr['required'] = true; }
16339 if(isset($attr['SPELLCHECK']) && strtolower($attr['SPELLCHECK'])=='true') { $objattr['spellcheck'] = true; }
16340 if(isset($attr['TITLE'])) { $objattr['title'] = $attr['TITLE']; }
16341 else if(isset($attr['ALT'])) { $objattr['title'] = $attr['ALT']; }
16342 else $objattr['title'] = '';
16343 $objattr['title'] = strcode2utf($objattr['title']);
16344 $objattr['title'] = $this->lesser_entity_decode($objattr['title']);
16345 if ($this->onlyCoreFonts)
16346 $objattr['title'] = mb_convert_encoding($objattr['title'], $this->mb_enc,'UTF-8');
16347 if ($this->useActiveForms) {
16348 if(isset($attr['NAME'])) { $objattr['fieldname'] = $attr['NAME']; }
16349 }
16350 if(isset($attr['VALUE'])) {
16351 $attr['VALUE'] = strcode2utf($attr['VALUE']);
16352 $attr['VALUE'] = $this->lesser_entity_decode($attr['VALUE']);
16353 if ($this->onlyCoreFonts)
16354 $attr['VALUE'] = mb_convert_encoding($attr['VALUE'], $this->mb_enc,'UTF-8');
16355 $objattr['value'] = $attr['VALUE'];
16356 }
16357
16358 $this->InlineProperties[$tag] = $this->saveInlineProperties();
16359 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
16360 $objattr['vertical-align'] = '';
16361
16362 if (isset($properties['FONT-FAMILY'])) {
16363 $this->SetFont($properties['FONT-FAMILY'],$this->FontStyle,0,false);
16364 }
16365 if (isset($properties['FONT-SIZE'])) {
16366 $mmsize = $this->ConvertSize($properties['FONT-SIZE'],($this->default_font_size/_MPDFK));
16367 $this->SetFontSize($mmsize*_MPDFK,false);
16368 }
16369 if (isset($properties['COLOR'])) { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
16370 $objattr['fontfamily'] = $this->FontFamily;
16371 $objattr['fontsize'] = $this->FontSizePt;
16372 if ($this->useActiveForms) {
16373 if(isset($attr['ALIGN'])) { $objattr['text_align'] = $align[strtolower($attr['ALIGN'])]; }
16374 else if(isset($properties['TEXT-ALIGN'])) { $objattr['text_align'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
16375 if (isset($properties['BORDER-TOP-COLOR'])) { $objattr['border-col'] = $this->ConvertColor($properties['BORDER-TOP-COLOR']); }
16376 if (isset($properties['BACKGROUND-COLOR'])) { $objattr['background-col'] = $this->ConvertColor($properties['BACKGROUND-COLOR']); }
16377 }
16378
16379 $type = '';
16380 $texto='';
16381 $height = $this->FontSize;
16382 $width = 0;
16383 $spacesize = $this->GetCharWidth(' ',false);
16384
16385 $w = 0;
16386 if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width']);
16387
16388 if ($properties['VERTICAL-ALIGN']) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
16389
16390 switch(strtoupper($attr['TYPE'])){
16391 case 'HIDDEN':
16392 $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
16393 if ($this->useActiveForms) {
16394 $this->form->SetFormText( 0, 0, $objattr['fieldname'], $objattr['value'], $objattr['value'], '', 0, '', true );
16395 }
16396 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
16397 unset($this->InlineProperties[$tag]);
16398 break 2;
16399 case 'CHECKBOX': //Draw Checkbox
16400 $type = 'CHECKBOX';
16401 if (isset($attr['CHECKED'])) { $objattr['checked'] = true; }
16402 else { $objattr['checked'] = false; }
16403 $width = $this->FontSize;
16404 $height = $this->FontSize;
16405 break;
16406
16407 case 'RADIO': //Draw Radio button
16408 $type = 'RADIO';
16409 if (isset($attr['CHECKED'])) $objattr['checked'] = true;
16410 $width = $this->FontSize;
16411 $height = $this->FontSize;
16412 break;
16413
16414 /*-- IMAGES-CORE --*/
16415 case 'IMAGE': // Draw an Image button
16416 if(isset($attr['SRC'])) {
16417 $type = 'IMAGE';
16418 $srcpath = $attr['SRC'];
16419 $orig_srcpath = $attr['ORIG_SRC'];
16420 // VSPACE and HSPACE converted to margins in MergeCSS
16421 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16422 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16423 if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16424 if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16425
16426
16427 if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
16428 if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
16429 if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
16430 if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
16431
16432 $objattr['padding_top'] = 0;
16433 $objattr['padding_bottom'] = 0;
16434 $objattr['padding_left'] = 0;
16435 $objattr['padding_right'] = 0;
16436
16437 if (isset($properties['VERTICAL-ALIGN'])) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
16438
16439 $w = 0;
16440 $h = 0;
16441 if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width']);
16442 if(isset($properties['HEIGHT'])) $h = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width']);
16443
16444 $extraheight = $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
16445 $extrawidth = $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
16446
16447 // Image file
16448 $info=$this->_getImage($srcpath, true, true, $orig_srcpath);
16449 if(!$info) {
16450 $info = $this->_getImage($this->noImageFile);
16451 if ($info) {
16452 $srcpath = $this->noImageFile;
16453 $w = ($info['w'] * (25.4/$this->dpi));
16454 $h = ($info['h'] * (25.4/$this->dpi));
16455 }
16456 }
16457 if(!$info) break;
16458 if ($info['cs']=='Indexed') { $objattr['Indexed'] = true; }
16459 $objattr['file'] = $srcpath;
16460 //Default width and height calculation if needed
16461 if($w==0 and $h==0) {
16462 /*-- IMAGES-WMF --*/
16463 if ($info['type']=='wmf') {
16464 // WMF units are twips (1/20pt)
16465 // divide by 20 to get points
16466 // divide by k to get user units
16467 $w = abs($info['w'])/(20*_MPDFK);
16468 $h = abs($info['h']) / (20*_MPDFK);
16469 }
16470 else
16471 /*-- END IMAGES-WMF --*/
16472 if ($info['type']=='svg') {
16473 // SVG units are pixels
16474 $w = abs($info['w'])/_MPDFK;
16475 $h = abs($info['h'])/_MPDFK;
16476 }
16477 else {
16478 //Put image at default image dpi
16479 $w=($info['w']/_MPDFK) * (72/$this->img_dpi);
16480 $h=($info['h']/_MPDFK) * (72/$this->img_dpi);
16481 }
16482 if (isset($properties['IMAGE-RESOLUTION'])) {
16483 if (preg_match('/from-image/i', $properties['IMAGE-RESOLUTION']) && isset($info['set-dpi']) && $info['set-dpi']>0) {
16484 $w *= $this->img_dpi / $info['set-dpi'];
16485 $h *= $this->img_dpi / $info['set-dpi'];
16486 }
16487 else if (preg_match('/(\d+)dpi/i', $properties['IMAGE-RESOLUTION'], $m)) {
16488 $dpi = $m[1];
16489 if ($dpi > 0) {
16490 $w *= $this->img_dpi / $dpi;
16491 $h *= $this->img_dpi / $dpi;
16492 }
16493 }
16494 }
16495 }
16496 // IF WIDTH OR HEIGHT SPECIFIED
16497 if($w==0) $w=$h*$info['w']/$info['h'];
16498 if($h==0) $h=$w*$info['h']/$info['w'];
16499 // Resize to maximum dimensions of page
16500 $maxWidth = $this->blk[$this->blklvl]['inner_width'];
16501 $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 10) ;
16502 if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
16503 if ($w + $extrawidth > $maxWidth ) {
16504 $w = $maxWidth - $extrawidth;
16505 $h=$w*$info['h']/$info['w'];
16506 }
16507 if ($h + $extraheight > $maxHeight ) {
16508 $h = $maxHeight - $extraheight;
16509 $w=$h*$info['w']/$info['h'];
16510 }
16511 $height = $h + $extraheight;
16512 $width = $w + $extrawidth;
16513 $objattr['type'] = 'image';
16514 $objattr['itype'] = $info['type'];
16515 $objattr['orig_h'] = $info['h'];
16516 $objattr['orig_w'] = $info['w'];
16517 /*-- IMAGES-WMF --*/
16518 if ($info['type']=='wmf') {
16519 $objattr['wmf_x'] = $info['x'];
16520 $objattr['wmf_y'] = $info['y'];
16521 }
16522 else
16523 /*-- END IMAGES-WMF --*/
16524 if ($info['type']=='svg') {
16525 $objattr['wmf_x'] = $info['x'];
16526 $objattr['wmf_y'] = $info['y'];
16527 }
16528 $objattr['height'] = $h + $extraheight;
16529 $objattr['width'] = $w + $extrawidth;
16530
16531 $objattr['image_height'] = $h;
16532 $objattr['image_width'] = $w;
16533 $objattr['ID'] = $info['i'];
16534 $texto = 'X';
16535 if ($this->useActiveForms) {
16536 if (isset($attr['ONCLICK'])) { $objattr['onClick'] = $attr['ONCLICK']; }
16537 $objattr['type'] = 'input';
16538 $type = 'IMAGE';
16539 }
16540 break;
16541 }
16542 /*-- END IMAGES-CORE --*/
16543
16544 case 'BUTTON': // Draw a button
16545 case 'SUBMIT':
16546 case 'RESET':
16547 $type = strtoupper($attr['TYPE']);
16548 if ($type=='IMAGE') { $type = 'BUTTON'; } // src path not found
16549 if(isset($attr['NOPRINT'])) { $objattr['noprint'] = true; }
16550 if (!isset($attr['VALUE'])) {
16551 $objattr['value'] = ucfirst(strtolower($type));
16552 }
16553
16554 $texto = " " . $objattr['value'] . " ";
16555 $width = $this->GetStringWidth($texto) + ($this->form->form_element_spacing['button']['outer']['h']*2)+($this->form->form_element_spacing['button']['inner']['h']*2);
16556 $height = $this->FontSize + ($this->form->form_element_spacing['button']['outer']['v']*2)+($this->form->form_element_spacing['button']['inner']['v']*2);
16557 if ($this->useActiveForms) {
16558 if (isset($attr['ONCLICK'])) { $objattr['onClick'] = $attr['ONCLICK']; }
16559 }
16560 break;
16561
16562 case 'PASSWORD':
16563 case 'TEXT':
16564 default:
16565 if ($type == '') { $type = 'TEXT'; }
16566 if(strtoupper($attr['TYPE'])=='PASSWORD') { $type = 'PASSWORD'; }
16567 if (isset($attr['VALUE'])) {
16568 if ($type == 'PASSWORD') {
16569 $num_stars = mb_strlen($attr['VALUE'],$this->mb_enc );
16570 $texto = str_repeat('*',$num_stars);
16571 }
16572 else { $texto = $attr['VALUE']; }
16573 }
16574 $xw = ($this->form->form_element_spacing['input']['outer']['h']*2)+($this->form->form_element_spacing['input']['inner']['h']*2);
16575 $xh = ($this->form->form_element_spacing['input']['outer']['v']*2)+($this->form->form_element_spacing['input']['inner']['v']*2);
16576 if ($w) { $width = $w + $xw; }
16577 else { $width = (20 * $spacesize) + $xw; } // Default width in chars
16578 if (isset($attr['SIZE']) and ctype_digit($attr['SIZE']) ) $width = ($attr['SIZE'] * $spacesize) + $xw;
16579 $height = $this->FontSize + $xh;
16580 if (isset($attr['MAXLENGTH']) and ctype_digit($attr['MAXLENGTH']) ) $objattr['maxlength'] = $attr['MAXLENGTH'];
16581 if ($this->useActiveForms) {
16582 if (isset($attr['ONCALCULATE'])) { $objattr['onCalculate'] = $attr['ONCALCULATE']; }
16583 else if (isset($attr['ONCHANGE'])) { $objattr['onCalculate'] = $attr['ONCHANGE']; }
16584 if (isset($attr['ONVALIDATE'])) { $objattr['onValidate'] = $attr['ONVALIDATE']; }
16585 if (isset($attr['ONKEYSTROKE'])) { $objattr['onKeystroke'] = $attr['ONKEYSTROKE']; }
16586 if (isset($attr['ONFORMAT'])) { $objattr['onFormat'] = $attr['ONFORMAT']; }
16587 }
16588 break;
16589 }
16590
16591 $objattr['subtype'] = $type;
16592 $objattr['text'] = $texto;
16593 $objattr['width'] = $width;
16594 $objattr['height'] = $height;
16595 $e = "\xbb\xa4\xactype=input,objattr=".serialize($objattr)."\xbb\xa4\xac";
16596
16597 // Clear properties - tidy up
16598 $properties = array();
16599
16600 /*-- TABLES --*/
16601 // Output it to buffers
16602 if ($this->tableLevel) {
16603 $this->_saveCellTextBuffer($e, $this->HREF);
16604 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
16605
16606 }
16607 else {
16608 /*-- END TABLES --*/
16609 $this->_saveTextBuffer($e, $this->HREF);
16610 } // *TABLES*
16611
16612 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
16613 unset($this->InlineProperties[$tag]);
16614
16615 break; // END of INPUT
16616 /*-- END FORMS --*/
16617
16618
16619 // *********** GRAPH ********************
16620 case 'JPGRAPH':
16621 if (!$this->useGraphs) { break; }
16622 if ($attr['TABLE']) { $gid = strtoupper($attr['TABLE']); }
16623 else { $gid = '0'; }
16624 if (!is_array($this->graphs[$gid]) || count($this->graphs[$gid])==0 ) { break; }
16625 include_once(_MPDF_PATH.'graph.php');
16626 $this->graphs[$gid]['attr'] = $attr;
16627
16628
16629 if (isset($this->graphs[$gid]['attr']['WIDTH']) && $this->graphs[$gid]['attr']['WIDTH']) {
16630 $this->graphs[$gid]['attr']['cWIDTH']=$this->ConvertSize($this->graphs[$gid]['attr']['WIDTH'],$pgwidth);
16631 } // mm
16632 if (isset($this->graphs[$gid]['attr']['HEIGHT']) && $this->graphs[$gid]['attr']['HEIGHT']) {
16633 $this->graphs[$gid]['attr']['cHEIGHT']=$this->ConvertSize($this->graphs[$gid]['attr']['HEIGHT'],$pgwidth);
16634 }
16635
16636 $graph_img = print_graph($this->graphs[$gid],$this->blk[$this->blklvl]['inner_width']);
16637 if ($graph_img) {
16638 if(isset($attr['ROTATE'])) {
16639 if ($attr['ROTATE']==90 || $attr['ROTATE']==-90) {
16640 $tmpw = $graph_img['w'];
16641 $graph_img['w']= $graph_img['h'];
16642 $graph_img['h']= $tmpw;
16643 }
16644 }
16645 $attr['SRC'] = $graph_img['file'];
16646 $attr['WIDTH'] = $graph_img['w'];
16647 $attr['HEIGHT'] = $graph_img['h'];
16648 }
16649 else { break; }
16650
16651 // *********** IMAGE ********************
16652 /*-- IMAGES-CORE --*/
16653 case 'IMG':
16654 if ($this->progressBar) { $this->UpdateProgressBar(1,'','IMG'); } // *PROGRESS-BAR*
16655 $objattr = array();
16656 $objattr['margin_top'] = 0;
16657 $objattr['margin_bottom'] = 0;
16658 $objattr['margin_left'] = 0;
16659 $objattr['margin_right'] = 0;
16660 $objattr['padding_top'] = 0;
16661 $objattr['padding_bottom'] = 0;
16662 $objattr['padding_left'] = 0;
16663 $objattr['padding_right'] = 0;
16664 $objattr['width'] = 0;
16665 $objattr['height'] = 0;
16666 $objattr['border_top']['w'] = 0;
16667 $objattr['border_bottom']['w'] = 0;
16668 $objattr['border_left']['w'] = 0;
16669 $objattr['border_right']['w'] = 0;
16670 if(isset($attr['SRC'])) {
16671 $srcpath = $attr['SRC'];
16672 $orig_srcpath = $attr['ORIG_SRC'];
16673 $properties = $this->cssmgr->MergeCSS('',$tag,$attr);
16674 if(isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY'])=='none') {
16675 return;
16676 }
16677 // mPDF 5.6.01 - LAYERS
16678 if (isset($properties['Z-INDEX']) && $this->currentlayer==0) {
16679 $v = intval($properties['Z-INDEX']);
16680 if ($v > 0) {
16681 $objattr['z-index'] = $v;
16682 }
16683 }
16684
16685 $objattr['visibility'] = 'visible';
16686 if (isset($properties['VISIBILITY'])) {
16687 $v = strtolower($properties['VISIBILITY']);
16688 if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible') {
16689 $objattr['visibility'] = $v;
16690 }
16691 }
16692
16693 // VSPACE and HSPACE converted to margins in MergeCSS
16694 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16695 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16696 if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16697 if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16698
16699 if (isset($properties['PADDING-TOP'])) { $objattr['padding_top']=$this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16700 if (isset($properties['PADDING-BOTTOM'])) { $objattr['padding_bottom'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16701 if (isset($properties['PADDING-LEFT'])) { $objattr['padding_left'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16702 if (isset($properties['PADDING-RIGHT'])) { $objattr['padding_right'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16703
16704 if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
16705 if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
16706 if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
16707 if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
16708
16709 if (isset($properties['VERTICAL-ALIGN'])) { $objattr['vertical-align'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
16710 $w = 0;
16711 $h = 0;
16712 if(isset($properties['WIDTH'])) $w = $this->ConvertSize($properties['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16713 else if(isset($attr['WIDTH'])) $w = $this->ConvertSize($attr['WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16714 if(isset($properties['HEIGHT'])) $h = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16715 else if(isset($attr['HEIGHT'])) $h = $this->ConvertSize($attr['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16716 // mPDF 5.5.15 // mPDF 5.6.60
16717 $maxw=$maxh=$minw=$minh=false;
16718 if(isset($properties['MAX-WIDTH'])) $maxw = $this->ConvertSize($properties['MAX-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16719 else if(isset($attr['MAX-WIDTH'])) $maxw = $this->ConvertSize($attr['MAX-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16720 if(isset($properties['MAX-HEIGHT'])) $maxh = $this->ConvertSize($properties['MAX-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16721 else if(isset($attr['MAX-HEIGHT'])) $maxh = $this->ConvertSize($attr['MAX-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16722 if(isset($properties['MIN-WIDTH'])) $minw = $this->ConvertSize($properties['MIN-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16723 else if(isset($attr['MIN-WIDTH'])) $minw = $this->ConvertSize($attr['MIN-WIDTH'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16724 if(isset($properties['MIN-HEIGHT'])) $minh = $this->ConvertSize($properties['MIN-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16725 else if(isset($attr['MIN-HEIGHT'])) $minh = $this->ConvertSize($attr['MIN-HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
16726
16727 if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { $objattr['opacity'] = $properties['OPACITY']; }
16728 if ($this->HREF) {
16729 if (strpos($this->HREF,".") === false && strpos($this->HREF,"@") !== 0) {
16730 $href = $this->HREF;
16731 while(array_key_exists($href,$this->internallink)) $href="#".$href;
16732 $this->internallink[$href] = $this->AddLink();
16733 $objattr['link'] = $this->internallink[$href];
16734 }
16735 else { $objattr['link'] = $this->HREF; }
16736 }
16737 $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
16738 $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
16739
16740 /*-- BACKGROUNDS --*/
16741 if(isset($properties['GRADIENT-MASK']) && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/',$properties['GRADIENT-MASK'])) {
16742 $objattr['GRADIENT-MASK'] = $properties['GRADIENT-MASK'];
16743 }
16744 /*-- END BACKGROUNDS --*/
16745
16746 // Image file
16747 $info=$this->_getImage($srcpath, true, true, $orig_srcpath);
16748 if(!$info) {
16749 $info = $this->_getImage($this->noImageFile);
16750 if ($info) {
16751 $srcpath = $this->noImageFile;
16752 $w = ($info['w'] * (25.4/$this->dpi));
16753 $h = ($info['h'] * (25.4/$this->dpi));
16754 }
16755 }
16756 if(!$info) break;
16757
16758 if(isset($attr['ROTATE'])) { $image_orientation = $attr['ROTATE']; }
16759 else if(isset($properties['IMAGE-ORIENTATION'])) { $image_orientation = $properties['IMAGE-ORIENTATION']; }
16760 else { $image_orientation = 0; }
16761 if($image_orientation) {
16762 if ($image_orientation==90 || $image_orientation==-90 || $image_orientation==270) {
16763 $tmpw = $info['w'];
16764 $info['w'] = $info['h'];
16765 $info['h'] = $tmpw;
16766 }
16767 $objattr['ROTATE'] = $image_orientation;
16768 }
16769
16770 $objattr['file'] = $srcpath;
16771 //Default width and height calculation if needed
16772 if($w==0 and $h==0) {
16773 /*-- IMAGES-WMF --*/
16774 if ($info['type']=='wmf') {
16775 // WMF units are twips (1/20pt)
16776 // divide by 20 to get points
16777 // divide by k to get user units
16778 $w = abs($info['w'])/(20*_MPDFK);
16779 $h = abs($info['h']) / (20*_MPDFK);
16780 }
16781 else
16782 /*-- END IMAGES-WMF --*/
16783 if ($info['type']=='svg') {
16784 // SVG units are pixels
16785 $w = abs($info['w'])/_MPDFK;
16786 $h = abs($info['h'])/_MPDFK;
16787 }
16788 else {
16789 //Put image at default image dpi
16790 $w=($info['w']/_MPDFK) * (72/$this->img_dpi);
16791 $h=($info['h']/_MPDFK) * (72/$this->img_dpi);
16792 }
16793 if (isset($properties['IMAGE-RESOLUTION'])) {
16794 if (preg_match('/from-image/i', $properties['IMAGE-RESOLUTION']) && isset($info['set-dpi']) && $info['set-dpi']>0) {
16795 $w *= $this->img_dpi / $info['set-dpi'];
16796 $h *= $this->img_dpi / $info['set-dpi'];
16797 }
16798 else if (preg_match('/(\d+)dpi/i', $properties['IMAGE-RESOLUTION'], $m)) {
16799 $dpi = $m[1];
16800 if ($dpi > 0) {
16801 $w *= $this->img_dpi / $dpi;
16802 $h *= $this->img_dpi / $dpi;
16803 }
16804 }
16805 }
16806 }
16807 // IF WIDTH OR HEIGHT SPECIFIED
16808 if($w==0) $w=abs($h*$info['w']/$info['h']);
16809 if($h==0) $h=abs($w*$info['h']/$info['w']);
16810
16811 // mPDF 5.5.15
16812 if ($minw && $w<$minw) { $w = $minw; $h=abs($w*$info['h']/$info['w']); }
16813 if ($maxw && $w>$maxw) { $w = $maxw; $h=abs($w*$info['h']/$info['w']); }
16814 if ($minh && $h<$minh) { $h = $minh; $w=abs($h*$info['w']/$info['h']); }
16815 if ($maxh && $h>$maxh) { $h = $maxh; $w=abs($h*$info['w']/$info['h']); }
16816
16817 // Resize to maximum dimensions of page
16818 $maxWidth = $this->blk[$this->blklvl]['inner_width'];
16819 $maxHeight = $this->h - ($this->tMargin + $this->bMargin + 1) ;
16820 if ($this->fullImageHeight) { $maxHeight = $this->fullImageHeight; }
16821 if ($w + $extrawidth > $maxWidth ) {
16822 $w = $maxWidth - $extrawidth;
16823 $h=abs($w*$info['h']/$info['w']);
16824 }
16825
16826 if ($h + $extraheight > $maxHeight ) {
16827 $h = $maxHeight - $extraheight;
16828 $w=abs($h*$info['w']/$info['h']);
16829 }
16830 $objattr['type'] = 'image';
16831 $objattr['itype'] = $info['type'];
16832
16833 $objattr['orig_h'] = $info['h'];
16834 $objattr['orig_w'] = $info['w'];
16835 /*-- IMAGES-WMF --*/
16836 if ($info['type']=='wmf') {
16837 $objattr['wmf_x'] = $info['x'];
16838 $objattr['wmf_y'] = $info['y'];
16839 }
16840 else
16841 /*-- END IMAGES-WMF --*/
16842 if ($info['type']=='svg') {
16843 $objattr['wmf_x'] = $info['x'];
16844 $objattr['wmf_y'] = $info['y'];
16845 }
16846 $objattr['height'] = $h + $extraheight;
16847 $objattr['width'] = $w + $extrawidth;
16848 $objattr['image_height'] = $h;
16849 $objattr['image_width'] = $w;
16850 /*-- CSS-IMAGE-FLOAT --*/
16851 if (!$this->ColActive && !$this->tableLevel && !$this->listlvl && !$this->kwt && !$this->keep_block_together) {
16852 if (isset($properties['FLOAT']) && (strtoupper($properties['FLOAT']) == 'RIGHT' || strtoupper($properties['FLOAT']) == 'LEFT')) {
16853 $objattr['float'] = substr(strtoupper($properties['FLOAT']),0,1);
16854 }
16855 }
16856 /*-- END CSS-IMAGE-FLOAT --*/
16857
16858 $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
16859
16860 // Clear properties - tidy up
16861 $properties = array();
16862
16863 /*-- TABLES --*/
16864 // Output it to buffers
16865 if ($this->tableLevel) {
16866 $this->_saveCellTextBuffer($e, $this->HREF);
16867 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
16868 }
16869 else {
16870 /*-- END TABLES --*/
16871 $this->_saveTextBuffer($e, $this->HREF);
16872 } // *TABLES*
16873 /*-- ANNOTATIONS --*/
16874 if ($this->title2annots && isset($attr['TITLE'])) {
16875 $objattr = array();
16876 $objattr['margin_top'] = 0;
16877 $objattr['margin_bottom'] = 0;
16878 $objattr['margin_left'] = 0;
16879 $objattr['margin_right'] = 0;
16880 $objattr['width'] = 0;
16881 $objattr['height'] = 0;
16882 $objattr['border_top']['w'] = 0;
16883 $objattr['border_bottom']['w'] = 0;
16884 $objattr['border_left']['w'] = 0;
16885 $objattr['border_right']['w'] = 0;
16886 $objattr['CONTENT'] = $attr['TITLE'];
16887 $objattr['type'] = 'annot';
16888 $objattr['POS-X'] = 0;
16889 $objattr['POS-Y'] = 0;
16890 $objattr['ICON'] = 'Comment';
16891 $objattr['AUTHOR'] = '';
16892 $objattr['SUBJECT'] = '';
16893 $objattr['OPACITY'] = $this->annotOpacity;
16894 $objattr['COLOR'] = $this->ConvertColor('yellow');
16895 $e = "\xbb\xa4\xactype=annot,objattr=".serialize($objattr)."\xbb\xa4\xac";
16896 if($this->tableLevel) { // *TABLES*
16897 $this->cell[$this->row][$this->col]['textbuffer'][] = array($e); // *TABLES*
16898 } // *TABLES*
16899 else { // *TABLES*
16900 $this->textbuffer[] = array($e);
16901 } // *TABLES*
16902 }
16903 /*-- END ANNOTATIONS --*/
16904 }
16905 break;
16906 /*-- END IMAGES-CORE --*/
16907
16908
16909 // *********** CIRCULAR TEXT = TEXTCIRCLE ********************
16910 case 'TEXTCIRCLE':
16911 $objattr = array();
16912 $objattr['margin_top'] = 0;
16913 $objattr['margin_bottom'] = 0;
16914 $objattr['margin_left'] = 0;
16915 $objattr['margin_right'] = 0;
16916 $objattr['padding_top'] = 0;
16917 $objattr['padding_bottom'] = 0;
16918 $objattr['padding_left'] = 0;
16919 $objattr['padding_right'] = 0;
16920 $objattr['width'] = 0;
16921 $objattr['height'] = 0;
16922 $objattr['border_top']['w'] = 0;
16923 $objattr['border_bottom']['w'] = 0;
16924 $objattr['border_left']['w'] = 0;
16925 $objattr['border_right']['w'] = 0;
16926 $objattr['top-text'] = '';
16927 $objattr['bottom-text'] = '';
16928 $objattr['r'] = 20; // radius (default value here for safety)
16929 $objattr['space-width'] = 120;
16930 $objattr['char-width'] = 100;
16931
16932 $this->InlineProperties[$tag] = $this->saveInlineProperties();
16933 $properties = $this->cssmgr->MergeCSS('INLINE',$tag,$attr);
16934
16935 if(isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY'])=='none') {
16936 return;
16937 }
16938 if (isset($attr['R'])) { $objattr['r']=$this->ConvertSize($attr['R'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
16939 if(isset($attr['TOP-TEXT'])) {
16940 $objattr['top-text'] = strcode2utf($attr['TOP-TEXT']);
16941 $objattr['top-text'] = $this->lesser_entity_decode($objattr['top-text']);
16942 if ($this->onlyCoreFonts)
16943 $objattr['top-text'] = mb_convert_encoding($objattr['top-text'], $this->mb_enc,'UTF-8');
16944 }
16945 if(isset($attr['BOTTOM-TEXT'])) {
16946 $objattr['bottom-text'] = strcode2utf($attr['BOTTOM-TEXT']);
16947 $objattr['bottom-text'] = $this->lesser_entity_decode($objattr['bottom-text']);
16948 if ($this->onlyCoreFonts)
16949 $objattr['bottom-text'] = mb_convert_encoding($objattr['bottom-text'], $this->mb_enc,'UTF-8');
16950 }
16951 if(isset($attr['SPACE-WIDTH']) && $attr['SPACE-WIDTH']) { $objattr['space-width'] = $attr['SPACE-WIDTH']; }
16952 if(isset($attr['CHAR-WIDTH']) && $attr['CHAR-WIDTH']) { $objattr['char-width'] = $attr['CHAR-WIDTH']; }
16953
16954 // VISIBILITY
16955 $objattr['visibility'] = 'visible';
16956 if (isset($properties['VISIBILITY'])) {
16957 $v = strtolower($properties['VISIBILITY']);
16958 if (($v == 'hidden' || $v == 'printonly' || $v == 'screenonly') && $this->visibility=='visible') {
16959 $objattr['visibility'] = $v;
16960 }
16961 }
16962 // mPDF 5.5.23
16963 if (isset($properties['FONT-SIZE'])) {
16964 if (strtolower($properties['FONT-SIZE'])=='auto') {
16965 if ($objattr['top-text'] && $objattr['bottom-text']) {
16966 $objattr['fontsize'] = -2;
16967 }
16968 else {
16969 $objattr['fontsize'] = -1;
16970 }
16971 }
16972 else {
16973 $mmsize = $this->ConvertSize($properties['FONT-SIZE'],($this->default_font_size/_MPDFK));
16974 $this->SetFontSize($mmsize*_MPDFK,false);
16975 $objattr['fontsize'] = $this->FontSizePt;
16976 }
16977 }
16978 // mPDF 5.5.23
16979 if(isset($attr['DIVIDER'])) {
16980 $objattr['divider'] = strcode2utf($attr['DIVIDER']);
16981 $objattr['divider'] = $this->lesser_entity_decode($objattr['divider']);
16982 if ($this->onlyCoreFonts)
16983 $objattr['divider'] = mb_convert_encoding($objattr['divider'], $this->mb_enc,'UTF-8');
16984
16985 }
16986
16987 if (isset($properties['COLOR'])) { $objattr['color'] = $this->ConvertColor($properties['COLOR']); }
16988
16989 $objattr['fontstyle'] = '';
16990 if (isset($properties['FONT-WEIGHT'])) {
16991 if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $objattr['fontstyle'] .= 'B'; }
16992 }
16993 if (isset($properties['FONT-STYLE'])) {
16994 if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $objattr['fontstyle'] .= 'I'; }
16995 }
16996
16997 if (isset($properties['FONT-FAMILY'])) {
16998 $this->SetFont($properties['FONT-FAMILY'],$this->FontStyle,0,false);
16999 }
17000 $objattr['fontfamily'] = $this->FontFamily;
17001
17002 // VSPACE and HSPACE converted to margins in MergeCSS
17003 if (isset($properties['MARGIN-TOP'])) { $objattr['margin_top']=$this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17004 if (isset($properties['MARGIN-BOTTOM'])) { $objattr['margin_bottom'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17005 if (isset($properties['MARGIN-LEFT'])) { $objattr['margin_left'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17006 if (isset($properties['MARGIN-RIGHT'])) { $objattr['margin_right'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17007
17008 if (isset($properties['PADDING-TOP'])) { $objattr['padding_top']=$this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17009 if (isset($properties['PADDING-BOTTOM'])) { $objattr['padding_bottom'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17010 if (isset($properties['PADDING-LEFT'])) { $objattr['padding_left'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17011 if (isset($properties['PADDING-RIGHT'])) { $objattr['padding_right'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17012
17013 if (isset($properties['BORDER-TOP'])) { $objattr['border_top'] = $this->border_details($properties['BORDER-TOP']); }
17014 if (isset($properties['BORDER-BOTTOM'])) { $objattr['border_bottom'] = $this->border_details($properties['BORDER-BOTTOM']); }
17015 if (isset($properties['BORDER-LEFT'])) { $objattr['border_left'] = $this->border_details($properties['BORDER-LEFT']); }
17016 if (isset($properties['BORDER-RIGHT'])) { $objattr['border_right'] = $this->border_details($properties['BORDER-RIGHT']); }
17017
17018 if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { $objattr['opacity'] = $properties['OPACITY']; }
17019 if (isset($properties['BACKGROUND-COLOR']) && $properties['BACKGROUND-COLOR'] != '') { $objattr['bgcolor'] = $this->ConvertColor($properties['BACKGROUND-COLOR']); }
17020 else { $objattr['bgcolor'] = false; }
17021 if ($this->HREF) {
17022 if (strpos($this->HREF,".") === false && strpos($this->HREF,"@") !== 0) {
17023 $href = $this->HREF;
17024 while(array_key_exists($href,$this->internallink)) $href="#".$href;
17025 $this->internallink[$href] = $this->AddLink();
17026 $objattr['link'] = $this->internallink[$href];
17027 }
17028 else { $objattr['link'] = $this->HREF; }
17029 }
17030 $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w'];
17031 $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w'];
17032
17033
17034 $w = $objattr['r']*2;
17035 $h = $w;
17036 $objattr['height'] = $h + $extraheight;
17037 $objattr['width'] = $w + $extrawidth;
17038 $objattr['type'] = 'textcircle';
17039
17040 $e = "\xbb\xa4\xactype=image,objattr=".serialize($objattr)."\xbb\xa4\xac";
17041
17042 // Clear properties - tidy up
17043 $properties = array();
17044
17045 /*-- TABLES --*/
17046 // Output it to buffers
17047 if ($this->tableLevel) {
17048 $this->_saveCellTextBuffer($e, $this->HREF);
17049 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ;
17050 }
17051 else {
17052 /*-- END TABLES --*/
17053 $this->_saveTextBuffer($e, $this->HREF);
17054 } // *TABLES*
17055
17056 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
17057 unset($this->InlineProperties[$tag]);
17058
17059 break;
17060
17061
17062 /*-- TABLES --*/
17063
17064 case 'TABLE': // TABLE-BEGIN
17065 $this->tdbegin = false;
17066 $this->lastoptionaltag = '';
17067 // Disable vertical justification in columns
17068 if ($this->ColActive) { $this->colvAlign = ''; } // *COLUMNS*
17069 if ($this->lastblocklevelchange == 1) { $blockstate = 1; } // Top margins/padding only
17070 else if ($this->lastblocklevelchange < 1) { $blockstate = 0; } // NO margins/padding
17071 // called from block after new div e.g. <div> ... <table> ... Outputs block top margin/border and padding
17072 if (count($this->textbuffer) == 0 && $this->lastblocklevelchange == 1 && !$this->tableLevel && !$this->kwt) {
17073 $this->newFlowingBlock( $this->blk[$this->blklvl]['width'],$this->lineheight,'',false,false,1,true, $this->blk[$this->blklvl]['direction']);
17074 $this->finishFlowingBlock(true); // true = END of flowing block
17075 }
17076 else if (!$this->tableLevel && count($this->textbuffer)) { $this->printbuffer($this->textbuffer,$blockstate); }
17077
17078 $this->textbuffer=array();
17079 $this->lastblocklevelchange = -1;
17080 if ($this->tableLevel) { // i.e. now a nested table coming...
17081 // Save current level table
17082 // mPDF 5.4.10
17083 $this->cell['PARENTCELL'] = $this->saveInlineProperties();
17084 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['baseProperties']= $this->base_table_properties;
17085 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] = $this->cell;
17086 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currrow'] = $this->row;
17087 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currcol'] = $this->col;
17088 }
17089 $this->tableLevel++;
17090 $this->cssmgr->tbCSSlvl++;
17091
17092 if ($this->tableLevel>1) { // inherit table properties from cell in which nested
17093 $this->base_table_properties['FONT-KERNING'] = $this->kerning ;
17094 $this->base_table_properties['LETTER-SPACING'] = $this->lSpacingCSS ;
17095 $this->base_table_properties['WORD-SPACING'] = $this->wSpacingCSS ;
17096 }
17097
17098 if (isset($this->tbctr[$this->tableLevel])) { $this->tbctr[$this->tableLevel]++; }
17099 else { $this->tbctr[$this->tableLevel] = 1; }
17100
17101 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['level'] = $this->tableLevel;
17102 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['levelid'] = $this->tbctr[$this->tableLevel];
17103
17104 if ($this->tableLevel > $this->innermostTableLevel) { $this->innermostTableLevel = $this->tableLevel; }
17105 if ($this->tableLevel > 1) {
17106 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nestedpos'] = array($this->row,$this->col,$this->tbctr[($this->tableLevel-1)]);
17107 }
17108 //++++++++++++++++++++++++++++
17109
17110 $this->cell = array();
17111 $this->col=-1; //int
17112 $this->row=-1; //int
17113 $table = &$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]];
17114
17115 // New table - any level
17116 if ($this->cacheTables) {
17117 $this->packTableData = true; // required for cacheTables
17118 $this->simpleTables = false; // Cannot co-exist with cacheTables
17119 $table['cache'] = _MPDF_TEMP_PATH.'_tempTblCache'.RAND(1,1000000).'.dat';
17120 $fh = fopen($table['cache'] , "wb") or $this->Error("When using cacheTables, you must have read/write access to cache files (".$table['cache'] .")");
17121 fwrite($fh, "\x00");
17122 fclose($fh);
17123 $table['ptr'] = 1 ; // Must not be 0
17124 }
17125
17126 $table['direction'] = $this->directionality;
17127 $table['bgcolor'] = false;
17128 $table['va'] = false;
17129 $table['txta'] = false;
17130 $table['topntail'] = false;
17131 $table['thead-underline'] = false;
17132 $table['border'] = false;
17133 $table['border_details']['R']['w'] = 0;
17134 $table['border_details']['L']['w'] = 0;
17135 $table['border_details']['T']['w'] = 0;
17136 $table['border_details']['B']['w'] = 0;
17137 $table['border_details']['R']['style'] = '';
17138 $table['border_details']['L']['style'] = '';
17139 $table['border_details']['T']['style'] = '';
17140 $table['border_details']['B']['style'] = '';
17141 $table['max_cell_border_width']['R'] = 0;
17142 $table['max_cell_border_width']['L'] = 0;
17143 $table['max_cell_border_width']['T'] = 0;
17144 $table['max_cell_border_width']['B'] = 0;
17145 $table['padding']['L'] = false;
17146 $table['padding']['R'] = false;
17147 $table['padding']['T'] = false;
17148 $table['padding']['B'] = false;
17149 $table['margin']['L'] = false;
17150 $table['margin']['R'] = false;
17151 $table['margin']['T'] = false;
17152 $table['margin']['B'] = false;
17153 $table['a'] = false;
17154 $table['border_spacing_H'] = false;
17155 $table['border_spacing_V'] = false;
17156 $table['decimal_align'] = false; // mPDF 5.6.13
17157 $this->Reset();
17158 $this->InlineProperties = array();
17159 $this->spanlvl = 0;
17160 $table['nc'] = $table['nr'] = 0;
17161 $this->tablethead = 0;
17162 $this->tabletfoot = 0;
17163 $this->tabletheadjustfinished = false;
17164
17165
17166 if ($this->blockjustfinished && !count($this->textbuffer) && $this->y != $this->tMargin && $this->collapseBlockMargins && $this->tableLevel==1) { $lastbottommargin = $this->lastblockbottommargin; }
17167 else { $lastbottommargin = 0; }
17168 $this->lastblockbottommargin = 0;
17169 $this->blockjustfinished=false;
17170
17171 if ($this->tableLevel==1) {
17172 $this->tableCJK = false;
17173 $this->table_lineheight = $this->normalLineheight;
17174 $table['headernrows'] = 0;
17175 $table['footernrows'] = 0;
17176 $this->base_table_properties = array();
17177 }
17178
17179 // ADDED CSS FUNCIONS FOR TABLE
17180 if ($this->cssmgr->tbCSSlvl==1) {
17181 $properties = $this->cssmgr->MergeCSS('TOPTABLE',$tag,$attr);
17182 }
17183 else {
17184 $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
17185 }
17186 $w = '';
17187 if (isset($properties['WIDTH'])) { $w = $properties['WIDTH']; }
17188 else if (isset($attr['WIDTH']) && $attr['WIDTH']) { $w = $attr['WIDTH']; }
17189
17190
17191 if(isset($properties['DIRECTION']) && $properties['DIRECTION']) { $table['direction'] = strtolower($properties['DIRECTION']); }
17192 else if(isset($attr['DIR']) && $attr['DIR']) { $table['direction'] = strtolower($attr['DIR']); }
17193 else if (!isset($table['direction'])){ $table['direction'] = $this->blk[$this->blklvl]['direction']; }
17194
17195 if (isset($properties['BACKGROUND-COLOR'])) { $table['bgcolor'][-1] = $properties['BACKGROUND-COLOR']; }
17196 else if (isset($properties['BACKGROUND'])) { $table['bgcolor'][-1] = $properties['BACKGROUND']; }
17197 else if (isset($attr['BGCOLOR'])) { $table['bgcolor'][-1] = $attr['BGCOLOR']; }
17198 if (isset($properties['VERTICAL-ALIGN'])) { $table['va'] = $align[strtolower($properties['VERTICAL-ALIGN'])]; }
17199 if (isset($properties['TEXT-ALIGN'])) { $table['txta'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
17200 if (isset($attr['ALIGN'])) { $table['a'] = $align[strtolower($attr['ALIGN'])]; }
17201 if (!$table['a']) {
17202 if ($table['direction'] == 'rtl' ) { $table['a'] = 'R'; }
17203 else { $table['a'] = 'L'; }
17204 }
17205
17206 if (isset($properties['AUTOSIZE']) && $properties['AUTOSIZE'] && $this->tableLevel ==1) {
17207 $this->shrink_this_table_to_fit = $properties['AUTOSIZE'];
17208 if ($this->shrink_this_table_to_fit < 1) { $this->shrink_this_table_to_fit = 0; }
17209 }
17210 if (isset($properties['ROTATE']) && $properties['ROTATE'] && $this->tableLevel ==1) {
17211 $this->table_rotate = $properties['ROTATE'];
17212 }
17213 if (isset($properties['TOPNTAIL'])) { $table['topntail'] = $properties['TOPNTAIL']; }
17214 if (isset($properties['THEAD-UNDERLINE'])) { $table['thead-underline'] = $properties['THEAD-UNDERLINE']; }
17215
17216 if (isset($properties['BORDER'])) {
17217 $bord = $this->border_details($properties['BORDER']);
17218 if ($bord['s']) {
17219 $table['border'] = _BORDER_ALL;
17220 $table['border_details']['R'] = $bord;
17221 $table['border_details']['L'] = $bord;
17222 $table['border_details']['T'] = $bord;
17223 $table['border_details']['B'] = $bord;
17224 }
17225 }
17226 if (isset($properties['BORDER-RIGHT'])) {
17227 if ($table['direction'] == 'rtl') { // *RTL*
17228 $table['border_details']['R'] = $this->border_details($properties['BORDER-LEFT']); // *RTL*
17229 } // *RTL*
17230 else { // *RTL*
17231 $table['border_details']['R'] = $this->border_details($properties['BORDER-RIGHT']);
17232 } // *RTL*
17233 $this->setBorder($table['border'], _BORDER_RIGHT, $table['border_details']['R']['s']);
17234 }
17235 if (isset($properties['BORDER-LEFT'])) {
17236 if ($table['direction'] == 'rtl') { // *RTL*
17237 $table['border_details']['L'] = $this->border_details($properties['BORDER-RIGHT']); // *RTL*
17238 } // *RTL*
17239 else { // *RTL*
17240 $table['border_details']['L'] = $this->border_details($properties['BORDER-LEFT']);
17241 } // *RTL*
17242 $this->setBorder($table['border'], _BORDER_LEFT, $table['border_details']['L']['s']);
17243 }
17244 if (isset($properties['BORDER-BOTTOM'])) {
17245 $table['border_details']['B'] = $this->border_details($properties['BORDER-BOTTOM']);
17246 $this->setBorder($table['border'], _BORDER_BOTTOM, $table['border_details']['B']['s']);
17247 }
17248 if (isset($properties['BORDER-TOP'])) {
17249 $table['border_details']['T'] = $this->border_details($properties['BORDER-TOP']);
17250 $this->setBorder($table['border'], _BORDER_TOP, $table['border_details']['T']['s']);
17251 }
17252 if ($table['border']){
17253 $this->table_border_css_set = 1;
17254 }
17255 else {
17256 $this->table_border_css_set = 0;
17257 }
17258
17259 if (isset($properties['FONT-FAMILY'])) {
17260 $this->default_font = $properties['FONT-FAMILY'];
17261 $this->SetFont($this->default_font,'',0,false);
17262 }
17263 $this->base_table_properties['FONT-FAMILY'] = $this->FontFamily; // mPDF 5.4.10
17264
17265 if (isset($properties['FONT-SIZE'])) {
17266 // mPDF 5.4.10
17267 if ($this->tableLevel>1) { $mmsize = $this->ConvertSize($properties['FONT-SIZE'], $this->base_table_properties['FONT-SIZE']); }
17268 else { $mmsize = $this->ConvertSize($properties['FONT-SIZE'],$this->default_font_size/_MPDFK); }
17269 if ($mmsize) {
17270 $this->default_font_size = $mmsize*(_MPDFK);
17271 $this->SetFontSize($this->default_font_size,false);
17272 }
17273 }
17274 $this->base_table_properties['FONT-SIZE'] = $this->FontSize.'mm'; // mPDF 5.4.10
17275
17276 if (isset($properties['FONT-WEIGHT'])) {
17277 if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $this->base_table_properties['FONT-WEIGHT'] = 'BOLD'; }
17278 }
17279 if (isset($properties['FONT-STYLE'])) {
17280 if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $this->base_table_properties['FONT-STYLE'] = 'ITALIC'; }
17281 }
17282 if (isset($properties['COLOR'])) {
17283 $this->base_table_properties['COLOR'] = $properties['COLOR'];
17284 }
17285 if (isset($properties['FONT-KERNING'])) {
17286 $this->base_table_properties['FONT-KERNING'] = $properties['FONT-KERNING'];
17287 }
17288 if (isset($properties['LETTER-SPACING'])) {
17289 $this->base_table_properties['LETTER-SPACING'] = $properties['LETTER-SPACING'];
17290 }
17291 if (isset($properties['WORD-SPACING'])) {
17292 $this->base_table_properties['WORD-SPACING'] = $properties['WORD-SPACING'];
17293 }
17294
17295 if (isset($properties['PADDING-LEFT'])) {
17296 $table['padding']['L'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17297 }
17298 if (isset($properties['PADDING-RIGHT'])) {
17299 $table['padding']['R'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17300 }
17301 if (isset($properties['PADDING-TOP'])) {
17302 $table['padding']['T'] = $this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17303 }
17304 if (isset($properties['PADDING-BOTTOM'])) {
17305 $table['padding']['B'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17306 }
17307
17308 if (isset($properties['MARGIN-TOP'])) {
17309 if ($lastbottommargin) {
17310 $tmp = $this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17311 if ($tmp > $lastbottommargin) { $properties['MARGIN-TOP'] -= $lastbottommargin; }
17312 else { $properties['MARGIN-TOP'] = 0; }
17313 }
17314 $table['margin']['T'] = $this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17315 }
17316
17317 if (isset($properties['MARGIN-BOTTOM'])) {
17318 $table['margin']['B'] = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17319 }
17320 if (isset($properties['MARGIN-LEFT'])) {
17321 $table['margin']['L'] = $this->ConvertSize($properties['MARGIN-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17322 }
17323
17324 if (isset($properties['MARGIN-RIGHT'])) {
17325 $table['margin']['R'] = $this->ConvertSize($properties['MARGIN-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17326 }
17327 if (isset($properties['MARGIN-LEFT']) && isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-LEFT'])=='auto' && strtolower($properties['MARGIN-RIGHT'])=='auto') {
17328 $table['a'] = 'C';
17329 }
17330 else if (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT'])=='auto') {
17331 $table['a'] = 'R';
17332 }
17333 else if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT'])=='auto') {
17334 $table['a'] = 'L';
17335 }
17336
17337 if (isset($properties['LINE-HEIGHT']) && $this->tableLevel==1) {
17338 $this->table_lineheight = $this->fixLineheight($properties['LINE-HEIGHT']);
17339 if (!$this->table_lineheight) { $this->table_lineheight = $this->normalLineheight; }
17340 }
17341
17342 if (isset($properties['BORDER-COLLAPSE']) && strtoupper($properties['BORDER-COLLAPSE'])=='SEPARATE') {
17343 $table['borders_separate'] = true;
17344 }
17345 else {
17346 $table['borders_separate'] = false;
17347 }
17348
17349 if (!$table['borders_separate']) { $table['border_spacing_H'] = $table['border_spacing_V'] = 0; }
17350 else if (isset($attr['CELLSPACING'])) {
17351 $table['border_spacing_H'] = $table['border_spacing_V'] = $this->ConvertSize($attr['CELLSPACING'],$this->blk[$this->blklvl]['inner_width']);
17352 }
17353 if (isset($properties['BORDER-SPACING-H'])) {
17354 $table['border_spacing_H'] = $this->ConvertSize($properties['BORDER-SPACING-H'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17355 }
17356 if (isset($properties['BORDER-SPACING-V'])) {
17357 $table['border_spacing_V'] = $this->ConvertSize($properties['BORDER-SPACING-V'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17358 }
17359
17360 if (isset($properties['EMPTY-CELLS'])) {
17361 $table['empty_cells'] = strtolower($properties['EMPTY-CELLS']); // 'hide' or 'show'
17362 }
17363 else { $table['empty_cells'] = ''; }
17364
17365 if (isset($properties['PAGE-BREAK-INSIDE']) && strtoupper($properties['PAGE-BREAK-INSIDE'])=='AVOID' && $this->tableLevel==1 && !$this->writingHTMLfooter) {
17366 $this->table_keep_together = true;
17367 }
17368 else if ($this->tableLevel==1) {
17369 $this->table_keep_together = false;
17370 }
17371 if (isset($properties['PAGE-BREAK-AFTER']) && $this->tableLevel==1) {
17372 $table['page_break_after'] = strtoupper($properties['PAGE-BREAK-AFTER']);
17373 }
17374
17375 /*-- BACKGROUNDS --*/
17376 if (isset($properties['BACKGROUND-GRADIENT']) && !$this->kwt && !$this->ColActive) { $table['gradient'] = $properties['BACKGROUND-GRADIENT']; }
17377
17378 if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->kwt && !$this->ColActive) {
17379 $ret = $this->SetBackground($properties, $currblk['inner_width']);
17380 if ($ret) { $table['background-image'] = $ret; }
17381 }
17382 /*-- END BACKGROUNDS --*/
17383
17384 if (isset($properties['OVERFLOW'])) {
17385 $table['overflow'] = strtolower($properties['OVERFLOW']); // 'hidden' 'wrap' or 'visible' or 'auto'
17386 if (($this->ColActive || $this->tableLevel>1) && $table['overflow']=='visible') { unset($table['overflow']); }
17387 }
17388
17389 $properties = array();
17390
17391
17392
17393 if (isset($attr['CELLPADDING'])) {
17394 $table['cell_padding'] = $attr['CELLPADDING'];
17395 }
17396 else {
17397 $table['cell_padding'] = false;
17398 }
17399
17400 if (isset($attr['BORDER']) && $attr['BORDER']=='1') { // mPDF 5.5.08
17401 $this->table_border_attr_set = 1; // mPDF 5.5.08
17402 $bord = $this->border_details('#000000 1px solid');
17403 if ($bord['s']) {
17404 $table['border'] = _BORDER_ALL;
17405 $table['border_details']['R'] = $bord;
17406 $table['border_details']['L'] = $bord;
17407 $table['border_details']['T'] = $bord;
17408 $table['border_details']['B'] = $bord;
17409 }
17410 }
17411 else {
17412 $this->table_border_attr_set = 0;
17413 }
17414
17415 if ($w) {
17416 $maxwidth = $this->blk[$this->blklvl]['inner_width'];
17417 if ($table['borders_separate']) {
17418 $tblblw = $table['margin']['L'] + $table['margin']['R'] + $table['border_details']['L']['w']/2 + $table['border_details']['R']['w']/2;
17419 }
17420 else {
17421 $tblblw = $table['margin']['L'] + $table['margin']['R'] + $table['max_cell_border_width']['L']/2 + $table['max_cell_border_width']['R']/2;
17422 }
17423 if (strpos($w,'%') && $this->tableLevel == 1 && !$this->ignore_table_percents ) {
17424 // % needs to be of inner box without table margins etc.
17425 $maxwidth -= $tblblw ;
17426 $wmm = $this->ConvertSize($w,$maxwidth,$this->FontSize,false);
17427 $table['w'] = $wmm + $tblblw ;
17428 }
17429 if (strpos($w,'%') && $this->tableLevel > 1 && !$this->ignore_table_percents && $this->keep_table_proportions) {
17430 $table['wpercent'] = $w + 0; // makes 80% -> 80
17431 }
17432 if (!strpos($w,'%') && !$this->ignore_table_widths ) {
17433 $wmm = $this->ConvertSize($w,$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17434 $table['w'] = $wmm + $tblblw ;
17435 }
17436 if (!$this->keep_table_proportions) {
17437 if (isset($table['w']) && $table['w'] > $this->blk[$this->blklvl]['inner_width']) { $table['w'] = $this->blk[$this->blklvl]['inner_width']; }
17438 }
17439 }
17440
17441 if (isset($attr['AUTOSIZE']) && $this->tableLevel==1) {
17442 $this->shrink_this_table_to_fit = $attr['AUTOSIZE'];
17443 if ($this->shrink_this_table_to_fit < 1) { $this->shrink_this_table_to_fit = 1; }
17444 }
17445 if (isset($attr['ROTATE']) && $this->tableLevel==1) {
17446 $this->table_rotate = $attr['ROTATE'];
17447 }
17448
17449 //++++++++++++++++++++++++++++
17450 // keeping block together on one page
17451 // Autosize is now forced therefore keep block together disabled
17452 if ($this->keep_block_together) {
17453 $this->keep_block_together = 0;
17454 $this->printdivbuffer();
17455 $this->blk[$this->blklvl]['keep_block_together'] = 0;
17456 }
17457 if ($this->table_rotate) {
17458 $this->tbrot_Links = array();
17459 $this->tbrot_Annots = array();
17460 $this->tbrotForms = array();
17461 $this->tbrot_Reference = array();
17462 $this->tbrot_BMoutlines = array();
17463 $this->tbrot_toc = array();
17464 }
17465
17466 if ($this->kwt) {
17467 if ($this->table_rotate) { $this->table_keep_together = true; }
17468 $this->kwt = false;
17469 $this->kwt_saved = true;
17470 }
17471
17472 if ($this->tableLevel==1 && $this->useGraphs) {
17473 if (isset($attr['ID']) && $attr['ID']) { $this->currentGraphId = strtoupper($attr['ID']); }
17474 else { $this->currentGraphId = '0'; }
17475 $this->graphs[$this->currentGraphId] = array();
17476 }
17477 //++++++++++++++++++++++++++++
17478 $this->plainCell_properties = array();
17479 unset($table);
17480 break;
17481
17482 case 'THEAD':
17483 $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
17484 $this->cssmgr->tbCSSlvl++;
17485 $this->tablethead = 1;
17486 $this->tabletfoot = 0;
17487 $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
17488 if (isset($properties['FONT-WEIGHT'])) {
17489 if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $this->thead_font_weight = 'B'; }
17490 else { $this->thead_font_weight = ''; }
17491 }
17492
17493 if (isset($properties['FONT-STYLE'])) {
17494 if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $this->thead_font_style = 'I'; }
17495 else { $this->thead_font_style = ''; }
17496 }
17497 if (isset($properties['FONT-VARIANT'])) {
17498 if (strtoupper($properties['FONT-VARIANT']) == 'SMALL-CAPS') { $this->thead_font_smCaps = 'S'; }
17499 else { $this->thead_font_smCaps = ''; }
17500 }
17501
17502 if (isset($properties['VERTICAL-ALIGN'])) {
17503 $this->thead_valign_default = $properties['VERTICAL-ALIGN'];
17504 }
17505 if (isset($properties['TEXT-ALIGN'])) {
17506 $this->thead_textalign_default = $properties['TEXT-ALIGN'];
17507 }
17508 $properties = array();
17509 break;
17510
17511 case 'TFOOT':
17512 $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
17513 $this->cssmgr->tbCSSlvl++;
17514 $this->tabletfoot = 1;
17515 $this->tablethead = 0;
17516 $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
17517 if (isset($properties['FONT-WEIGHT'])) {
17518 if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $this->tfoot_font_weight = 'B'; }
17519 else { $this->tfoot_font_weight = ''; }
17520 }
17521
17522 if (isset($properties['FONT-STYLE'])) {
17523 if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $this->tfoot_font_style = 'I'; }
17524 else { $this->tfoot_font_style = ''; }
17525 }
17526 if (isset($properties['FONT-VARIANT'])) {
17527 if (strtoupper($properties['FONT-VARIANT']) == 'SMALL-CAPS') { $this->tfoot_font_smCaps = 'S'; }
17528 else { $this->tfoot_font_smCaps = ''; }
17529 }
17530
17531 if (isset($properties['VERTICAL-ALIGN'])) {
17532 $this->tfoot_valign_default = $properties['VERTICAL-ALIGN'];
17533 }
17534 if (isset($properties['TEXT-ALIGN'])) {
17535 $this->tfoot_textalign_default = $properties['TEXT-ALIGN'];
17536 }
17537 $properties = array();
17538 break;
17539
17540
17541 case 'TBODY':
17542 $this->tablethead = 0;
17543 $this->tabletfoot = 0;
17544 $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
17545 $this->cssmgr->tbCSSlvl++;
17546 $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
17547 break;
17548
17549
17550 case 'TR':
17551 $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
17552 $this->cssmgr->tbCSSlvl++;
17553 $this->row++;
17554 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr']++;
17555 $this->col = -1;
17556 $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
17557
17558 if (!$this->simpleTables && (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['borders_separate']) || !$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['borders_separate'])) {
17559 if (isset($properties['BORDER-LEFT']) && $properties['BORDER-LEFT']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-left'][$this->row] = $properties['BORDER-LEFT']; }
17560 if (isset($properties['BORDER-RIGHT']) && $properties['BORDER-RIGHT']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-right'][$this->row] = $properties['BORDER-RIGHT']; }
17561 if (isset($properties['BORDER-TOP']) && $properties['BORDER-TOP']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-top'][$this->row] = $properties['BORDER-TOP']; }
17562 if (isset($properties['BORDER-BOTTOM']) && $properties['BORDER-BOTTOM']) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-bottom'][$this->row] = $properties['BORDER-BOTTOM']; }
17563 }
17564
17565 if (isset($properties['BACKGROUND-COLOR'])) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$this->row] = $properties['BACKGROUND-COLOR']; }
17566 else if (isset($attr['BGCOLOR'])) $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$this->row] = $attr['BGCOLOR'];
17567
17568 /*-- BACKGROUNDS --*/
17569 if (isset($properties['BACKGROUND-GRADIENT']) && !$this->kwt && !$this->ColActive) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'][$this->row] = $properties['BACKGROUND-GRADIENT']; }
17570
17571 if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->kwt && !$this->ColActive) {
17572 $ret = $this->SetBackground($properties, $currblk['inner_width']);
17573 if ($ret) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'][$this->row] = $ret; }
17574 }
17575 /*-- END BACKGROUNDS --*/
17576
17577
17578 if (isset($properties['TEXT-ROTATE'])) {
17579 $this->trow_text_rotate = $properties['TEXT-ROTATE'];
17580 }
17581 if (isset($attr['TEXT-ROTATE'])) $this->trow_text_rotate = $attr['TEXT-ROTATE'];
17582
17583 if ($this->tablethead) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_thead'][$this->row] = true; }
17584 if ($this->tabletfoot) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'][$this->row] = true; }
17585 $properties = array();
17586 break;
17587
17588
17589 case 'TH':
17590 case 'TD':
17591 $this->ignorefollowingspaces = true;
17592 $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
17593 $this->cssmgr->tbCSSlvl++;
17594 $this->InlineProperties = array();
17595 $this->spanlvl = 0;
17596 $this->tdbegin = true;
17597 $this->col++;
17598 while (isset($this->cell[$this->row][$this->col])) { $this->col++; }
17599
17600 //Update number column
17601 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; }
17602
17603 $table = &$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]];
17604
17605 $c = array('a' => false,
17606 'R' => false,
17607 'nowrap' => false,
17608 'bgcolor' => false,
17609 'padding' => array('L' => false,
17610 'R' => false,
17611 'T' => false,
17612 'B' => false
17613 )
17614 );
17615
17616 if ($this->simpleTables && $this->row==0 && $this->col==0){
17617 $table['simple']['border'] = false;
17618 $table['simple']['border_details']['R']['w'] = 0;
17619 $table['simple']['border_details']['L']['w'] = 0;
17620 $table['simple']['border_details']['T']['w'] = 0;
17621 $table['simple']['border_details']['B']['w'] = 0;
17622 $table['simple']['border_details']['R']['style'] = '';
17623 $table['simple']['border_details']['L']['style'] = '';
17624 $table['simple']['border_details']['T']['style'] = '';
17625 $table['simple']['border_details']['B']['style'] = '';
17626 }
17627 else if (!$this->simpleTables) {
17628 $c['border'] = false;
17629 $c['border_details']['R']['w'] = 0;
17630 $c['border_details']['L']['w'] = 0;
17631 $c['border_details']['T']['w'] = 0;
17632 $c['border_details']['B']['w'] = 0;
17633 $c['border_details']['mbw']['BL'] = 0;
17634 $c['border_details']['mbw']['BR'] = 0;
17635 $c['border_details']['mbw']['RT'] = 0;
17636 $c['border_details']['mbw']['RB'] = 0;
17637 $c['border_details']['mbw']['TL'] = 0;
17638 $c['border_details']['mbw']['TR'] = 0;
17639 $c['border_details']['mbw']['LT'] = 0;
17640 $c['border_details']['mbw']['LB'] = 0;
17641 $c['border_details']['R']['style'] = '';
17642 $c['border_details']['L']['style'] = '';
17643 $c['border_details']['T']['style'] = '';
17644 $c['border_details']['B']['style'] = '';
17645 $c['border_details']['R']['s'] = 0;
17646 $c['border_details']['L']['s'] = 0;
17647 $c['border_details']['T']['s'] = 0;
17648 $c['border_details']['B']['s'] = 0;
17649 $c['border_details']['R']['c'] = $this->ConvertColor(0);
17650 $c['border_details']['L']['c'] = $this->ConvertColor(0);
17651 $c['border_details']['T']['c'] = $this->ConvertColor(0);
17652 $c['border_details']['B']['c'] = $this->ConvertColor(0);
17653 $c['border_details']['R']['dom'] = 0;
17654 $c['border_details']['L']['dom'] = 0;
17655 $c['border_details']['T']['dom'] = 0;
17656 $c['border_details']['B']['dom'] = 0;
17657 }
17658
17659
17660 if ($table['va']) { $c['va'] = $table['va']; }
17661 if ($table['txta']) { $c['a'] = $table['txta']; }
17662 if ($this->table_border_attr_set) {
17663 if ($table['border_details']) {
17664 if (!$this->simpleTables){
17665 $c['border_details']['R'] = $table['border_details']['R'];
17666 $c['border_details']['L'] = $table['border_details']['L'];
17667 $c['border_details']['T'] = $table['border_details']['T'];
17668 $c['border_details']['B'] = $table['border_details']['B'];
17669 $c['border'] = $table['border'];
17670 $c['border_details']['L']['dom'] = 1;
17671 $c['border_details']['R']['dom'] = 1;
17672 $c['border_details']['T']['dom'] = 1;
17673 $c['border_details']['B']['dom'] = 1;
17674 }
17675 else if ($this->simpleTables && $this->row==0 && $this->col==0){
17676 $table['simple']['border_details']['R'] = $table['border_details']['R'];
17677 $table['simple']['border_details']['L'] = $table['border_details']['L'];
17678 $table['simple']['border_details']['T'] = $table['border_details']['T'];
17679 $table['simple']['border_details']['B'] = $table['border_details']['B'];
17680 $table['simple']['border'] = $table['border'];
17681 }
17682 }
17683 }
17684 // INHERITED THEAD CSS Properties
17685 if ($this->tablethead) {
17686 if ($this->thead_valign_default) $c['va'] = $align[strtolower($this->thead_valign_default)];
17687 if ($this->thead_textalign_default) $c['a'] = $align[strtolower($this->thead_textalign_default)];
17688 if ($this->thead_font_weight == 'B') { $this->SetStyle('B',true); }
17689 if ($this->thead_font_style == 'I') { $this->SetStyle('I',true); }
17690 if ($this->thead_font_smCaps == 'S') { $this->SetStyle('S',true); }
17691 }
17692
17693 // INHERITED TFOOT CSS Properties
17694 if ($this->tabletfoot) {
17695 if ($this->tfoot_valign_default) $c['va'] = $align[strtolower($this->tfoot_valign_default)];
17696 if ($this->tfoot_textalign_default) $c['a'] = $align[strtolower($this->tfoot_textalign_default)];
17697 if ($this->tfoot_font_weight == 'B') { $this->SetStyle('B',true); }
17698 if ($this->tfoot_font_style == 'I') { $this->SetStyle('I',true); }
17699 if ($this->tfoot_font_style == 'S') { $this->SetStyle('S',true); }
17700 }
17701
17702
17703 if ($this->trow_text_rotate){
17704 $c['R'] = $this->trow_text_rotate;
17705 }
17706
17707 $this->cell_border_dominance_L = 0;
17708 $this->cell_border_dominance_R = 0;
17709 $this->cell_border_dominance_T = 0;
17710 $this->cell_border_dominance_B = 0;
17711
17712 $properties = $this->cssmgr->MergeCSS('TABLE',$tag,$attr);
17713 $properties = $this->cssmgr->array_merge_recursive_unique($this->base_table_properties, $properties);
17714
17715 if (isset($properties['FONT-KERNING']) && (strtoupper($properties['FONT-KERNING'])=='NORMAL' || strtoupper($properties['FONT-KERNING'])=='AUTO')) {
17716 $this->kerning = true;
17717 }
17718 else { $this->kerning = false; }
17719
17720 if (isset($properties['LETTER-SPACING']) && ($properties['LETTER-SPACING'] || $properties['LETTER-SPACING']==='0') && strtoupper($properties['LETTER-SPACING']) != 'NORMAL') {
17721 $this->lSpacingCSS = strtoupper($properties['LETTER-SPACING']);
17722 $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize);
17723 }
17724 else {
17725 $this->lSpacingCSS = '';
17726 $this->fixedlSpacing = false;
17727 }
17728 if (isset($properties['WORD-SPACING']) && strtoupper($properties['WORD-SPACING']) != 'NORMAL') {
17729 $this->wSpacingCSS = strtoupper($properties['WORD-SPACING']);
17730 $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize);
17731 }
17732 else {
17733 $this->minwSpacing = 0;
17734 $this->wSpacingCSS = '';
17735 }
17736 // mPDF 5.6.08
17737 if (isset($properties['HYPHENS']) && $properties['HYPHENS']) {
17738 if (strtoupper($properties['HYPHENS']) == 'NONE') { $this->textparam['hyphens'] = 2; }
17739 else if (strtoupper($properties['HYPHENS']) == 'AUTO') { $this->textparam['hyphens'] = 1; }
17740 else if (strtoupper($properties['HYPHENS']) == 'MANUAL') { $this->textparam['hyphens'] = 0; }
17741 }
17742
17743 if (isset($properties['BACKGROUND-COLOR'])) { $c['bgcolor'] = $properties['BACKGROUND-COLOR']; }
17744 else if (isset($properties['BACKGROUND'])) { $c['bgcolor'] = $properties['BACKGROUND']; }
17745 else if (isset($attr['BGCOLOR'])) $c['bgcolor'] = $attr['BGCOLOR'];
17746
17747
17748
17749 /*-- BACKGROUNDS --*/
17750 if (isset($properties['BACKGROUND-GRADIENT'])) { $c['gradient'] = $properties['BACKGROUND-GRADIENT']; }
17751 else { $c['gradient'] = false; }
17752
17753 if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE'] && !$this->keep_block_together) {
17754 $ret = $this->SetBackground($properties, $this->blk[$this->blklvl]['inner_width']);
17755 if ($ret) { $c['background-image'] = $ret; }
17756 }
17757 /*-- END BACKGROUNDS --*/
17758 if (isset($properties['VERTICAL-ALIGN'])) { $c['va']=$align[strtolower($properties['VERTICAL-ALIGN'])]; }
17759 else if (isset($attr['VALIGN'])) $c['va'] = $align[strtolower($attr['VALIGN'])];
17760
17761
17762 // mPDF 5.6.13
17763 if (isset($properties['TEXT-ALIGN']) && $properties['TEXT-ALIGN']) {
17764 if (substr($properties['TEXT-ALIGN'],0,1)=='D') { $c['a'] = $properties['TEXT-ALIGN']; }
17765 else { $c['a'] = $align[strtolower($properties['TEXT-ALIGN'])]; }
17766 }
17767 // mPDF 5.6.13
17768 if (isset($attr['ALIGN']) && $attr['ALIGN']) {
17769 if (strtolower($attr['ALIGN']) == 'char') {
17770 if (isset($attr['CHAR']) && $attr['CHAR']) {
17771 $char = html_entity_decode($attr['CHAR']);
17772 $char = strcode2utf($char);
17773 $d = array_search($char,$this->decimal_align);
17774 if ($d !== false) { $c['a'] = $d.'R'; }
17775 }
17776 else { $c['a'] = 'DPR'; }
17777 }
17778 else { $c['a'] = $align[strtolower($attr['ALIGN'])]; }
17779 }
17780
17781 if (!$c['a']) {
17782 if (isset($table['direction']) && $table['direction'] == 'rtl' ) { $c['a'] = 'R'; }
17783 else { $c['a'] = 'L'; }
17784 }
17785
17786
17787 if (isset($properties['TEXT-ROTATE']) && ($properties['TEXT-ROTATE'] || $properties['TEXT-ROTATE']==="0")){
17788 $c['R'] = $properties['TEXT-ROTATE'];
17789 }
17790 if (isset($properties['BORDER'])) {
17791 $bord = $this->border_details($properties['BORDER']);
17792 if ($bord['s']) {
17793 if (!$this->simpleTables){
17794 $c['border'] = _BORDER_ALL;
17795 $c['border_details']['R'] = $bord;
17796 $c['border_details']['L'] = $bord;
17797 $c['border_details']['T'] = $bord;
17798 $c['border_details']['B'] = $bord;
17799 $c['border_details']['L']['dom'] = $this->cell_border_dominance_L;
17800 $c['border_details']['R']['dom'] = $this->cell_border_dominance_R;
17801 $c['border_details']['T']['dom'] = $this->cell_border_dominance_T;
17802 $c['border_details']['B']['dom'] = $this->cell_border_dominance_B;
17803 }
17804 else if ($this->simpleTables && $this->row==0 && $this->col==0){
17805 $table['simple']['border'] = _BORDER_ALL;
17806 $table['simple']['border_details']['R'] = $bord;
17807 $table['simple']['border_details']['L'] = $bord;
17808 $table['simple']['border_details']['T'] = $bord;
17809 $table['simple']['border_details']['B'] = $bord;
17810 }
17811 }
17812 }
17813 if (!$this->simpleTables){
17814 if (isset($properties['BORDER-RIGHT']) && $properties['BORDER-RIGHT']) {
17815 $c['border_details']['R'] = $this->border_details($properties['BORDER-RIGHT']);
17816 $this->setBorder($c['border'], _BORDER_RIGHT, $c['border_details']['R']['s']);
17817 $c['border_details']['R']['dom'] = $this->cell_border_dominance_R;
17818 }
17819 if (isset($properties['BORDER-LEFT']) && $properties['BORDER-LEFT']) {
17820 $c['border_details']['L'] = $this->border_details($properties['BORDER-LEFT']);
17821 $this->setBorder($c['border'], _BORDER_LEFT, $c['border_details']['L']['s']);
17822 $c['border_details']['L']['dom'] = $this->cell_border_dominance_L;
17823 }
17824 if (isset($properties['BORDER-BOTTOM']) && $properties['BORDER-BOTTOM']) {
17825 $c['border_details']['B'] = $this->border_details($properties['BORDER-BOTTOM']);
17826 $this->setBorder($c['border'], _BORDER_BOTTOM, $c['border_details']['B']['s']);
17827 $c['border_details']['B']['dom'] = $this->cell_border_dominance_B;
17828 }
17829 if (isset($properties['BORDER-TOP']) && $properties['BORDER-TOP']) {
17830 $c['border_details']['T'] = $this->border_details($properties['BORDER-TOP']);
17831 $this->setBorder($c['border'], _BORDER_TOP, $c['border_details']['T']['s']);
17832 $c['border_details']['T']['dom'] = $this->cell_border_dominance_T;
17833 }
17834 }
17835 else if ($this->simpleTables && $this->row==0 && $this->col==0){
17836 if (isset($properties['BORDER-LEFT']) && $properties['BORDER-LEFT']) {
17837 $bord = $this->border_details($properties['BORDER-LEFT']);
17838 if ($bord['s']) { $table['simple']['border'] = _BORDER_ALL; }
17839 else { $table['simple']['border'] = 0; }
17840 $table['simple']['border_details']['R'] = $bord;
17841 $table['simple']['border_details']['L'] = $bord;
17842 $table['simple']['border_details']['T'] = $bord;
17843 $table['simple']['border_details']['B'] = $bord;
17844 }
17845 }
17846
17847 if ($this->simpleTables && $this->row==0 && $this->col==0 && !$table['borders_separate'] && $table['simple']['border'] ){
17848 $table['border_details'] = $table['simple']['border_details'];
17849 $table['border'] = $table['simple']['border'];
17850 }
17851
17852 // Border set on TR (if collapsed only)
17853 if (!$table['borders_separate'] && !$this->simpleTables && isset($table['trborder-left'][$this->row])) {
17854 if ($this->col==0) {
17855 $left = $this->border_details($table['trborder-left'][$this->row]);
17856 $c['border_details']['L'] = $left;
17857 $this->setBorder($c['border'], _BORDER_LEFT, $c['border_details']['L']['s']);
17858 }
17859 $c['border_details']['B'] = $this->border_details($table['trborder-bottom'][$this->row]);
17860 $this->setBorder($c['border'], _BORDER_BOTTOM, $c['border_details']['B']['s']);
17861 $c['border_details']['T'] = $this->border_details($table['trborder-top'][$this->row]);
17862 $this->setBorder($c['border'], _BORDER_TOP, $c['border_details']['T']['s']);
17863 }
17864
17865 if ($this->packTableData && !$this->simpleTables) {
17866 $c['borderbin'] = $this->_packCellBorder($c);
17867 unset($c['border']);
17868 unset($c['border_details']);
17869 }
17870
17871 if (isset($properties['PADDING-LEFT'])) {
17872 $c['padding']['L'] = $this->ConvertSize($properties['PADDING-LEFT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17873 }
17874 if (isset($properties['PADDING-RIGHT'])) {
17875 $c['padding']['R'] = $this->ConvertSize($properties['PADDING-RIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17876 }
17877 if (isset($properties['PADDING-BOTTOM'])) {
17878 $c['padding']['B'] = $this->ConvertSize($properties['PADDING-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17879 }
17880 if (isset($properties['PADDING-TOP'])) {
17881 $c['padding']['T'] = $this->ConvertSize($properties['PADDING-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17882 }
17883
17884 $w = '';
17885 if (isset($properties['WIDTH'])) { $w = $properties['WIDTH']; }
17886 else if (isset($attr['WIDTH'])) { $w = $attr['WIDTH']; }
17887 if ($w) {
17888 if (strpos($w,'%') && !$this->ignore_table_percents ) { $c['wpercent'] = $w + 0; } // makes 80% -> 80
17889 else if (!strpos($w,'%') && !$this->ignore_table_widths ) { $c['w'] = $this->ConvertSize($w,$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17890 }
17891
17892 if (isset($properties['HEIGHT']) && !strpos($properties['HEIGHT'],'%')) { $c['h'] = $this->ConvertSize($properties['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
17893 else if (isset($attr['HEIGHT']) && !strpos($attr['HEIGHT'],'%')) $c['h'] = $this->ConvertSize($attr['HEIGHT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
17894
17895
17896 if (isset($properties['COLOR'])) {
17897 $cor = $this->ConvertColor($properties['COLOR']);
17898 if ($cor) {
17899 $this->colorarray = $cor;
17900 $this->SetTColor($cor);
17901 }
17902 }
17903 if (isset($properties['FONT-FAMILY'])) {
17904 $this->SetFont($properties['FONT-FAMILY'],'',0,false);
17905 }
17906 if (isset($properties['FONT-SIZE'])) {
17907 $mmsize = $this->ConvertSize($properties['FONT-SIZE'],$this->default_font_size/_MPDFK);
17908 if ($mmsize) {
17909 $this->SetFontSize($mmsize*(_MPDFK),false);
17910 }
17911 }
17912 $c['dfs'] = $this->FontSize; // Default Font size
17913 if (isset($properties['FONT-WEIGHT'])) {
17914 if (strtoupper($properties['FONT-WEIGHT']) == 'BOLD') { $this->SetStyle('B',true); }
17915 }
17916 if (isset($properties['FONT-STYLE'])) {
17917 if (strtoupper($properties['FONT-STYLE']) == 'ITALIC') { $this->SetStyle('I',true); }
17918 }
17919 if (isset($properties['FONT-VARIANT'])) {
17920 if (strtoupper($properties['FONT-VARIANT']) == 'SMALL-CAPS') { $this->SetStyle('S',true); }
17921 }
17922 if (isset($properties['TEXT-DECORATION'])) {
17923 if (strtoupper($properties['TEXT-DECORATION']) == 'LINE-THROUGH') { $this->strike = true; }
17924 else if (strtoupper($properties['TEXT-DECORATION']) == 'UNDERLINE') { $this->SetStyle('U',true); }
17925 }
17926 if (isset($properties['TEXT-SHADOW'])) {
17927 $ts = $this->cssmgr->setCSStextshadow($properties['TEXT-SHADOW']);
17928 if ($ts) { $this->textshadow = $ts; }
17929 }
17930 if (isset($properties['TEXT-TRANSFORM'])) {
17931 if (strtoupper($properties['TEXT-TRANSFORM']) == 'CAPITALIZE') { $this->capitalize = true; }
17932 else if (strtoupper($properties['TEXT-TRANSFORM']) == 'UPPERCASE') { $this->toupper = true; }
17933 else if (strtoupper($properties['TEXT-TRANSFORM']) == 'LOWERCASE') { $this->tolower = true; }
17934 }
17935 if (isset($properties['WHITE-SPACE'])) {
17936 if (strtoupper($properties['WHITE-SPACE']) == 'NOWRAP') { $c['nowrap']= 1; }
17937 }
17938 $properties = array();
17939
17940 if (isset($attr['TEXT-ROTATE'])) {
17941 $c['R'] = $attr['TEXT-ROTATE'];
17942 }
17943 if (isset($attr['NOWRAP']) && $attr['NOWRAP']) $c['nowrap']= 1;
17944
17945 $this->cell[$this->row][$this->col] = $c;
17946 unset($c);
17947 $this->cell[$this->row][$this->col]['s'] = 0 ;
17948
17949 $cs = $rs = 1;
17950 if (isset($attr['COLSPAN']) && $attr['COLSPAN']>1) $cs = $this->cell[$this->row][$this->col]['colspan'] = $attr['COLSPAN'];
17951 if ($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'] < $this->col+$cs) {
17952 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nc'] = $this->col+$cs;
17953 } // following code moved outside if...
17954 for($l=$this->col; $l < $this->col+$cs ;$l++) {
17955 if ($l-$this->col) $this->cell[$this->row][$l] = 0;
17956 }
17957 if (isset($attr['ROWSPAN']) && $attr['ROWSPAN']>1) $rs = $this->cell[$this->row][$this->col]['rowspan'] = $attr['ROWSPAN'];
17958 for ($k=$this->row ; $k < $this->row+$rs ;$k++) {
17959 for($l=$this->col; $l < $this->col+$cs ;$l++) {
17960 if ($k-$this->row || $l-$this->col) $this->cell[$k][$l] = 0;
17961 }
17962 }
17963 unset($table);
17964 break;
17965 /*-- END TABLES --*/
17966
17967
17968 /*-- LISTS --*/
17969 // *********** LISTS ********************
17970 case 'OL':
17971 case 'UL':
17972 $this->listjustfinished = false;
17973
17974 if ($this->blockjustfinished && !count($this->textbuffer) && $this->y != $this->tMargin && $this->collapseBlockMargins) { $lastbottommargin = $this->lastblockbottommargin; }
17975 else { $lastbottommargin = 0; }
17976 $this->lastblockbottommargin = 0;
17977 $this->blockjustfinished=false;
17978
17979 $this->linebreakjustfinished=false;
17980 $this->lastoptionaltag = ''; // Save current HTML specified optional endtag
17981 $this->cssmgr->listCSSlvl++;
17982 if((!$this->tableLevel) && ($this->listlvl == 0)) {
17983 $blockstate = 0;
17984 //if ($this->lastblocklevelchange == 1) { $blockstate = -1; } // Top margins/padding only
17985 //else if ($this->lastblocklevelchange < 1) { $blockstate = 0; } // NO margins/padding
17986 // called from block after new div e.g. <div> ... <ol> ... Outputs block top margin/border and padding
17987 if (count($this->textbuffer) == 0 && $this->lastblocklevelchange == 1 && !$this->tableLevel && !$this->kwt) {
17988 $this->newFlowingBlock( $this->blk[$this->blklvl]['width'],$this->lineheight,'',false,false,1,true, $this->blk[$this->blklvl]['direction']);
17989 $this->finishFlowingBlock(true); // true = END of flowing block
17990 }
17991 else if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer,$blockstate); }
17992 $this->textbuffer=array();
17993 $this->lastblocklevelchange = -1;
17994 }
17995 // ol and ul types are mixed here
17996 if ($this->listlvl == 0) {
17997 $this->list_indent = array();
17998 $this->list_align = array();
17999 $this->list_lineheight = array();
18000 $this->InlineProperties['LIST'] = array();
18001 $this->InlineProperties['LISTITEM'] = array();
18002 }
18003
18004 /*-- TABLES --*/
18005 // A simple list for inside a table
18006 if($this->tableLevel) {
18007 $this->list_indent[$this->listlvl] = 0; // mm default indent for each level
18008 if ($tag == 'OL') $this->listtype = '1';
18009 else if ($tag == 'UL') $this->listtype = 'disc';
18010 if ($this->listlvl > 0) {
18011 $this->listlist[$this->listlvl]['MAXNUM'] = $this->listnum; //save previous lvl's maxnum
18012 }
18013 $this->listlvl++;
18014 // mPDF 5.6.15
18015 if (isset($attr['START'])) { $this->listnum = intval($attr['START']); }
18016 else { $this->listnum = 0; }
18017 $this->listlist[$this->listlvl] = array('TYPE'=>$this->listtype,'MAXNUM'=>$this->listnum);
18018 break;
18019 }
18020 /*-- END TABLES --*/
18021
18022
18023 if (($this->PDFA || $this->PDFX) && $tag == 'UL') {
18024 if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "List bullets cannot use core font Zapfdingbats in PDFA1-b or PDFX/1-a. (Substitute characters from current font used if available, otherwise substitutes hyphen '-')"; }
18025 }
18026
18027 if ($this->cssmgr->listCSSlvl==1) {
18028 $properties = $this->cssmgr->MergeCSS('TOPLIST',$tag,$attr);
18029 }
18030 else {
18031 $properties = $this->cssmgr->MergeCSS('LIST',$tag,$attr);
18032 }
18033 if (!empty($properties)) $this->setCSS($properties,'LIST');
18034 // List-type
18035
18036 $this->listtype = '';
18037 if (isset($properties['LIST-STYLE-TYPE'])) {
18038 $this->listtype = $this->_getListStyle($properties['LIST-STYLE-TYPE']);
18039 }
18040 else if (isset($properties['LIST-STYLE'])) {
18041 $this->listtype = $this->_getListStyle($properties['LIST-STYLE']);
18042 }
18043 else if (isset($attr['TYPE']) && $attr['TYPE']) { $this->listtype = $attr['TYPE']; }
18044 if (!$this->listtype) {
18045 if ($tag == 'OL') $this->listtype = '1';
18046 if ($tag == 'UL') {
18047 if ($this->listlvl % 3 == 0) $this->listtype = 'disc';
18048 elseif ($this->listlvl % 3 == 1) $this->listtype = 'circle';
18049 else $this->listtype = 'square';
18050 }
18051 }
18052 if ($this->listlvl == 0) {
18053 $this->inherit_lineheight = 0;
18054 $this->listlvl++; // first depth level
18055 // mPDF 5.6.15
18056 if (isset($attr['START'])) { $this->listnum = intval($attr['START']); }
18057 else { $this->listnum = 0; }
18058 $this->listDir = (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : null);
18059 $occur = $this->listoccur[$this->listlvl] = 1;
18060 $this->listlist[$this->listlvl][1] = array('TYPE'=>$this->listtype,'MAXNUM'=>$this->listnum);
18061 }
18062 else {
18063 if (!empty($this->textbuffer))
18064 {
18065 $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl],$this->listitemtype);
18066 $this->listnum++;
18067 }
18068 // Save current lineheight to inherit
18069 $this->textbuffer = array();
18070 $occur = $this->listoccur[$this->listlvl];
18071 $this->listlist[$this->listlvl][$occur]['MAXNUM'] = $this->listnum; //save previous lvl's maxnum
18072 $this->listlvl++;
18073 // mPDF 5.6.15
18074 if (isset($attr['START'])) { $this->listnum = intval($attr['START']); }
18075 else { $this->listnum = 0; }
18076
18077
18078 if (!isset($this->listoccur[$this->listlvl]) || $this->listoccur[$this->listlvl] == 0) $this->listoccur[$this->listlvl] = 1;
18079 else $this->listoccur[$this->listlvl]++;
18080 $occur = $this->listoccur[$this->listlvl];
18081 $this->listlist[$this->listlvl][$occur] = array('TYPE'=>$this->listtype,'MAXNUM'=>$this->listnum);
18082 }
18083
18084
18085 // TOP LEVEL ONLY
18086 if ($this->listlvl == 1) {
18087 if (isset($properties['MARGIN-TOP'])) {
18088 if ($lastbottommargin) {
18089 $tmp = $this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18090 if ($tmp > $lastbottommargin) { $properties['MARGIN-TOP'] -= $lastbottommargin; }
18091 else { $properties['MARGIN-TOP'] = 0; }
18092 }
18093 $this->DivLn($this->ConvertSize($properties['MARGIN-TOP'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false),$this->blklvl,true,1); // collapsible
18094 }
18095 if (isset($properties['MARGIN-BOTTOM'])) {
18096 $this->list_margin_bottom = $this->ConvertSize($properties['MARGIN-BOTTOM'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false);
18097 }
18098
18099 if (isset($this->blk[$this->blklvl]['line_height'])) {
18100 $this->list_lineheight[$this->listlvl][$occur] = $this->blk[$this->blklvl]['line_height'];
18101 }
18102
18103 if (isset($properties['DIRECTION']) && $properties['DIRECTION']) { $this->listDir = strtolower($properties['DIRECTION']); }
18104 else if (isset($attr['DIR']) && $attr['DIR']) { $this->listDir = strtolower($attr['DIR']); }
18105
18106 }
18107 $this->list_indent[$this->listlvl][$occur] = 5; // mm default indent for each level
18108 if (isset($properties['TEXT-INDENT'])) { $this->list_indent[$this->listlvl][$occur] = $this->ConvertSize($properties['TEXT-INDENT'],$this->blk[$this->blklvl]['inner_width'],$this->FontSize,false); }
18109
18110 if (isset($properties['TEXT-ALIGN'])) {
18111 $this->list_align[$this->listlvl][$occur] = $align[strtolower($properties['TEXT-ALIGN'])];
18112 }
18113
18114
18115 if (isset($properties['LINE-HEIGHT'])) {
18116 $this->list_lineheight[$this->listlvl][$occur] = $this->fixLineheight($properties['LINE-HEIGHT']);
18117 }
18118 else if ($this->listlvl>1 && isset($this->list_lineheight[($this->listlvl - 1)][1])) {
18119 $this->list_lineheight[$this->listlvl][$occur] = end($this->list_lineheight[($this->listlvl - 1)]);
18120 }
18121 if (!isset($this->list_lineheight[$this->listlvl][$occur]) || !$this->list_lineheight[$this->listlvl][$occur]) {
18122 $this->list_lineheight[$this->listlvl][$occur] = $this->normalLineheight;
18123 }
18124
18125 $this->InlineProperties['LIST'][$this->listlvl][$occur] = $this->saveInlineProperties();
18126 $properties = array();
18127 break;
18128
18129
18130
18131 case 'LI':
18132 // Start Block
18133 $this->lastoptionaltag = $tag; // Save current HTML specified optional endtag
18134 $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
18135 /*-- TABLES --*/
18136 // A simple list for inside a table
18137 if($this->tableLevel) {
18138 $this->blockjustfinished=false;
18139
18140 // If already something in the Cell
18141 if ((isset($this->cell[$this->row][$this->col]['maxs']) && $this->cell[$this->row][$this->col]['maxs'] > 0 ) || $this->cell[$this->row][$this->col]['s'] > 0 ) {
18142 $this->_saveCellTextBuffer("\n");
18143 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
18144 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
18145 }
18146 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
18147 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
18148 }
18149 $this->cell[$this->row][$this->col]['s'] = 0 ;
18150 }
18151 if ($this->listlvl == 0) { //in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...)
18152 $this->listlvl++; // first depth level
18153 $this->listnum = 0; // reset
18154 $this->listlist[$this->listlvl] = array('TYPE'=>'disc','MAXNUM'=>$this->listnum);
18155 }
18156
18157 $this->listnum++;
18158 switch($this->listlist[$this->listlvl]['TYPE']) {
18159 case 'A':
18160 $blt = $this->dec2alpha($this->listnum,true).$this->list_number_suffix;
18161 break;
18162 case 'a':
18163 $blt = $this->dec2alpha($this->listnum,false).$this->list_number_suffix;
18164 break;
18165 case 'I':
18166 $blt = $this->dec2roman($this->listnum,true).$this->list_number_suffix;
18167 break;
18168 case 'i':
18169 $blt = $this->dec2roman($this->listnum,false).$this->list_number_suffix;
18170 break;
18171 case '1':
18172 $blt = $this->listnum.$this->list_number_suffix;
18173 break;
18174 default:
18175 if ($this->listlvl % 3 == 1 && $this->_charDefined($this->CurrentFont['cw'],8226)) { $blt = "\xe2\x80\xa2"; } // &#8226;
18176 else if ($this->listlvl % 3 == 2 && $this->_charDefined($this->CurrentFont['cw'],9900)) { $blt = "\xe2\x9a\xac"; } // &#9900;
18177 else if ($this->listlvl % 3 == 0 && $this->_charDefined($this->CurrentFont['cw'],9642)) { $blt = "\xe2\x96\xaa"; } // &#9642;
18178 else { $blt = '-'; }
18179 break;
18180 }
18181
18182 // change to &nbsp; spaces
18183 if ($this->usingCoreFont) {
18184 $ls = str_repeat(chr(160).chr(160),($this->listlvl-1)*2) . $blt . ' ';
18185 }
18186 else {
18187 $ls = str_repeat("\xc2\xa0\xc2\xa0",($this->listlvl-1)*2) . $blt . ' ';
18188 }
18189
18190 $this->_saveCellTextBuffer($ls, $this->HREF);
18191 $this->cell[$this->row][$this->col]['s'] += $this->GetStringWidth($ls);
18192 break;
18193 }
18194 /*-- END TABLES --*/
18195 //Observation: </LI> is ignored
18196 if ($this->listlvl == 0) { //in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...)
18197 //First of all, skip a line
18198 $this->listlvl++; // first depth level
18199 $this->listnum = 0; // reset
18200 $this->listoccur[$this->listlvl] = 1;
18201 $this->listlist[$this->listlvl][1] = array('TYPE'=>'disc','MAXNUM'=>$this->listnum);
18202 }
18203 if ($this->listnum == 0) {
18204 $this->listnum++;
18205 $this->textbuffer = array();
18206 }
18207 else {
18208 if (!empty($this->textbuffer)) {
18209 if (!$this->listjustfinished) {
18210 $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl],$this->listitemtype);
18211 $this->listnum++;
18212 }
18213 else {
18214 $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl],$this->listitemtype, true);
18215 }
18216 }
18217 $this->textbuffer = array();
18218 }
18219 $this->listjustfinished = false;
18220
18221 $this->cssmgr->listCSSlvl++;
18222 $properties = $this->cssmgr->MergeCSS('LIST',$tag,$attr);
18223 if (!empty($properties)) $this->setCSS($properties,'LIST');
18224 $this->InlineProperties['LISTITEM'][$this->listlvl][$this->listoccur[$this->listlvl]][$this->listnum] = $this->saveInlineProperties();
18225
18226 // List-type
18227 if (isset($properties['LIST-STYLE-TYPE'])) {
18228 $this->listitemtype = $this->_getListStyle($properties['LIST-STYLE-TYPE']);
18229 }
18230 else if (isset($properties['LIST-STYLE'])) {
18231 $this->listitemtype = $this->_getListStyle($properties['LIST-STYLE']);
18232 }
18233 else if (isset($attr['TYPE']) && $attr['TYPE']) { $this->listitemtype = $attr['TYPE']; }
18234 else $this->listitemtype = '';
18235 break;
18236 /*-- END LISTS --*/
18237
18238 }//end of switch
18239 }
18240
18241 /*-- LISTS --*/
18242
18243 function _getListStyle($ls) {
18244 if (stristr($ls,'decimal')) { return '1'; }
18245 /* CSS3 list-styles numeric (selected) + I added tamil
18246 arabic-indic | bengali | devanagari | gujarati | gurmukhi | kannada | malayalam | oriya | persian | telugu | thai | urdu
18247 */
18248 else if (preg_match('/(disc|circle|square|arabic-indic|bengali|devanagari|gujarati|gurmukhi|kannada|malayalam|oriya|persian|tamil|telugu|thai|urdu)/i',$ls,$m)) {
18249 return strtolower(trim($m[1]));
18250 }
18251 else if (stristr($ls,'lower-roman')) { return 'i'; }
18252 else if (stristr($ls,'upper-roman')) { return 'I'; }
18253 else if (stristr($ls,'lower-latin')|| stristr($ls,'lower-alpha')) { return 'a'; }
18254 else if (stristr($ls,'upper-latin') || stristr($ls,'upper-alpha')) { return 'A'; }
18255 else if (stristr($ls,'none')) { return 'none'; }
18256 else if (preg_match('/U\+([a-fA-F0-9]+)/i',$ls)) { return $ls; }
18257 else { return ''; }
18258 }
18259 /*-- END LISTS --*/
18260
18261
18262
18263 function CloseTag($tag)
18264 {
18265 $this->ignorefollowingspaces = false; //Eliminate exceeding left-side spaces
18266 //Closing tag
18267 if($tag=='OPTION') { $this->selectoption['ACTIVE'] = false; $this->lastoptionaltag = ''; }
18268
18269 if($tag=='TTS' or $tag=='TTA' or $tag=='TTZ') {
18270 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
18271 unset($this->InlineProperties[$tag]);
18272 $ltag = strtolower($tag);
18273 $this->$ltag = false;
18274 }
18275
18276
18277 if($tag=='FONT' || $tag=='SPAN' || $tag=='CODE' || $tag=='KBD' || $tag=='SAMP' || $tag=='TT' || $tag=='VAR'
18278 || $tag=='INS' || $tag=='STRONG' || $tag=='CITE' || $tag=='SUB' || $tag=='SUP' || $tag=='S' || $tag=='STRIKE' || $tag=='DEL'
18279 || $tag=='Q' || $tag=='EM' || $tag=='B' || $tag=='I' || $tag=='U' | $tag=='SMALL' || $tag=='BIG' || $tag=='ACRONYM'
18280 || $tag=='MARK' || $tag=='TIME' || $tag=='PROGRESS' || $tag=='METER'
18281 ) { // mPDF 5.5.09
18282
18283 if ($tag == 'SPAN') {
18284 if (isset($this->InlineProperties['SPAN'][$this->spanlvl]) && $this->InlineProperties['SPAN'][$this->spanlvl]) { $this->restoreInlineProperties($this->InlineProperties['SPAN'][$this->spanlvl]); }
18285 unset($this->InlineProperties['SPAN'][$this->spanlvl]);
18286 if (isset($this->InlineAnnots['SPAN'][$this->spanlvl]) && $this->InlineAnnots['SPAN'][$this->spanlvl]) { $annot = $this->InlineAnnots['SPAN'][$this->spanlvl]; } // *ANNOTATIONS*
18287 unset($this->InlineAnnots['SPAN'][$this->spanlvl]); // *ANNOTATIONS*
18288 $this->spanlvl--;
18289 }
18290 else {
18291 if (isset($this->InlineProperties[$tag]) && $this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
18292 unset($this->InlineProperties[$tag]);
18293 if (isset($this->InlineAnnots[$tag]) && $this->InlineAnnots[$tag]) { $annot = $this->InlineAnnots[$tag]; } // *ANNOTATIONS*
18294 unset($this->InlineAnnots[$tag]); // *ANNOTATIONS*
18295 }
18296
18297 /*-- ANNOTATIONS --*/
18298 if (isset($annot)) {
18299 if($this->tableLevel) { // *TABLES*
18300 $this->cell[$this->row][$this->col]['textbuffer'][] = array($annot); // *TABLES*
18301 } // *TABLES*
18302 else { // *TABLES*
18303 $this->textbuffer[] = array($annot);
18304 } // *TABLES*
18305 }
18306 /*-- END ANNOTATIONS --*/
18307 }
18308
18309 if($tag=='METER' || $tag=='PROGRESS') {
18310 $this->inMeter = false; // mPDF 5.5.09
18311 }
18312
18313
18314 if($tag=='A') {
18315 $this->HREF='';
18316 if (isset($this->InlineProperties['A'])) { $this->restoreInlineProperties($this->InlineProperties['A']); }
18317 unset($this->InlineProperties['A']);
18318 }
18319
18320 if($tag=='LEGEND') { // mPDF 5.4.18
18321 if (count($this->textbuffer) && !$this->tableLevel) {
18322 $leg = $this->textbuffer[(count($this->textbuffer)-1)];
18323 unset($this->textbuffer[(count($this->textbuffer)-1)]);
18324 $this->textbuffer = array_values($this->textbuffer);
18325 $this->blk[$this->blklvl]['border_legend'] = $leg;
18326 $this->blk[$this->blklvl]['margin_top'] += ($leg[11]/2)/_MPDFK;
18327 $this->blk[$this->blklvl]['padding_top'] += ($leg[11]/2)/_MPDFK;
18328 }
18329 if (isset($this->InlineProperties['LEGEND'])) { $this->restoreInlineProperties($this->InlineProperties['LEGEND']); }
18330 unset($this->InlineProperties['LEGEND']);
18331 $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
18332 }
18333
18334
18335
18336 /*-- FORMS --*/
18337 // *********** FORM ELEMENTS ********************
18338
18339 if($tag=='TEXTAREA') {
18340 $this->specialcontent = '';
18341 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
18342 unset($this->InlineProperties[$tag]);
18343 }
18344
18345
18346 if($tag=='SELECT') {
18347 $this->lastoptionaltag = '';
18348 $texto = '';
18349 if (isset($this->selectoption['SELECTED'])) { $texto = $this->selectoption['SELECTED']; }
18350
18351 if ($this->useActiveForms) { $w = $this->selectoption['MAXWIDTH']; }
18352 else { $w = $this->GetStringWidth($texto); }
18353 if ($w == 0) { $w = 5; }
18354 $objattr['type'] = 'select';
18355 $objattr['text'] = $texto;
18356 if (isset($this->selectoption['NAME'])) { $objattr['fieldname'] = $this->selectoption['NAME']; }
18357 if (isset($this->selectoption['READONLY'])) { $objattr['readonly'] = true; }
18358 if (isset($this->selectoption['REQUIRED'])) { $objattr['required'] = true; }
18359 if (isset($this->selectoption['SPELLCHECK'])) { $objattr['spellcheck'] = true; }
18360 if (isset($this->selectoption['EDITABLE'])) { $objattr['editable'] = true; }
18361 if (isset($this->selectoption['ONCHANGE'])) { $objattr['onChange'] = $this->selectoption['ONCHANGE']; }
18362 if (isset($this->selectoption['ITEMS'])) { $objattr['items'] = $this->selectoption['ITEMS']; }
18363 if (isset($this->selectoption['MULTIPLE'])) { $objattr['multiple'] = $this->selectoption['MULTIPLE']; }
18364 if (isset($this->selectoption['DISABLED'])) { $objattr['disabled'] = $this->selectoption['DISABLED']; }
18365 if (isset($this->selectoption['TITLE'])) { $objattr['title'] = $this->selectoption['TITLE']; }
18366 if (isset($this->selectoption['COLOR'])) { $objattr['color'] = $this->selectoption['COLOR']; }
18367 if (isset($this->selectoption['SIZE'])) { $objattr['size'] = $this->selectoption['SIZE']; }
18368 if (isset($objattr['size']) && $objattr['size']>1) { $rows=$objattr['size']; } else { $rows = 1; }
18369
18370 $objattr['fontfamily'] = $this->FontFamily;
18371 $objattr['fontsize'] = $this->FontSizePt;
18372
18373 $objattr['width'] = $w + ($this->form->form_element_spacing['select']['outer']['h']*2)+($this->form->form_element_spacing['select']['inner']['h']*2) + ($this->FontSize*1.4);
18374 $objattr['height'] = ($this->FontSize*$rows) + ($this->form->form_element_spacing['select']['outer']['v']*2)+($this->form->form_element_spacing['select']['inner']['v']*2);
18375 $e = "\xbb\xa4\xactype=select,objattr=".serialize($objattr)."\xbb\xa4\xac";
18376
18377 // Clear properties - tidy up
18378 $properties = array();
18379
18380 // Output it to buffers
18381 if ($this->tableLevel) { // *TABLES*
18382 $this->_saveCellTextBuffer($e, $this->HREF);
18383 $this->cell[$this->row][$this->col]['s'] += $objattr['width'] ; // *TABLES*
18384 } // *TABLES*
18385 else { // *TABLES*
18386 $this->_saveTextBuffer($e, $this->HREF);
18387 } // *TABLES*
18388
18389 $this->selectoption = array();
18390 $this->specialcontent = '';
18391
18392 if ($this->InlineProperties[$tag]) { $this->restoreInlineProperties($this->InlineProperties[$tag]); }
18393 unset($this->InlineProperties[$tag]);
18394
18395 }
18396 /*-- END FORMS --*/
18397
18398
18399 // *********** BLOCKS ********************
18400 // mPDF 5.4.18
18401 if($tag=='P' || $tag=='DIV' || $tag=='H1' || $tag=='H2' || $tag=='H3' || $tag=='H4' || $tag=='H5' || $tag=='H6' || $tag=='PRE'
18402 || $tag=='FORM' || $tag=='ADDRESS' || $tag=='BLOCKQUOTE' || $tag=='CENTER' || $tag=='DT' || $tag=='DD' || $tag=='DL'
18403 || $tag=='CAPTION' || $tag=='FIELDSET'
18404 || $tag=='ARTICLE' || $tag=='ASIDE' || $tag=='FIGURE' || $tag=='FIGCAPTION' || $tag=='FOOTER' || $tag=='HEADER' || $tag=='HGROUP'
18405 || $tag=='NAV' || $tag=='SECTION' || $tag=='DETAILS' || $tag=='SUMMARY'
18406 ) { // mPDF 5.5.09 // mPDF 5.5.22
18407
18408 $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
18409 $this->blockjustfinished=true;
18410
18411 $this->lastblockbottommargin = $this->blk[$this->blklvl]['margin_bottom'];
18412 /*-- LISTS --*/
18413 if ($this->listlvl>0) { return; }
18414 /*-- END LISTS --*/
18415
18416 // mPDF 5.6.34
18417 if (preg_match('/^H\d/',$tag) && !$this->tableLevel && !$this->writingToC) { // mPDF 5.6.38
18418 if (isset($this->h2toc[$tag]) || isset($this->h2bookmarks[$tag])) {
18419 $content = '';
18420 if (count($this->textbuffer)==1) { $content = $this->textbuffer[0][0]; }
18421 else {
18422 for ($i=0;$i<count($this->textbuffer);$i++) {
18423 if (substr($this->textbuffer[$i][0],0,3) != "\xbb\xa4\xac") { //inline object
18424 $content .= $this->textbuffer[$i][0];
18425 }
18426 }
18427 }
18428 /*-- TOC --*/
18429 if (isset($this->h2toc[$tag])) {
18430 $objattr = array();
18431 $objattr['type'] = 'toc';
18432 $objattr['toclevel'] = $this->h2toc[$tag];
18433 $objattr['CONTENT'] = htmlspecialchars($content); // mPDF 5.6.37
18434 $e = "\xbb\xa4\xactype=toc,objattr=".serialize($objattr)."\xbb\xa4\xac";
18435 array_unshift($this->textbuffer,array($e));
18436 }
18437 /*-- END TOC --*/
18438 /*-- BOOKMARKS --*/
18439 if (isset($this->h2bookmarks[$tag])) {
18440 $objattr = array();
18441 $objattr['type'] = 'bookmark';
18442 $objattr['bklevel'] = $this->h2bookmarks[$tag];
18443 $objattr['CONTENT'] = $content;
18444 $e = "\xbb\xa4\xactype=toc,objattr=".serialize($objattr)."\xbb\xa4\xac";
18445 array_unshift($this->textbuffer,array($e));
18446 }
18447 /*-- END BOOKMARKS --*/
18448 }
18449 }
18450
18451 /*-- TABLES --*/
18452 if($this->tableLevel) {
18453 if ($this->linebreakjustfinished) { $this->blockjustfinished=false; }
18454 if (isset($this->InlineProperties['BLOCKINTABLE'])) {
18455 if ($this->InlineProperties['BLOCKINTABLE']) { $this->restoreInlineProperties($this->InlineProperties['BLOCKINTABLE']); }
18456 unset($this->InlineProperties['BLOCKINTABLE']);
18457 }
18458 if($tag=='PRE') { $this->ispre=false; }
18459 return;
18460 }
18461 /*-- END TABLES --*/
18462 $this->lastoptionaltag = '';
18463 $this->divbegin=false;
18464
18465 $this->linebreakjustfinished=false;
18466
18467 $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
18468
18469 /*-- CSS-FLOAT --*/
18470 // If float contained in a float, need to extend bottom to allow for it
18471 $currpos = $this->page*1000 + $this->y;
18472 if (isset($this->blk[$this->blklvl]['float_endpos']) && $this->blk[$this->blklvl]['float_endpos'] > $currpos) {
18473 $old_page = $this->page;
18474 $new_page = intval($this->blk[$this->blklvl]['float_endpos'] /1000);
18475 if ($old_page != $new_page) {
18476 $s = $this->PrintPageBackgrounds();
18477 // Writes after the marker so not overwritten later by page background etc.
18478 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
18479 $this->pageBackgrounds = array();
18480 $this->page = $new_page;
18481 $this->ResetMargins();
18482 $this->Reset();
18483 $this->pageoutput[$this->page] = array();
18484 }
18485 $this->y = (($this->blk[$this->blklvl]['float_endpos'] *1000) % 1000000)/1000; // mod changes operands to integers before processing
18486 }
18487 /*-- END CSS-FLOAT --*/
18488
18489
18490 //Print content
18491 if ($this->lastblocklevelchange == 1) { $blockstate = 3; } // Top & bottom margins/padding
18492 else if ($this->lastblocklevelchange == -1) { $blockstate = 2; } // Bottom margins/padding only
18493 else { $blockstate = 0; }
18494 // called from after e.g. </table> </div> </div> ... Outputs block margin/border and padding
18495 if (count($this->textbuffer) && $this->textbuffer[count($this->textbuffer)-1]) {
18496 if (substr($this->textbuffer[count($this->textbuffer)-1][0],0,3) != "\xbb\xa4\xac") { // not special content
18497 if ($this->usingCoreFont) {
18498 $this->textbuffer[count($this->textbuffer)-1][0] = preg_replace('/[ ]+$/', '', $this->textbuffer[count($this->textbuffer)-1][0]);
18499 }
18500 else {
18501 $this->textbuffer[count($this->textbuffer)-1][0] = preg_replace('/[ ]+$/u', '', $this->textbuffer[count($this->textbuffer)-1][0]); }
18502 }
18503 }
18504
18505 if (count($this->textbuffer) == 0 && $this->lastblocklevelchange != 0) {
18506 //$this->newFlowingBlock( $this->blk[$this->blklvl]['width'],$this->lineheight,'',false,false,2,true, $this->blk[$this->blklvl]['direction']);
18507 $this->newFlowingBlock( $this->blk[$this->blklvl]['width'],$this->lineheight,'',false,false,$blockstate,true, $this->blk[$this->blklvl]['direction']);
18508 $this->finishFlowingBlock(true); // true = END of flowing block
18509 $this->PaintDivBB('',$blockstate);
18510 }
18511 else {
18512 $this->printbuffer($this->textbuffer,$blockstate);
18513 }
18514
18515
18516 $this->textbuffer=array();
18517
18518 if ($this->blk[$this->blklvl]['keep_block_together']) {
18519 $this->printdivbuffer();
18520 }
18521
18522 if ($this->kwt) {
18523 $this->kwt_height = $this->y - $this->kwt_y0;
18524 }
18525
18526 /*-- CSS-IMAGE-FLOAT --*/
18527 $this->printfloatbuffer();
18528 /*-- END CSS-IMAGE-FLOAT --*/
18529
18530 if($tag=='PRE') { $this->ispre=false; }
18531
18532 /*-- CSS-FLOAT --*/
18533 if ($this->blk[$this->blklvl]['float'] == 'R') {
18534 // If width not set, here would need to adjust and output buffer
18535 $s = $this->PrintPageBackgrounds();
18536 // Writes after the marker so not overwritten later by page background etc.
18537 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
18538 $this->pageBackgrounds = array();
18539 $this->Reset();
18540 $this->pageoutput[$this->page] = array();
18541
18542 for($i=($this->blklvl-1); $i >= 0; $i--) {
18543 if (isset($this->blk[$i]['float_endpos'])) { $this->blk[$i]['float_endpos'] = max($this->blk[$i]['float_endpos'], ($this->page*1000 + $this->y)); }
18544 else { $this->blk[$i]['float_endpos'] = $this->page*1000 + $this->y; }
18545 }
18546
18547 $this->floatDivs[] = array(
18548 'side'=>'R',
18549 'startpage'=>$this->blk[$this->blklvl]['startpage'] ,
18550 'y0'=>$this->blk[$this->blklvl]['float_start_y'] ,
18551 'startpos'=> ($this->blk[$this->blklvl]['startpage']*1000 + $this->blk[$this->blklvl]['float_start_y']),
18552 'endpage'=>$this->page ,
18553 'y1'=>$this->y ,
18554 'endpos'=> ($this->page*1000 + $this->y),
18555 'w'=> $this->blk[$this->blklvl]['float_width'],
18556 'blklvl'=>$this->blklvl,
18557 'blockContext' => $this->blk[$this->blklvl-1]['blockContext']
18558 );
18559
18560 $this->y = $this->blk[$this->blklvl]['float_start_y'] ;
18561 $this->page = $this->blk[$this->blklvl]['startpage'] ;
18562 $this->ResetMargins();
18563 $this->pageoutput[$this->page] = array();
18564 }
18565 if ($this->blk[$this->blklvl]['float'] == 'L') {
18566 // If width not set, here would need to adjust and output buffer
18567 $s = $this->PrintPageBackgrounds();
18568 // Writes after the marker so not overwritten later by page background etc.
18569 $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
18570 $this->pageBackgrounds = array();
18571 $this->Reset();
18572 $this->pageoutput[$this->page] = array();
18573
18574 for($i=($this->blklvl-1); $i >= 0; $i--) {
18575 if (isset($this->blk[$i]['float_endpos'])) { $this->blk[$i]['float_endpos'] = max($this->blk[$i]['float_endpos'], ($this->page*1000 + $this->y)); }
18576 else { $this->blk[$i]['float_endpos'] = $this->page*1000 + $this->y; }
18577 }
18578
18579 $this->floatDivs[] = array(
18580 'side'=>'L',
18581 'startpage'=>$this->blk[$this->blklvl]['startpage'] ,
18582 'y0'=>$this->blk[$this->blklvl]['float_start_y'] ,
18583 'startpos'=> ($this->blk[$this->blklvl]['startpage']*1000 + $this->blk[$this->blklvl]['float_start_y']),
18584 'endpage'=>$this->page ,
18585 'y1'=>$this->y ,
18586 'endpos'=> ($this->page*1000 + $this->y),
18587 'w'=> $this->blk[$this->blklvl]['float_width'],
18588 'blklvl'=>$this->blklvl,
18589 'blockContext' => $this->blk[$this->blklvl-1]['blockContext']
18590 );
18591
18592 $this->y = $this->blk[$this->blklvl]['float_start_y'] ;
18593 $this->page = $this->blk[$this->blklvl]['startpage'] ;
18594 $this->ResetMargins();
18595 $this->pageoutput[$this->page] = array();
18596 }
18597 /*-- END CSS-FLOAT --*/
18598
18599 if (isset($this->blk[$this->blklvl]['visibility']) && $this->blk[$this->blklvl]['visibility']!='visible') {
18600 $this->SetVisibility('visible');
18601 }
18602
18603 if (isset($this->blk[$this->blklvl]['page_break_after'])) { $page_break_after = $this->blk[$this->blklvl]['page_break_after']; }
18604 else { $page_break_after = ''; }
18605
18606 //Reset values
18607 $this->Reset();
18608
18609 // mPDF 5.6.01 - LAYERS
18610 if (isset($this->blk[$this->blklvl]['z-index']) && $this->blk[$this->blklvl]['z-index'] > 0) {
18611 $this->EndLayer();
18612 }
18613
18614 if ($this->blklvl > 0) { // ==0 SHOULDN'T HAPPEN - NOT XHTML
18615 if ($this->blk[$this->blklvl]['tag'] == $tag) {
18616 unset($this->blk[$this->blklvl]);
18617 $this->blklvl--;
18618 }
18619 //else { echo $tag; exit; } // debug - forces error if incorrectly nested html tags
18620 }
18621
18622 $this->lastblocklevelchange = -1 ;
18623 // Reset Inline-type properties
18624 if (isset($this->blk[$this->blklvl]['InlineProperties'])) { $this->restoreInlineProperties($this->blk[$this->blklvl]['InlineProperties']); }
18625
18626 $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
18627
18628 if ($page_break_after) {
18629 $save_blklvl = $this->blklvl;
18630 $save_blk = $this->blk;
18631 $save_silp = $this->saveInlineProperties();
18632 $save_spanlvl = $this->spanlvl;
18633 $save_ilp = $this->InlineProperties;
18634 if ($this->blklvl>1) {
18635 // Close any open block tags
18636 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
18637 // Output any text left in buffer
18638 if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); $this->textbuffer=array(); }
18639 }
18640 /*-- COLUMNS --*/
18641 $save_cols = false;
18642 if ($this->ColActive) {
18643 $save_cols = true;
18644 $save_nbcol = $this->NbCol; // other values of gap and vAlign will not change by setting Columns off
18645 $this->SetColumns(0);
18646 }
18647 /*-- END COLUMNS --*/
18648 if ($page_break_after == 'RIGHT') { $this->AddPage($this->CurOrientation,'NEXT-ODD','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
18649 else if ($page_break_after == 'LEFT') { $this->AddPage($this->CurOrientation,'NEXT-EVEN','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
18650 else { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
18651 if (!$this->restoreBlockPagebreaks) {
18652 $this->blklvl = 0;
18653 $this->lastblocklevelchange = 0;
18654 $this->blk = array();
18655 $this->initialiseBlock($this->blk[0]);
18656 $this->blk[0]['width'] =& $this->pgwidth;
18657 $this->blk[0]['inner_width'] =& $this->pgwidth;
18658 $this->blk[0]['blockContext'] = $this->blockContext;
18659 $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
18660 $this->setCSS($properties,'','BODY');
18661 $this->blklvl++;
18662 $currblk =& $this->blk[$this->blklvl];
18663 $prevblk =& $this->blk[$this->blklvl-1];
18664
18665 $this->initialiseBlock($currblk);
18666 $currblk['tag'] = $tag;
18667 $currblk['attr'] = $attr;
18668
18669 $this->Reset();
18670 $properties = $this->cssmgr->MergeCSS('BLOCK',$tag,$attr);
18671 }
18672 /*-- COLUMNS --*/
18673 if ($save_cols) {
18674 // Restore columns
18675 $this->SetColumns($save_nbcol,$this->colvAlign,$this->ColGap);
18676 }
18677 /*-- END COLUMNS --*/
18678 if ($this->restoreBlockPagebreaks && !$this->tableLevel && !$this->listlvl) {
18679 $this->blk = $save_blk;
18680 // Re-open block tags
18681 $t = $this->blk[0]['tag'];
18682 $a = $this->blk[0]['attr'];
18683 $this->blklvl = 0;
18684 for ($b=0; $b<=$save_blklvl;$b++) {
18685 $tc = $t;
18686 $ac = $a;
18687 $t = $this->blk[$b+1]['tag'];
18688 $a = $this->blk[$b+1]['attr'];
18689 unset($this->blk[$b+1]);
18690 $this->OpenTag($tc,$ac);
18691 }
18692 $this->spanlvl = $save_spanlvl;
18693 $this->InlineProperties = $save_ilp;
18694 $this->restoreInlineProperties($save_silp);
18695 }
18696 }
18697
18698 }
18699
18700
18701 /*-- TABLES --*/
18702
18703 if($tag=='TH') $this->SetStyle('B',false);
18704
18705 if(($tag=='TH' or $tag=='TD') && $this->tableLevel) {
18706 $this->lastoptionaltag = 'TR';
18707 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
18708 $this->cssmgr->tbCSSlvl--;
18709 if (!$this->tdbegin) { return; }
18710 $this->tdbegin = false;
18711 // Added for correct calculation of cell column width - otherwise misses the last line if not end </p> etc.
18712 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
18713 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;"); }
18714 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
18715 }
18716 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
18717 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
18718 }
18719
18720 // Remove last <br> if at end of cell
18721 if (isset($this->cell[$this->row][$this->col]['textbuffer'])) { $ntb = count($this->cell[$this->row][$this->col]['textbuffer']); }
18722 else { $ntb = 0; }
18723 if ($ntb>1 && $this->cell[$this->row][$this->col]['textbuffer'][$ntb-1][0] == "\n") {
18724 unset($this->cell[$this->row][$this->col]['textbuffer'][$ntb-1]);
18725 }
18726
18727 if ($this->cacheTables) {
18728 $clen = $this->_cacheCell($this->cell[$this->row][$this->col], $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cache']);
18729 $this->cell[$this->row][$this->col] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['ptr'];
18730 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['ptr'] += $clen;
18731 }
18732
18733 if ($this->tablethead) {
18734 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_thead'][$this->row] = true;
18735 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)); }
18736 }
18737 if ($this->tabletfoot) {
18738 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'][$this->row] = true;
18739 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'] )); }
18740 }
18741 $this->Reset();
18742 }
18743
18744 if($tag=='TR' && $this->tableLevel) {
18745 // If Border set on TR - Update right border
18746 if (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-left'][$this->row])) {
18747 if ($this->cacheTables) {
18748 $c = $this->_uncacheCell($this->cell[$this->row][$this->col], $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cache'], null);
18749 }
18750 else { $c =& $this->cell[$this->row][$this->col]; }
18751 if ($c) {
18752 if ($this->packTableData) {
18753 $cell = $this->_unpackCellBorder($c['borderbin'] );
18754 }
18755 else { $cell = $c; }
18756 $cell['border_details']['R'] = $this->border_details($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trborder-right'][$this->row]);
18757 $this->setBorder($cell['border'], _BORDER_RIGHT, $cell['border_details']['R']['s']);
18758 if ($this->packTableData) {
18759 $c['borderbin'] = $this->_packCellBorder($cell);
18760 unset($c['border']);
18761 unset($c['border_details']);
18762 }
18763 else { $c = $cell; }
18764 }
18765 if ($this->cacheTables) {
18766 $fh = fopen($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cache'], "r+b");
18767 $this->_cacheUpdateBorder($c, $fh, $this->cell[$this->row][$this->col]);
18768 fclose($fh);
18769 }
18770 }
18771 $this->lastoptionaltag = '';
18772 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
18773 $this->cssmgr->tbCSSlvl--;
18774 $this->trow_text_rotate = '';
18775 $this->tabletheadjustfinished = false;
18776 }
18777
18778 if($tag=='TBODY') {
18779 $this->lastoptionaltag = '';
18780 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
18781 $this->cssmgr->tbCSSlvl--;
18782 }
18783
18784 if($tag=='THEAD') {
18785 $this->lastoptionaltag = '';
18786 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
18787 $this->cssmgr->tbCSSlvl--;
18788 $this->tablethead = 0;
18789 $this->tabletheadjustfinished = true;
18790 $this->ResetStyles();
18791 $this->thead_font_weight = '';
18792 $this->thead_font_style = '';
18793 $this->thead_font_smCaps = '';
18794
18795 $this->thead_valign_default = '';
18796 $this->thead_textalign_default = '';
18797 }
18798
18799 if($tag=='TFOOT') {
18800 $this->lastoptionaltag = '';
18801 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
18802 $this->cssmgr->tbCSSlvl--;
18803 $this->tabletfoot = 0;
18804 $this->ResetStyles();
18805 $this->tfoot_font_weight = '';
18806 $this->tfoot_font_style = '';
18807 $this->tfoot_font_smCaps = '';
18808
18809 $this->tfoot_valign_default = '';
18810 $this->tfoot_textalign_default = '';
18811 }
18812
18813 if($tag=='TABLE') { // TABLE-END (
18814 if ($this->progressBar) { $this->UpdateProgressBar(1,'','TABLE'); } // *PROGRESS-BAR*
18815 if ($this->progressBar) { $this->UpdateProgressBar(7,0,''); } // *PROGRESS-BAR*
18816 $this->lastoptionaltag = '';
18817 unset($this->cssmgr->tablecascadeCSS[$this->cssmgr->tbCSSlvl]);
18818 $this->cssmgr->tbCSSlvl--;
18819 $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
18820 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] = $this->cell;
18821 $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));
18822 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['hr'] = array_pad(array(),$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr'],0);
18823
18824 // Move table footer <tfoot> row to end of table
18825 if (isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot']) && count($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'])) {
18826 $tfrows = array();
18827 foreach($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'] AS $r=>$val) {
18828 if ($val) { $tfrows[] = $r; }
18829 }
18830 $temp = array();
18831 $temptf = array();
18832 foreach($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] AS $k=>$row) {
18833 if (in_array($k,$tfrows)) {
18834 $temptf[] = $row;
18835 }
18836 else {
18837 $temp[] = $row;
18838 }
18839 }
18840 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'] = array();
18841 for($i=count($temp) ; $i<(count($temp)+count($temptf)); $i++) {
18842 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['is_tfoot'][$i] = true;
18843 }
18844 // Update nestedpos row references
18845 if (count($this->table[($this->tableLevel+1)])) {
18846 foreach($this->table[($this->tableLevel+1)] AS $nid=>$nested) {
18847 $this->table[($this->tableLevel+1)][$nid]['nestedpos'][0] -= count($temptf);
18848 }
18849 }
18850 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'] = array_merge($temp, $temptf);
18851
18852 // Update other arays set on row number
18853 // [trbackground-images] [trgradients]
18854 $temptrbgi = array();
18855 $temptrbgg = array();
18856 $temptrbgc = array();
18857 $temptrbgc[-1] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][-1];
18858 for($k=0; $k<$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr']; $k++) {
18859 if (!in_array($k,$tfrows)) {
18860 $temptrbgi[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'][$k];
18861 $temptrbgg[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'][$k];
18862 $temptrbgc[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$k];
18863 }
18864 }
18865 for($k=0; $k<$this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['nr']; $k++) {
18866 if (in_array($k,$tfrows)) {
18867 $temptrbgi[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'][$k];
18868 $temptrbgg[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'][$k];
18869 $temptrbgc[] = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'][$k];
18870 }
18871 }
18872 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trbackground-images'] = $temptrbgi;
18873 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['trgradients'] = $temptrbgg;
18874 $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['bgcolor'] = $temptrbgc ;
18875 // Should Update all other arays set on row number, but cell properties have been set so not needed
18876 // [bgcolor] [trborder-left] [trborder-right] [trborder-top] [trborder-bottom]
18877 }
18878
18879 if ($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['direction']=='rtl') {
18880 $this->_reverseTableDir($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]);
18881 }
18882
18883 // Fix Borders *********************************************
18884 $this->_fixTableBorders($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]);
18885
18886 if ($this->progressBar) { $this->UpdateProgressBar(7,10,' '); } // *PROGRESS-BAR*
18887
18888 if ($this->ColActive) { $this->table_rotate = 0; } // *COLUMNS*
18889 if ($this->table_rotate <> 0) {
18890 $this->tablebuffer = '';
18891 // Max width for rotated table
18892 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 1);
18893 $this->tbrot_maxh = $this->blk[$this->blklvl]['inner_width'] ; // Max width for rotated table
18894 $this->tbrot_align = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['a'] ;
18895 }
18896 $this->shrin_k = 1;
18897
18898 if ($this->shrink_tables_to_fit < 1) { $this->shrink_tables_to_fit = 1; }
18899 if (!$this->shrink_this_table_to_fit) { $this->shrink_this_table_to_fit = $this->shrink_tables_to_fit; }
18900
18901 if ($this->tableLevel>1) {
18902 // deal with nested table
18903
18904 $this->_tableColumnWidth($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]],true);
18905
18906 $tmiw = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['miw'];
18907 $tmaw = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['maw'];
18908 $tl = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['tl'];
18909
18910 // Go down to lower table level
18911 $this->tableLevel--;
18912
18913 // Reset lower level table
18914 $this->base_table_properties = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['baseProperties'];
18915 $this->cell = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['cells'];
18916 // mPDF 5.4.10
18917 if (isset($this->cell['PARENTCELL'])) {
18918 if ($this->cell['PARENTCELL']) { $this->restoreInlineProperties($this->cell['PARENTCELL']); }
18919 unset($this->cell['PARENTCELL']);
18920 }
18921 $this->row = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currrow'];
18922 $this->col = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['currcol'];
18923 $objattr = array();
18924 $objattr['type'] = 'nestedtable';
18925 $objattr['nestedcontent'] = $this->tbctr[($this->tableLevel+1)];
18926 $objattr['table'] = $this->tbctr[$this->tableLevel];
18927 $objattr['row'] = $this->row;
18928 $objattr['col'] = $this->col;
18929 $objattr['level'] = $this->tableLevel;
18930 $e = "\xbb\xa4\xactype=nestedtable,objattr=".serialize($objattr)."\xbb\xa4\xac";
18931 $this->_saveCellTextBuffer($e);
18932 $this->cell[$this->row][$this->col]['s'] += $tl ;
18933 if (!isset($this->cell[$this->row][$this->col]['maxs'])) {
18934 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
18935 }
18936 elseif($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) {
18937 $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s'];
18938 }
18939 $this->cell[$this->row][$this->col]['s'] = 0;// reset
18940 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 ; }
18941 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 ; }
18942 $this->tdbegin = true;
18943 $this->nestedtablejustfinished = true;
18944 $this->ignorefollowingspaces = true;
18945 return;
18946 }
18947 $this->cMarginL = 0;
18948 $this->cMarginR = 0;
18949 $this->cMarginT = 0;
18950 $this->cMarginB = 0;
18951 $this->cellPaddingL = 0;
18952 $this->cellPaddingR = 0;
18953 $this->cellPaddingT = 0;
18954 $this->cellPaddingB = 0;
18955
18956 if (isset($this->table[1][1]['overflow']) && $this->table[1][1]['overflow']=='visible') {
18957 if ($this->kwt || $this->table_rotate || $this->table_keep_together || $this->ColActive) {
18958 $this->kwt = false;
18959 $this->table_rotate = 0;
18960 $this->table_keep_together = false;
18961 //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");
18962 }
18963 $this->_tableColumnWidth($this->table[1][1],true);
18964 $this->_tableWidth($this->table[1][1]);
18965 }
18966 else {
18967 if (!$this->kwt_saved) { $this->kwt_height = 0; }
18968
18969 list($check,$tablemiw) = $this->_tableColumnWidth($this->table[1][1],true);
18970 $save_table = $this->table;
18971 if ($this->cacheTables) { $this->_backupCacheFiles(); }
18972 $reset_to_minimum_width = false;
18973 $added_page = false;
18974
18975 if ($check > 1) {
18976 if ($check > $this->shrink_this_table_to_fit && $this->table_rotate) {
18977 if ($this->y != $this->tMargin) {
18978 $this->AddPage($this->CurOrientation);
18979 $this->kwt_moved = true;
18980 }
18981 $added_page = true;
18982 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
18983 //$check = $tablemiw/$this->tbrot_maxw; // undo any shrink
18984 $check = 1; // undo any shrink
18985 }
18986 $reset_to_minimum_width = true;
18987 }
18988
18989 if ($reset_to_minimum_width) {
18990
18991 $this->shrin_k = $check;
18992
18993 $this->default_font_size /= $this->shrin_k;
18994 $this->SetFontSize($this->default_font_size, false );
18995
18996 $this->shrinkTable($this->table[1][1],$this->shrin_k);
18997
18998 $this->_tableColumnWidth($this->table[1][1],false); // repeat
18999
19000 // Starting at $this->innermostTableLevel
19001 // Shrink table values - and redo columnWidth
19002 for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
19003 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
19004 $this->shrinkTable($this->table[$lvl][$nid],$this->shrin_k);
19005 $this->_tableColumnWidth($this->table[$lvl][$nid],false);
19006 }
19007 }
19008 }
19009
19010 // Set table cell widths for top level table
19011 // Use $shrin_k to resize but don't change again
19012 $this->SetLineHeight('',$this->table_lineheight);
19013
19014 // Top level table
19015 $this->_tableWidth($this->table[1][1]);
19016
19017 }
19018
19019
19020 // Now work through any nested tables setting child table[w'] = parent cell['w']
19021 // Now do nested tables _tableWidth
19022 for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
19023 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
19024 // HERE set child table width = cell width
19025
19026 list($parentrow, $parentcol, $parentnid) = $this->table[$lvl][$nid]['nestedpos'];
19027
19028 if ($this->cacheTables) {
19029 $c = $this->_uncacheCell($this->table[($lvl-1)][$parentnid]['cells'][$parentrow][$parentcol], $this->table[($lvl-1)][$parentnid]['cache'], null);
19030 }
19031 else
19032 $c =& $this->table[($lvl-1)][$parentnid]['cells'][$parentrow][$parentcol];
19033
19034 if (isset($c['colspan']) && $c['colspan']> 1) {
19035 $parentwidth = 0;
19036 for($cs=0;$cs<$c['colspan'] ; $cs++) {
19037 $parentwidth += $this->table[($lvl-1)][$parentnid]['wc'][$parentcol+$cs];
19038 }
19039 }
19040 else { $parentwidth = $this->table[($lvl-1)][$parentnid]['wc'][$parentcol]; }
19041
19042
19043 //$parentwidth -= ALLOW FOR PADDING ETC.in parent cell
19044 if (!$this->simpleTables){
19045 if ($this->packTableData) {
19046 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
19047 }
19048 else {
19049 $br = $c['border_details']['R']['w'];
19050 $bl = $c['border_details']['L']['w'];
19051 }
19052 if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
19053 $parentwidth -= $br + $bl
19054 + $c['padding']['L']
19055 + $c['padding']['R']
19056 + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
19057 }
19058 else {
19059 $parentwidth -= $br/2 + $bl/2
19060 + $c['padding']['L']
19061 + $c['padding']['R'];
19062 }
19063 }
19064 else if ($this->simpleTables){
19065 if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
19066 $parentwidth -= $this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']
19067 + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']
19068 + $c['padding']['L']
19069 + $c['padding']['R']
19070 + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
19071 }
19072 else {
19073 $parentwidth -= $this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']/2
19074 + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']/2
19075 + $c['padding']['L']
19076 + $c['padding']['R'];
19077 }
19078 }
19079 if (isset($this->table[$lvl][$nid]['wpercent']) && $this->table[$lvl][$nid]['wpercent'] && $lvl>1) {
19080 $this->table[$lvl][$nid]['w'] = $parentwidth;
19081 }
19082 else if ($parentwidth > $this->table[$lvl][$nid]['maw']) {
19083 $this->table[$lvl][$nid]['w'] = $this->table[$lvl][$nid]['maw'];
19084 }
19085 else {
19086 $this->table[$lvl][$nid]['w'] = $parentwidth;
19087 }
19088 unset($c);
19089 $this->_tableWidth($this->table[$lvl][$nid]);
19090 }
19091 }
19092
19093 // Starting at $this->innermostTableLevel
19094 // Cascade back up nested tables: setting heights back up the tree
19095 for($lvl=$this->innermostTableLevel;$lvl>0;$lvl--) {
19096 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
19097 list($tableheight,$maxrowheight,$fullpage,$remainingpage, $maxfirstrowheight) = $this->_tableHeight($this->table[$lvl][$nid]); }
19098 }
19099 if ($this->progressBar) { $this->UpdateProgressBar(7,20,' '); } // *PROGRESS-BAR*
19100 if ($this->table[1][1]['overflow']=='visible') {
19101 if ($maxrowheight > $fullpage) { die("mPDF Warning: A Table row is greater than available height. You cannot use CSS overflow:visible"); }
19102 if ($maxfirstrowheight > $remainingpage) { $this->AddPage($this->CurOrientation); }
19103 $r = 0; $c = 0; $p = 0; $y = 0;
19104 while (!$finished) {
19105 list($finished,$r,$c,$p,$y,$y0) = $this->_tableWrite($this->table[1][1],true,$r,$c,$p,$y);
19106 if (!$finished) {
19107 $this->AddPage($this->CurOrientation);
19108 // If printed something on first spread, set same y
19109 if ($r==0 && $y0 > -1) { $this->y = $y0; }
19110 }
19111 }
19112 }
19113 else {
19114 $recalculate = 1;
19115 $forcerecalc = false;
19116 // RESIZING ALGORITHM
19117 if ($maxrowheight > $fullpage) {
19118 $recalculate = $this->tbsqrt($maxrowheight / $fullpage, 1);
19119 $forcerecalc = true;
19120 }
19121 else if ($this->table_rotate) { // NB $remainingpage == $fullpage == the width of the page
19122 if ($tableheight > $remainingpage) {
19123 // If can fit on remainder of page whilst respecting autsize value..
19124 if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, 1)) <= $this->shrink_this_table_to_fit) {
19125 $recalculate = $this->tbsqrt($tableheight / $remainingpage, 1);
19126 }
19127 else if (!$added_page) {
19128 if ($this->y != $this->tMargin) {
19129 $this->AddPage($this->CurOrientation);
19130 $this->kwt_moved = true;
19131 }
19132 $added_page = true;
19133 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
19134 // 0.001 to force it to recalculate
19135 $recalculate = (1 / $this->shrin_k) + 0.001; // undo any shrink
19136 }
19137 }
19138 else { $recalculate = 1; }
19139 }
19140 else if ($this->table_keep_together || ($this->table[1][1]['nr']==1 && !$this->writingHTMLfooter)) {
19141 if ($tableheight > $fullpage) {
19142 if (($this->shrin_k * $this->tbsqrt($tableheight / $fullpage, 1)) <= $this->shrink_this_table_to_fit) {
19143 $recalculate = $this->tbsqrt($tableheight / $fullpage, 1);
19144 }
19145 else if ($this->tableMinSizePriority) {
19146 $this->table_keep_together = false;
19147 $recalculate = 1.001;
19148 }
19149 else {
19150 if ($this->y != $this->tMargin) { // mPDF 5.1
19151 $this->AddPage($this->CurOrientation);
19152 $this->kwt_moved = true;
19153 }
19154 $added_page = true;
19155 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
19156 $recalculate = $this->tbsqrt($tableheight / $fullpage, 1);
19157 }
19158 }
19159 else if ($tableheight > $remainingpage) {
19160 // If can fit on remainder of page whilst respecting autsize value..
19161 if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, 1)) <= $this->shrink_this_table_to_fit) {
19162 $recalculate = $this->tbsqrt($tableheight / $remainingpage, 1);
19163 }
19164 else {
19165 if ($this->y != $this->tMargin) {
19166 $this->AddPage($this->CurOrientation);
19167 $this->kwt_moved = true;
19168 }
19169 $added_page = true;
19170 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
19171 $recalculate = 1.001;
19172 }
19173 }
19174 else { $recalculate = 1; }
19175 }
19176 else { $recalculate = 1; }
19177
19178 if ($recalculate > $this->shrink_this_table_to_fit && !$forcerecalc) { $recalculate = $this->shrink_this_table_to_fit; }
19179
19180 $iteration = 1;
19181
19182 // RECALCULATE
19183 while($recalculate <> 1) {
19184 $this->shrin_k1 = $recalculate ;
19185 $this->shrin_k *= $recalculate ;
19186 $this->default_font_size /= ($this->shrin_k1) ;
19187 $this->SetFontSize($this->default_font_size, false );
19188 $this->SetLineHeight('',$this->table_lineheight);
19189 $this->table = $save_table;
19190 if ($this->cacheTables) { $this->_restoreCacheFiles(); }
19191 if ($this->shrin_k <> 1) { $this->shrinkTable($this->table[1][1],$this->shrin_k); }
19192 $this->_tableColumnWidth($this->table[1][1],false); // repeat
19193
19194 // Starting at $this->innermostTableLevel
19195 // Shrink table values - and redo columnWidth
19196 for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
19197 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
19198 if ($this->shrin_k <> 1) { $this->shrinkTable($this->table[$lvl][$nid],$this->shrin_k); }
19199 $this->_tableColumnWidth($this->table[$lvl][$nid],false);
19200 }
19201 }
19202 // Set table cell widths for top level table
19203
19204 // Top level table
19205 $this->_tableWidth($this->table[1][1]);
19206
19207 // Now work through any nested tables setting child table[w'] = parent cell['w']
19208 // Now do nested tables _tableWidth
19209 for($lvl=2;$lvl<=$this->innermostTableLevel;$lvl++) {
19210 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
19211 // HERE set child table width = cell width
19212
19213 list($parentrow, $parentcol, $parentnid) = $this->table[$lvl][$nid]['nestedpos'];
19214 if ($this->cacheTables) {
19215 $c = $this->_uncacheCell($this->table[($lvl-1)][$parentnid]['cells'][$parentrow][$parentcol], $this->table[($lvl-1)][$parentnid]['cache'], null);
19216 }
19217 else
19218 $c =& $this->table[($lvl-1)][$parentnid]['cells'][$parentrow][$parentcol];
19219
19220 if (isset($c['colspan']) && $c['colspan']> 1) {
19221 $parentwidth = 0;
19222 for($cs=0;$cs<$c['colspan'] ; $cs++) {
19223 $parentwidth += $this->table[($lvl-1)][$parentnid]['wc'][$parentcol+$cs];
19224 }
19225 }
19226 else { $parentwidth = $this->table[($lvl-1)][$parentnid]['wc'][$parentcol]; }
19227
19228 //$parentwidth -= ALLOW FOR PADDING ETC.in parent cell
19229 if (!$this->simpleTables){
19230 if ($this->packTableData) {
19231 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
19232 }
19233 else {
19234 $br = $c['border_details']['R']['w'];
19235 $bl = $c['border_details']['L']['w'];
19236 }
19237 if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
19238 $parentwidth -= $br + $bl
19239 + $c['padding']['L']
19240 + $c['padding']['R']
19241 + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
19242 }
19243 else {
19244 $parentwidth -= $br/2 + $bl/2
19245 + $c['padding']['L']
19246 + $c['padding']['R'];
19247 }
19248 }
19249 else if ($this->simpleTables){
19250 if ($this->table[$lvl-1][$parentnid]['borders_separate']) {
19251 $parentwidth -= $this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']
19252 + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']
19253 + $c['padding']['L']
19254 + $c['padding']['R']
19255 + $this->table[($lvl-1)][$parentnid]['border_spacing_H'];
19256 }
19257 else {
19258 $parentwidth -= ($this->table[($lvl-1)][$parentnid]['simple']['border_details']['L']['w']
19259 + $this->table[($lvl-1)][$parentnid]['simple']['border_details']['R']['w']) /2
19260 + $c['padding']['L']
19261 + $c['padding']['R'];
19262 }
19263 }
19264 if (isset($this->table[$lvl][$nid]['wpercent']) && $this->table[$lvl][$nid]['wpercent'] && $lvl>1) {
19265 $this->table[$lvl][$nid]['w'] = $parentwidth;
19266 }
19267 else if ($parentwidth > $this->table[$lvl][$nid]['maw']) {
19268 $this->table[$lvl][$nid]['w'] = $this->table[$lvl][$nid]['maw'] ;
19269 }
19270 else {
19271 $this->table[$lvl][$nid]['w'] = $parentwidth;
19272 }
19273 unset($c);
19274 $this->_tableWidth($this->table[$lvl][$nid]);
19275 }
19276 }
19277
19278 // Starting at $this->innermostTableLevel
19279 // Cascade back up nested tables: setting heights back up the tree
19280 for($lvl=$this->innermostTableLevel;$lvl>0;$lvl--) {
19281 for ($nid=1; $nid<=$this->tbctr[$lvl]; $nid++) {
19282 list($tableheight,$maxrowheight,$fullpage,$remainingpage, $maxfirstrowheight) = $this->_tableHeight($this->table[$lvl][$nid]); }
19283 }
19284
19285 // RESIZING ALGORITHM
19286
19287 if ($maxrowheight > $fullpage) { $recalculate = $this->tbsqrt($maxrowheight / $fullpage, $iteration); $iteration++; }
19288 else if ($this->table_rotate && $tableheight > $remainingpage && !$added_page) {
19289 // If can fit on remainder of page whilst respecting autosize value..
19290 if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->shrink_this_table_to_fit) {
19291 $recalculate = $this->tbsqrt($tableheight / $remainingpage, $iteration); $iteration++;
19292 }
19293 else {
19294 if (!$added_page) {
19295 $this->AddPage($this->CurOrientation);
19296 $added_page = true;
19297 $this->kwt_moved = true;
19298 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
19299 }
19300 // 0.001 to force it to recalculate
19301 $recalculate = (1 / $this->shrin_k) + 0.001; // undo any shrink
19302 }
19303 }
19304 else if ($this->table_keep_together || ($this->table[1][1]['nr']==1 && !$this->writingHTMLfooter)) {
19305 if ($tableheight > $fullpage) {
19306 if (($this->shrin_k * $this->tbsqrt($tableheight / $fullpage, $iteration)) <= $this->shrink_this_table_to_fit) {
19307 $recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); $iteration++;
19308 }
19309 else if ($this->tableMinSizePriority) {
19310 $this->table_keep_together = false;
19311 $recalculate = (1 / $this->shrin_k) + 0.001;
19312 }
19313 else {
19314 if (!$added_page && $this->y != $this->tMargin) {
19315 $this->AddPage($this->CurOrientation);
19316 $added_page = true;
19317 $this->kwt_moved = true;
19318 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
19319 }
19320 $recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); $iteration++;
19321 }
19322 }
19323 else if ($tableheight > $remainingpage) {
19324 // If can fit on remainder of page whilst respecting autosize value..
19325 if (($this->shrin_k * $this->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->shrink_this_table_to_fit) {
19326 $recalculate = $this->tbsqrt($tableheight / $remainingpage, $iteration); $iteration++;
19327 }
19328 else {
19329 if (!$added_page) {
19330 $this->AddPage($this->CurOrientation);
19331 $added_page = true;
19332 $this->kwt_moved = true;
19333 $this->tbrot_maxw = $this->h - ($this->y + $this->bMargin + 5) - $this->kwt_height;
19334 }
19335
19336 //$recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); $iteration++;
19337 $recalculate = (1 / $this->shrin_k) + 0.001; // undo any shrink
19338 }
19339 }
19340 else { $recalculate = 1; }
19341 }
19342 else { $recalculate = 1; }
19343 }
19344
19345
19346 if ($maxfirstrowheight > $remainingpage && !$added_page && !$this->table_rotate && !$this->ColActive && !$this->table_keep_together && !$this->writingHTMLheader && !$this->writingHTMLfooter) {
19347 $this->AddPage($this->CurOrientation);
19348 $this->kwt_moved = true;
19349 }
19350
19351 // keep-with-table: if page has advanced, print out buffer now, else done in fn. _Tablewrite()
19352 if ($this->kwt_saved && $this->kwt_moved) {
19353 $this->printkwtbuffer();
19354 $this->kwt_moved = false;
19355 $this->kwt_saved = false;
19356 }
19357
19358 if ($this->progressBar) { $this->UpdateProgressBar(7,30,' '); } // *PROGRESS-BAR*
19359 // Recursively writes all tables starting at top level
19360 $this->_tableWrite($this->table[1][1]);
19361
19362 if ($this->table_rotate && $this->tablebuffer) {
19363 $this->PageBreakTrigger=$this->h-$this->bMargin;
19364 $save_tr = $this->table_rotate;
19365 $save_y = $this->y;
19366 $this->table_rotate = 0;
19367 $this->y = $this->tbrot_y0;
19368 $h = $this->tbrot_w;
19369 $this->DivLn($h,$this->blklvl,true);
19370
19371 $this->table_rotate = $save_tr;
19372 $this->y = $save_y;
19373
19374 $this->printtablebuffer();
19375 }
19376 $this->table_rotate = 0;
19377 }
19378
19379
19380 $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
19381
19382 $this->maxPosR = max($this->maxPosR , ($this->x + $this->table[1][1]['w']));
19383
19384 $this->blockjustfinished=true;
19385 $this->lastblockbottommargin = $this->table[1][1]['margin']['B'];
19386 //Reset values
19387
19388 if (isset($this->table[1][1]['page_break_after'])) { $page_break_after = $this->table[1][1]['page_break_after']; }
19389 else { $page_break_after = ''; }
19390
19391 // Keep-with-table
19392 $this->kwt = false;
19393 $this->kwt_y0 = 0;
19394 $this->kwt_x0 = 0;
19395 $this->kwt_height = 0;
19396 $this->kwt_buffer = array();
19397 $this->kwt_Links = array();
19398 $this->kwt_Annots = array();
19399 $this->kwt_moved = false;
19400 $this->kwt_saved = false;
19401
19402 $this->kwt_Reference = array();
19403 $this->kwt_BMoutlines = array();
19404 $this->kwt_toc = array();
19405
19406 $this->shrin_k = 1;
19407 $this->shrink_this_table_to_fit = 0;
19408
19409 unset($this->table);
19410 $this->table=array(); //array
19411 $this->tableLevel=0;
19412 $this->tbctr=array();
19413 $this->innermostTableLevel=0;
19414 $this->cssmgr->tbCSSlvl = 0;
19415 $this->cssmgr->tablecascadeCSS = array();
19416
19417 unset($this->cell);
19418 $this->cell=array(); //array
19419
19420 $this->col=-1; //int
19421 $this->row=-1; //int
19422 $this->Reset();
19423
19424 $this->cellPaddingL = 0;
19425 $this->cellPaddingT = 0;
19426 $this->cellPaddingR = 0;
19427 $this->cellPaddingB = 0;
19428 $this->cMarginL = 0;
19429 $this->cMarginT = 0;
19430 $this->cMarginR = 0;
19431 $this->cMarginB = 0;
19432 $this->default_font_size = $this->original_default_font_size;
19433 $this->default_font = $this->original_default_font;
19434 $this->SetFontSize($this->default_font_size, false);
19435 $this->SetFont($this->default_font,'',0,false);
19436 $this->SetLineHeight();
19437 if (isset($this->blk[$this->blklvl]['InlineProperties'])) { $this->restoreInlineProperties($this->blk[$this->blklvl]['InlineProperties']);}
19438 if ($this->progressBar) { $this->UpdateProgressBar(7,100,' '); } // *PROGRESS-BAR*
19439
19440 if ($page_break_after) {
19441 $save_blklvl = $this->blklvl;
19442 $save_blk = $this->blk;
19443 $save_silp = $this->saveInlineProperties();
19444 $save_spanlvl = $this->spanlvl;
19445 $save_ilp = $this->InlineProperties;
19446 if ($this->blklvl>1) {
19447 // Close any open block tags
19448 for ($b= $this->blklvl;$b>0;$b--) { $this->CloseTag($this->blk[$b]['tag']); }
19449 // Output any text left in buffer
19450 if (count($this->textbuffer)) { $this->printbuffer($this->textbuffer); $this->textbuffer=array(); }
19451 }
19452 /*-- COLUMNS --*/
19453 $save_cols = false;
19454 if ($this->ColActive) {
19455 $save_cols = true;
19456 $save_nbcol = $this->NbCol; // other values of gap and vAlign will not change by setting Columns off
19457 $this->SetColumns(0);
19458 }
19459 /*-- END COLUMNS --*/
19460 if ($page_break_after == 'RIGHT') { $this->AddPage($this->CurOrientation,'NEXT-ODD','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
19461 else if ($page_break_after == 'LEFT') { $this->AddPage($this->CurOrientation,'NEXT-EVEN','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
19462 else { $this->AddPage($this->CurOrientation,'','','','','','', '','', '','','','','','',0,0,0,0,$pagesel); }
19463 if (!$this->restoreBlockPagebreaks) {
19464 $this->blklvl = 0;
19465 $this->lastblocklevelchange = 0;
19466 $this->blk = array();
19467 $this->initialiseBlock($this->blk[0]);
19468 $this->blk[0]['width'] =& $this->pgwidth;
19469 $this->blk[0]['inner_width'] =& $this->pgwidth;
19470 $this->blk[0]['blockContext'] = $this->blockContext;
19471 $properties = $this->cssmgr->MergeCSS('BLOCK','BODY','');
19472 $this->setCSS($properties,'','BODY');
19473 }
19474
19475 /*-- COLUMNS --*/
19476 if ($save_cols) {
19477 // Restore columns
19478 $this->SetColumns($save_nbcol,$this->colvAlign,$this->ColGap);
19479 }
19480 /*-- END COLUMNS --*/
19481 if ($this->restoreBlockPagebreaks) {
19482 $this->blk = $save_blk;
19483 // Re-open block tags
19484 $t = $this->blk[0]['tag'];
19485 $a = $this->blk[0]['attr'];
19486 $this->blklvl = 0;
19487 for ($b=0; $b<=$save_blklvl;$b++) {
19488 $tc = $t;
19489 $ac = $a;
19490 $t = $this->blk[$b+1]['tag'];
19491 $a = $this->blk[$b+1]['attr'];
19492 unset($this->blk[$b+1]);
19493 $this->OpenTag($tc,$ac);
19494 }
19495 $this->spanlvl = $save_spanlvl;
19496 $this->InlineProperties = $save_ilp;
19497 $this->restoreInlineProperties($save_silp);
19498 }
19499 }
19500
19501 }
19502 /*-- END TABLES --*/
19503
19504 /*-- LISTS --*/
19505 // *********** LISTS ********************
19506
19507 if($tag=='LI') {
19508 $this->lastoptionaltag = '';
19509 unset($this->cssmgr->listcascadeCSS[$this->cssmgr->listCSSlvl]);
19510 $this->cssmgr->listCSSlvl--;
19511 if (isset($this->listoccur[$this->listlvl]) && isset($this->InlineProperties['LIST'][$this->listlvl][$this->listoccur[$this->listlvl]])) { $this->restoreInlineProperties($this->InlineProperties['LIST'][$this->listlvl][$this->listoccur[$this->listlvl]]); }
19512 }
19513
19514
19515 if(($tag=='UL') or ($tag=='OL')) {
19516 $this->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
19517 unset($this->cssmgr->listcascadeCSS[$this->cssmgr->listCSSlvl]);
19518 $this->cssmgr->listCSSlvl--;
19519
19520 $this->lastoptionaltag = '';
19521 /*-- TABLES --*/
19522 // A simple list for inside a table
19523 if($this->tableLevel) {
19524 $this->listlist[$this->listlvl]['MAXNUM'] = $this->listnum; //save previous lvl's maxnum
19525 unset($this->listlist[$this->listlvl]);
19526 $this->listlvl--;
19527 if (isset($this->listlist[$this->listlvl]['MAXNUM'])) { $this->listnum = $this->listlist[$this->listlvl]['MAXNUM']; } // restore previous levels
19528 if ($this->listlvl == 0) { $this->listjustfinished = true; }
19529 return;
19530 }
19531 /*-- END TABLES --*/
19532
19533 if ($this->listlvl > 1) { // returning one level
19534 $this->listjustfinished=true;
19535 if (!empty($this->textbuffer)) {
19536 $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl],$this->listitemtype);
19537 }
19538 else {
19539 $this->listnum--;
19540 }
19541
19542 $this->textbuffer = array();
19543 $occur = $this->listoccur[$this->listlvl];
19544 $this->listlist[$this->listlvl][$occur]['MAXNUM'] = $this->listnum; //save previous lvl's maxnum
19545 $this->listlvl--;
19546 $occur = $this->listoccur[$this->listlvl];
19547 $this->listnum = $this->listlist[$this->listlvl][$occur]['MAXNUM']; // recover previous level's number
19548 $this->listtype = $this->listlist[$this->listlvl][$occur]['TYPE']; // recover previous level's type
19549 if ($this->InlineProperties['LIST'][$this->listlvl][$occur]) { $this->restoreInlineProperties($this->InlineProperties['LIST'][$this->listlvl][$occur]); }
19550
19551 }
19552 else { // We are closing the last OL/UL tag
19553 if (!empty($this->textbuffer)) {
19554 $this->listitem[] = array($this->listlvl,$this->listnum,$this->textbuffer,$this->listoccur[$this->listlvl],$this->listitemtype);
19555 }
19556 else {
19557 $this->listnum--;
19558 }
19559
19560 $occur = $this->listoccur[$this->listlvl];
19561 $this->listlist[$this->listlvl][$occur]['MAXNUM'] = $this->listnum;
19562 $this->textbuffer = array();
19563 $this->listlvl--;
19564
19565 $this->printlistbuffer();
19566 unset($this->InlineProperties['LIST']);
19567 // SPACING AFTER LIST (Top level only)
19568 $this->Ln(0);
19569 if ($this->list_margin_bottom) {
19570 $this->DivLn($this->list_margin_bottom,$this->blklvl,true,1); // collapsible
19571 }
19572 if (isset($this->blk[$this->blklvl]['InlineProperties'])) { $this->restoreInlineProperties($this->blk[$this->blklvl]['InlineProperties']);}
19573 $this->listjustfinished = true;
19574 $this->cssmgr->listCSSlvl = 0;
19575 $this->cssmgr->listcascadeCSS = array();
19576 $this->blockjustfinished=true;
19577 $this->lastblockbottommargin = $this->list_margin_bottom;
19578 }
19579 }
19580 /*-- END LISTS --*/
19581
19582
19583 }
19584
19585
19586 /*-- TABLES --*/
19587 // This function determines the shrink factor when resizing tables
19588 // val is the table_height / page_height_available
19589 // returns a scaling factor used as $shrin_k to resize the table
19590 // Overcompensating will be quicker but may unnecessarily shrink table too much
19591 // Undercompensating means it will reiterate more times (taking more processing time)
19592 function tbsqrt($val, $iteration=3) {
19593 $k = 4; // Alters number of iterations until it returns $val itself - Must be > 2
19594 // Probably best guess and most accurate
19595 if ($iteration==1) return sqrt($val);
19596 // Faster than using sqrt (because it won't undercompensate), and gives reasonable results
19597 //return 1+(($val-1)/2);
19598 $x = 2-(($iteration-2)/($k-2));
19599 if ($x == 0) { $ret = $val+0.00001; }
19600 else if ($x < 0) { $ret = 1 + ( pow(2, ($iteration-2-$k))/1000 ); }
19601 else { $ret = 1+(($val-1)/$x); }
19602 return $ret;
19603 }
19604 /*-- END TABLES --*/
19605
19606
19607 /*-- LISTS --*/
19608 function printlistbuffer() {
19609 //Save x coordinate
19610 $x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
19611 $this->cMarginL = 0;
19612 $this->cMarginR = 0;
19613 $currIndentLvl = -1;
19614 $lastIndent = array();
19615 $bak_page = $this->page;
19616 $indent = 0;
19617 foreach($this->listitem as $item)
19618 {
19619 // COLS
19620 $oldcolumn = $this->CurrCol;
19621
19622 $this->bulletarray = array();
19623 //Get list's buffered data
19624 $this->listlvl = $lvl = $item[0];
19625 $num = $item[1];
19626 $this->textbuffer = $item[2];
19627 $occur = $item[3];
19628 if ($item[4]) { $type = $item[4]; } // listitemtype
19629 else { $type = $this->listlist[$lvl][$occur]['TYPE']; }
19630 $maxnum = $this->listlist[$lvl][$occur]['MAXNUM'];
19631 $this->restoreInlineProperties($this->InlineProperties['LIST'][$lvl][$occur]);
19632 $this->SetFont($this->FontFamily,$this->FontStyle,$this->FontSizePt,true,true); // force to write
19633 $clh = $this->FontSize;
19634
19635 $this->SetLineHeight($this->FontSizePt,$this->list_lineheight[$lvl][$occur]);
19636 $this->listOcc = $occur;
19637 $this->listnum = $num;
19638
19639 if (isset($this->list_align[$this->listlvl][$occur])) { $this->divalign = $this->list_align[$this->listlvl][$occur]; }
19640 else {
19641 if (isset($this->blk[$this->blklvl]['direction']) && $this->blk[$this->blklvl]['direction']=='rtl') { $this->divalign = 'R'; }
19642 else { $this->divalign = 'L'; }
19643 }
19644
19645 // Set the bullet fontsize
19646 $bullfs = $this->InlineProperties['LISTITEM'][$lvl][$occur][$num]['size'];
19647
19648 $space_width = $this->GetCharWidth(' ',false) * 1.5;
19649
19650 //Set default width & height values
19651 $this->divwidth = $this->blk[$this->blklvl]['inner_width'];
19652 $this->divheight = $this->lineheight;
19653 $typefont = $this->FontFamily;
19654 if (preg_match('/U\+([a-fA-F0-9]+)/i',$type,$m)) {
19655 if ($this->_charDefined($this->CurrentFont['cw'],hexdec($m[1]))) { $list_item_marker = codeHex2utf($m[1]); }
19656 else { $list_item_marker = '-'; }
19657 $blt_width = $this->GetStringWidth($list_item_marker);
19658 $typefont = '';
19659 if (preg_match('/rgb\(.*?\)/',$type,$m)) {
19660 $list_item_color = $this->ConvertColor($m[0]);
19661 }
19662 }
19663 else {
19664 $list_item_color = false;
19665
19666 switch($type) //Format type
19667 {
19668 case '1':
19669 if ($this->listDir == 'rtl') { $list_item_marker = $this->list_number_suffix . $num; }
19670 else { $list_item_marker = $num . $this->list_number_suffix; }
19671 $blt_width = $this->GetStringWidth(str_repeat('5',strlen($maxnum)).$this->list_number_suffix);
19672 break;
19673 case 'none':
19674 $list_item_marker = '';
19675 $blt_width = 0;
19676 break;
19677 case 'A':
19678 $anum = $this->dec2alpha($num,true);
19679 $maxnum = $this->dec2alpha($maxnum,true);
19680 if ($this->listDir == 'rtl') { $list_item_marker = $this->list_number_suffix . $anum; }
19681 else { $list_item_marker = $anum . $this->list_number_suffix; }
19682 $blt_width = $this->GetStringWidth(str_repeat('W',strlen($maxnum)).$this->list_number_suffix);
19683 break;
19684 case 'a':
19685 $anum = $this->dec2alpha($num,false);
19686 $maxnum = $this->dec2alpha($maxnum,false);
19687 if ($this->listDir == 'rtl') { $list_item_marker = $this->list_number_suffix . $anum; }
19688 else { $list_item_marker = $anum . $this->list_number_suffix; }
19689 $blt_width = $this->GetStringWidth(str_repeat('m',strlen($maxnum)).$this->list_number_suffix);
19690 break;
19691 case 'I':
19692 $anum = $this->dec2roman($num,true);
19693 if ($this->listDir == 'rtl') { $list_item_marker = $this->list_number_suffix . $anum; }
19694 else { $list_item_marker = $anum . $this->list_number_suffix; }
19695
19696 if ($maxnum>87) { $bbit = 87; }
19697 else if ($maxnum>86) { $bbit = 86; }
19698 else if ($maxnum>37) { $bbit = 38; }
19699 else if ($maxnum>36) { $bbit = 37; }
19700 else if ($maxnum>27) { $bbit = 28; }
19701 else if ($maxnum>26) { $bbit = 27; }
19702 else if ($maxnum>17) { $bbit = 18; }
19703 else if ($maxnum>16) { $bbit = 17; }
19704 else if ($maxnum>7) { $bbit = 8; }
19705 else if ($maxnum>6) { $bbit = 7; }
19706 else if ($maxnum>3) { $bbit = 4; }
19707 else { $bbit = $maxnum; }
19708 $maxlnum = $this->dec2roman($bbit,true);
19709 $blt_width = $this->GetStringWidth($maxlnum.$this->list_number_suffix);
19710 break;
19711 case 'i':
19712 $anum = $this->dec2roman($num,false);
19713 if ($this->listDir == 'rtl') { $list_item_marker = $this->list_number_suffix . $anum; }
19714 else { $list_item_marker = $anum . $this->list_number_suffix; }
19715
19716 if ($maxnum>87) { $bbit = 87; }
19717 else if ($maxnum>86) { $bbit = 86; }
19718 else if ($maxnum>37) { $bbit = 38; }
19719 else if ($maxnum>36) { $bbit = 37; }
19720 else if ($maxnum>27) { $bbit = 28; }
19721 else if ($maxnum>26) { $bbit = 27; }
19722 else if ($maxnum>17) { $bbit = 18; }
19723 else if ($maxnum>16) { $bbit = 17; }
19724 else if ($maxnum>7) { $bbit = 8; }
19725 else if ($maxnum>6) { $bbit = 7; }
19726 else if ($maxnum>3) { $bbit = 4; }
19727 else { $bbit = $maxnum; }
19728 $maxlnum = $this->dec2roman($bbit,false);
19729
19730 $blt_width = $this->GetStringWidth($maxlnum.$this->list_number_suffix);
19731 break;
19732 case 'disc':
19733 if ($this->PDFA || $this->PDFX) {
19734 if ($this->_charDefined($this->CurrentFont['cw'],8226)) { $list_item_marker = "\xe2\x80\xa2"; } // &#8226;
19735 else { $list_item_marker = '-'; }
19736 $blt_width = $this->GetCharWidth($list_item_marker);
19737 break;
19738 }
19739 $list_item_marker = chr(108); // bullet disc in Zapfdingbats 'l'
19740 $typefont = 'czapfdingbats';
19741 $blt_width = (0.791 * $this->FontSize/2.5);
19742 break;
19743 case 'circle':
19744 if ($this->PDFA || $this->PDFX) {
19745 if ($this->_charDefined($this->CurrentFont['cw'],9900)) { $list_item_marker = "\xe2\x9a\xac"; } // &#9900;
19746 else { $list_item_marker = '-'; }
19747 $blt_width = $this->GetCharWidth($list_item_marker);
19748 break;
19749 }
19750 $list_item_marker = chr(109); // circle in Zapfdingbats 'm'
19751 $typefont = 'czapfdingbats';
19752 $blt_width = (0.873 * $this->FontSize/2.5);
19753 break;
19754 case 'square':
19755 if ($this->PDFA || $this->PDFX) {
19756 if ($this->_charDefined($this->CurrentFont['cw'],9642)) { $list_item_marker = "\xe2\x96\xaa"; } // &#9642;
19757 else { $list_item_marker = '-'; }
19758 $blt_width = $this->GetCharWidth($list_item_marker);
19759 break;
19760 }
19761 $list_item_marker = chr(110); //black square in Zapfdingbats font 'n'
19762 $typefont = 'czapfdingbats';
19763 $blt_width = (0.761 * $this->FontSize/2.5);
19764 break;
19765
19766 /* CSS3 list-styles numeric + I added tamil
19767 arabic-indic | bengali | cambodian | devanagari | gujarati | gurmukhi | kannada | khmer | lao | malayalam | mongolian | myanmar | oriya | persian | telugu | tibetan | thai | urdu
19768 */
19769 case 'arabic-indic':
19770 $cp = 0x0660;
19771 $rnum = $this->dec2other($num, $cp);
19772 $list_item_marker = $this->list_number_suffix . $rnum; // RTL
19773 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, $cp),strlen($maxnum)).$this->list_number_suffix);
19774 break;
19775 case 'persian':
19776 case 'urdu':
19777 $cp = 0x06F0;
19778 $rnum = $this->dec2other($num, $cp);
19779 $list_item_marker = $this->list_number_suffix . $rnum; // RTL
19780 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, $cp),strlen($maxnum)).$this->list_number_suffix);
19781 break;
19782 case 'bengali':
19783 $cp = 0x09E6;
19784 $rnum = $this->dec2other($num, $cp);
19785 $list_item_marker = $rnum . $this->list_number_suffix;
19786 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, $cp),strlen($maxnum)).$this->list_number_suffix);
19787 break;
19788 case 'devanagari':
19789 $cp = 0x0966;
19790 $rnum = $this->dec2other($num, $cp);
19791 $list_item_marker = $rnum . $this->list_number_suffix;
19792 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, $cp),strlen($maxnum)).$this->list_number_suffix);
19793 break;
19794 case 'gujarati':
19795 $cp = 0x0AE6;
19796 $rnum = $this->dec2other($num, $cp);
19797 $list_item_marker = $rnum . $this->list_number_suffix;
19798 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, $cp),strlen($maxnum)).$this->list_number_suffix);
19799 break;
19800 case 'gurmukhi':
19801 $cp = 0x0A66;
19802 $rnum = $this->dec2other($num, $cp);
19803 $list_item_marker = $rnum . $this->list_number_suffix;
19804 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, $cp),strlen($maxnum)).$this->list_number_suffix);
19805 break;
19806 case 'kannada':
19807 $cp = 0x0CE6;
19808 $rnum = $this->dec2other($num, $cp);
19809 $list_item_marker = $rnum . $this->list_number_suffix;
19810 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, $cp),strlen($maxnum)).$this->list_number_suffix);
19811 break;
19812 case 'malayalam':
19813 $cp = 0x0D66;
19814 $rnum = $this->dec2other($num, $cp);
19815 $list_item_marker = $rnum . $this->list_number_suffix;
19816 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(6, $cp),strlen($maxnum)).$this->list_number_suffix);
19817 break;
19818 case 'oriya':
19819 $cp = 0x0B66;
19820 $rnum = $this->dec2other($num, $cp);
19821 $list_item_marker = $rnum . $this->list_number_suffix;
19822 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, $cp),strlen($maxnum)).$this->list_number_suffix);
19823 break;
19824 case 'telugu':
19825 $cp = 0x0C66;
19826 $rnum = $this->dec2other($num, $cp);
19827 $list_item_marker = $rnum . $this->list_number_suffix;
19828 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(3, $cp),strlen($maxnum)).$this->list_number_suffix);
19829 break;
19830 case 'tamil':
19831 $cp = 0x0BE6;
19832 $rnum = $this->dec2other($num, $cp);
19833 $list_item_marker = $rnum . $this->list_number_suffix;
19834 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(9, $cp),strlen($maxnum)).$this->list_number_suffix);
19835 break;
19836 case 'thai':
19837 $cp = 0x0E50;
19838 $rnum = $this->dec2other($num, $cp);
19839 $list_item_marker = $rnum . $this->list_number_suffix;
19840 $blt_width = $this->GetStringWidth(str_repeat($this->dec2other(5, $cp),strlen($maxnum)).$this->list_number_suffix);
19841 break;
19842 default:
19843 if ($this->listDir == 'rtl') { $list_item_marker = $this->list_number_suffix . $num; }
19844 else { $list_item_marker = $num . $this->list_number_suffix; }
19845 $blt_width = $this->GetStringWidth(str_repeat('5',strlen($maxnum)).$this->list_number_suffix);
19846 break;
19847 }
19848 }
19849
19850 if (isset($item[5]) && $item[5]) { $list_item_marker = ''; }
19851
19852 if ($currIndentLvl < $lvl) {
19853 if ($lvl > 1 || $this->list_indent_first_level) {
19854 $indent += $this->list_indent[$lvl][$occur];
19855 $lastIndent[$lvl] = $this->list_indent[$lvl][$occur];
19856 }
19857 }
19858 else if ($currIndentLvl > $lvl) {
19859 while ($currIndentLvl > $lvl) {
19860 $indent -= $lastIndent[$currIndentLvl];
19861 $currIndentLvl--;
19862 }
19863 }
19864 $currIndentLvl = $lvl;
19865
19866
19867 /*-- RTL --*/
19868
19869 if ($this->listDir == 'rtl') {
19870 // list_align_style Determines alignment of numbers in numbered lists
19871 if ($this->list_align_style == 'L') { $lalign = 'R'; }
19872 else { $lalign = 'L'; }
19873 $this->divwidth = $this->blk[$this->blklvl]['width'] - ($indent + $blt_width + $space_width) ;
19874 $xb = $this->blk[$this->blklvl]['inner_width'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_left'] - $indent - $blt_width; //Bullet position (relative)
19875 //Output bullet
19876 $this->bulletarray = array('w'=>$blt_width,'h'=>$clh,'txt'=>$list_item_marker,'x'=>$xb,'align'=>$lalign,'font'=>$typefont,'level'=>$lvl, 'occur'=>$occur, 'num'=>$num, 'fontsize'=>$bullfs, 'col'=>$list_item_color );
19877 $this->x = $x;
19878 }
19879 else {
19880 /*-- END RTL --*/
19881
19882 if ($this->list_align_style == 'L') { $lalign = 'L'; }
19883 else { $lalign = 'R'; }
19884 $this->divwidth = $this->blk[$this->blklvl]['width'] - ($indent + $blt_width + $space_width) ;
19885 $xb = $this->blk[$this->blklvl]['padding_left'] + $this->blk[$this->blklvl]['border_left']['w'] - $blt_width - $space_width;
19886 //Output bullet
19887 $this->bulletarray = array('w'=>$blt_width,'h'=>$clh,'txt'=>$list_item_marker,'x'=>$xb,'align'=>$lalign,'font'=>$typefont,'level'=>$lvl, 'occur'=>$occur, 'num'=>$num, 'fontsize'=>$bullfs, 'col'=>$list_item_color );
19888 $this->x = $x + $indent + $blt_width + $space_width;
19889 } // *RTL*
19890
19891 //Print content
19892 $this->printbuffer($this->textbuffer,'',false,true);
19893 $this->textbuffer=array();
19894
19895 // Added to correct for OddEven Margins
19896 if ($this->page != $bak_page) {
19897 if (($this->page-$bak_page) % 2 == 1) {
19898 $x += $this->MarginCorrection;
19899 }
19900 $bak_page = $this->page;
19901 }
19902 /*-- COLUMNS --*/
19903 // OR COLUMN CHANGE
19904 if ($this->CurrCol != $oldcolumn) {
19905 if ($this->directionality == 'rtl') { // *RTL*
19906 $x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap); // *RTL*
19907 } // *RTL*
19908 else { // *RTL*
19909 $x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap);
19910 } // *RTL*
19911 $oldcolumn = $this->CurrCol;
19912 }
19913 /*-- END COLUMNS --*/
19914
19915 }
19916
19917 //Reset all used values
19918 $this->listoccur = array();
19919 $this->listitem = array();
19920 $this->listlist = array();
19921 $this->listlvl = 0;
19922 $this->listnum = 0;
19923 $this->listtype = '';
19924 $this->textbuffer = array();
19925 $this->divwidth = 0;
19926 $this->divheight = 0;
19927 $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'];
19928 }
19929 /*-- END LISTS --*/
19930
19931 function _saveTextBuffer($t, $link = '', $intlink = '') {
19932 // $this->textbuffer[] = array($t,$link,$this->currentfontstyle,$this->colorarray,$this->currentfontfamily,$this->SUP,$this->SUB,$intlink,$this->strike,$this->textparam,$this->spanbgcolorarray,$this->currentfontsize,$this->ReqFontStyle,$this->kerning,$this->lSpacingCSS,$this->wSpacingCSS,$this->spanborddet, $this->textshadow);
19933 // mPDF 5.6.14
19934 $arr = array();
19935 $arr[0] = $t;
19936 if (isset($link) && $link) $arr[1] = $link;
19937 $arr[2] = $this->currentfontstyle;
19938 if (isset($this->colorarray) && $this->colorarray) $arr[3] = $this->colorarray;
19939 $arr[4] = $this->currentfontfamily;
19940 if (isset($this->SUP) && $this->SUP) $arr[5] = $this->SUP;
19941 if (isset($this->SUB) && $this->SUB) $arr[6] = $this->SUB;
19942 if (isset($intlink) && $intlink) $arr[7] = $intlink;
19943 if (isset($this->strike) && $this->strike) $arr[8] = $this->strike;
19944 if (isset($this->textparam) && $this->textparam) $arr[9] = $this->textparam;
19945 if (isset($this->spanbgcolorarray) && $this->spanbgcolorarray) $arr[10] = $this->spanbgcolorarray;
19946 $arr[11] = $this->currentfontsize;
19947 if (isset($this->ReqFontStyle) && $this->ReqFontStyle) $arr[12] = $this->ReqFontStyle;
19948 if (isset($this->kerning) && $this->kerning) $arr[13] = $this->kerning;
19949 if (isset($this->lSpacingCSS) && $this->lSpacingCSS) $arr[14] = $this->lSpacingCSS;
19950 if (isset($this->wSpacingCSS) && $this->wSpacingCSS) $arr[15] = $this->wSpacingCSS;
19951 if (isset($this->spanborddet) && $this->spanborddet) $arr[16] = $this->spanborddet;
19952 if (isset($this->textshadow) && $this->textshadow) $arr[17] = $this->textshadow;
19953 $this->textbuffer[] = $arr;
19954 }
19955
19956 function _saveCellTextBuffer($t, $link = '', $intlink = '') {
19957 // $this->cell[$this->row][$this->col]['textbuffer'][] = array($t,$link,$this->currentfontstyle,$this->colorarray,$this->currentfontfamily,$this->SUP,$this->SUB,$intlink,$this->strike,$this->textparam,$this->spanbgcolorarray,$this->currentfontsize,$this->ReqFontStyle,$this->kerning,$this->lSpacingCSS,$this->wSpacingCSS,$this->spanborddet, $this->textshadow);
19958 // mPDF 5.6.14
19959 $arr = array();
19960 $arr[0] = $t;
19961 if (isset($link) && $link) $arr[1] = $link;
19962 $arr[2] = $this->currentfontstyle;
19963 if (isset($this->colorarray) && $this->colorarray) $arr[3] = $this->colorarray;
19964 $arr[4] = $this->currentfontfamily;
19965 if (isset($this->SUP) && $this->SUP) $arr[5] = $this->SUP;
19966 if (isset($this->SUB) && $this->SUB) $arr[6] = $this->SUB;
19967 if (isset($intlink) && $intlink) $arr[7] = $intlink;
19968 if (isset($this->strike) && $this->strike) $arr[8] = $this->strike;
19969 if (isset($this->textparam) && $this->textparam) $arr[9] = $this->textparam;
19970 if (isset($this->spanbgcolorarray) && $this->spanbgcolorarray) $arr[10] = $this->spanbgcolorarray;
19971 $arr[11] = $this->currentfontsize;
19972 if (isset($this->ReqFontStyle) && $this->ReqFontStyle) $arr[12] = $this->ReqFontStyle;
19973 if (isset($this->kerning) && $this->kerning) $arr[13] = $this->kerning;
19974 if (isset($this->lSpacingCSS) && $this->lSpacingCSS) $arr[14] = $this->lSpacingCSS;
19975 if (isset($this->wSpacingCSS) && $this->wSpacingCSS) $arr[15] = $this->wSpacingCSS;
19976 if (isset($this->spanborddet) && $this->spanborddet) $arr[16] = $this->spanborddet;
19977 if (isset($this->textshadow) && $this->textshadow) $arr[17] = $this->textshadow;
19978 $this->cell[$this->row][$this->col]['textbuffer'][] = $arr;
19979 }
19980
19981
19982 function printbuffer($arrayaux,$blockstate=0,$is_table=false,$is_list=false)
19983 {
19984 // $blockstate = 0; // NO margins/padding
19985 // $blockstate = 1; // Top margins/padding only
19986 // $blockstate = 2; // Bottom margins/padding only
19987 // $blockstate = 3; // Top & bottom margins/padding
19988 $this->spanbgcolorarray = '';
19989 $this->spanbgcolor = false;
19990 $this->spanborder = false;
19991 $this->spanborddet = array();
19992 $paint_ht_corr = 0;
19993
19994 /*-- CSS-FLOAT --*/
19995 if (count($this->floatDivs)) {
19996 list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl);
19997 if (($this->blk[$this->blklvl]['inner_width']-$l_width-$r_width) < (2*$this->GetCharWidth('W',false))) {
19998 // Too narrow to fit - try to move down past L or R float
19999 if ($l_max < $r_max && ($this->blk[$this->blklvl]['inner_width']-$r_width) > (2*$this->GetCharWidth('W',false))) {
20000 $this->ClearFloats('LEFT', $this->blklvl);
20001 }
20002 else if ($r_max < $l_max && ($this->blk[$this->blklvl]['inner_width']-$l_width) > (2*$this->GetCharWidth('W',false))) {
20003 $this->ClearFloats('RIGHT', $this->blklvl);
20004 }
20005 else { $this->ClearFloats('BOTH', $this->blklvl); }
20006 }
20007 }
20008 /*-- END CSS-FLOAT --*/
20009 $bak_y = $this->y;
20010 $bak_x = $this->x;
20011 $align = '';
20012 if (!$is_table && !$is_list) {
20013 if (isset($this->blk[$this->blklvl]['align']) && $this->blk[$this->blklvl]['align']) { $align = $this->blk[$this->blklvl]['align']; }
20014 // Block-align is set by e.g. <.. align="center"> Takes priority for this block but not inherited
20015 if (isset($this->blk[$this->blklvl]['block-align']) && $this->blk[$this->blklvl]['block-align']) { $align = $this->blk[$this->blklvl]['block-align']; }
20016 if (isset($this->blk[$this->blklvl]['direction'])) $blockdir = $this->blk[$this->blklvl]['direction'];
20017 else $blockdir = "";
20018 $this->divwidth = $this->blk[$this->blklvl]['width'];
20019 }
20020 else {
20021 $align = $this->divalign;
20022 if ($is_table) { $blockdir = $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['direction']; }
20023 else { $blockdir = $this->listDir; }
20024 }
20025 $oldpage = $this->page;
20026
20027 // ADDED for Out of Block now done as Flowing Block
20028 if ($this->divwidth == 0) {
20029 $this->divwidth = $this->pgwidth;
20030 }
20031
20032 if (!$is_table && !$is_list) { $this->SetLineHeight($this->FontSizePt,$this->blk[$this->blklvl]['line_height']); }
20033 $this->divheight = $this->lineheight;
20034 $old_height = $this->divheight;
20035
20036 // As a failsafe - if font has been set but not output to page
20037 $this->SetFont($this->default_font,'',$this->default_font_size,true,true); // force output to page
20038
20039 $array_size = count($arrayaux);
20040 $this->newFlowingBlock( $this->divwidth,$this->divheight,$align,$is_table,$is_list,$blockstate,true,$blockdir);
20041
20042 // Added - Otherwise <div><div><p> did not output top margins/padding for 1st/2nd div
20043 if ($array_size == 0) { $this->finishFlowingBlock(true); } // true = END of flowing block
20044
20045 for($i=0;$i < $array_size; $i++)
20046 {
20047 // COLS
20048 $oldcolumn = $this->CurrCol;
20049
20050 $vetor = $arrayaux[$i];
20051 if ($i == 0 and $vetor[0] != "\n" and !$this->ispre) {
20052 $vetor[0] = ltrim($vetor[0]);
20053 }
20054
20055 // FIXED TO ALLOW IT TO SHOW '0'
20056 if (empty($vetor[0]) && !($vetor[0]==='0') && empty($vetor[7])) { //Ignore empty text and not carrying an internal link
20057 //Check if it is the last element. If so then finish printing the block
20058 if ($i == ($array_size-1)) { $this->finishFlowingBlock(true); } // true = END of flowing block
20059 continue;
20060 }
20061
20062
20063 //Activating buffer properties
20064 if(isset($vetor[11]) and $vetor[11] != '') { // Font Size
20065 if ($is_table && $this->shrin_k) {
20066 $this->SetFontSize($vetor[11]/$this->shrin_k,false);
20067 }
20068 else {
20069 $this->SetFontSize($vetor[11],false);
20070 }
20071 }
20072
20073 if(isset($vetor[17]) && !empty($vetor[17])) { //TextShadow
20074 $this->textshadow = $vetor[17];
20075 }
20076 if(isset($vetor[16]) && !empty($vetor[16])) { //Border
20077 $this->spanborddet = $vetor[16];
20078 $this->spanborder = true;
20079 }
20080
20081 if(isset($vetor[15])) { // Word spacing
20082 $this->wSpacingCSS = $vetor[15];
20083 if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') {
20084 $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize);
20085 }
20086 }
20087 if(isset($vetor[14])) { // Letter spacing
20088 $this->lSpacingCSS = $vetor[14];
20089 if (($this->lSpacingCSS || $this->lSpacingCSS==='0') && strtoupper($this->lSpacingCSS) != 'NORMAL') {
20090 $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize);
20091 }
20092 }
20093 if(isset($vetor[13])) { // Font Kerning
20094 $this->kerning = $vetor[13];
20095 }
20096
20097
20098 if(isset($vetor[10]) and !empty($vetor[10])) //Background color
20099 {
20100 $this->spanbgcolorarray = $vetor[10];
20101 $this->spanbgcolor = true;
20102 }
20103 if(isset($vetor[9]) and !empty($vetor[9])) // Text parameters - Outline + hyphens
20104 {
20105 $this->textparam = $vetor[9] ; // mPDF 5.6.14
20106 $this->SetTextOutline($this->textparam); // mPDF 5.6.07
20107 }
20108 if(isset($vetor[8]) and $vetor[8] === true) // strike-through the text
20109 {
20110 $this->strike = true;
20111 }
20112 if(isset($vetor[7]) and $vetor[7] != '') // internal target: <a name="anyvalue">
20113 {
20114 $ily = $this->y;
20115 if ($this->keep_block_together) { $this->internallink[$vetor[7]] = array("Y"=>$ily,"PAGE"=>$this->page, "kt"=>true ); }
20116 else if ($this->table_rotate) { $this->internallink[$vetor[7]] = array("Y"=>$ily,"PAGE"=>$this->page, "tbrot"=>true ); }
20117 else if ($this->kwt) { $this->internallink[$vetor[7]] = array("Y"=>$ily,"PAGE"=>$this->page, "kwt"=>true ); }
20118 else if ($this->ColActive) { $this->internallink[$vetor[7]] = array("Y"=>$ily,"PAGE"=>$this->page, "col"=>$this->CurrCol ); }
20119 else
20120 $this->internallink[$vetor[7]] = array("Y"=>$ily,"PAGE"=>$this->page );
20121 if (empty($vetor[0])) { //Ignore empty text
20122 //Check if it is the last element. If so then finish printing the block
20123 if ($i == ($array_size-1)) { $this->finishFlowingBlock(true); } // true = END of flowing block
20124 continue;
20125 }
20126 }
20127 if(isset($vetor[6]) and $vetor[6] === true) // Subscript
20128 {
20129 $this->SUB = true;
20130 }
20131 if(isset($vetor[5]) and $vetor[5] === true) // Superscript
20132 {
20133 $this->SUP = true;
20134 }
20135 if(isset($vetor[4]) and $vetor[4] != '') { // Font Family
20136 $font = $this->SetFont($vetor[4],$this->FontStyle,0,false);
20137 }
20138 if (!empty($vetor[3])) //Font Color
20139 {
20140 $cor = $vetor[3];
20141 $this->SetTColor($cor);
20142 }
20143 if(isset($vetor[2]) and $vetor[2] != '') //Bold,Italic,Underline styles
20144 {
20145 $this->SetStyles($vetor[2]);
20146 }
20147
20148 if(isset($vetor[12]) and $vetor[12] != '') { //Requested Bold,Italic,Underline
20149 $this->ReqFontStyle = $vetor[12];
20150 }
20151 if(isset($vetor[1]) and $vetor[1] != '') //LINK
20152 {
20153 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.)
20154 {
20155 //Repeated reference to same anchor?
20156 while(array_key_exists($vetor[1],$this->internallink)) $vetor[1]="#".$vetor[1];
20157 $this->internallink[$vetor[1]] = $this->AddLink();
20158 $vetor[1] = $this->internallink[$vetor[1]];
20159 }
20160 $this->HREF = $vetor[1]; // HREF link style set here ******
20161 }
20162
20163 // SPECIAL CONTENT - IMAGES & FORM OBJECTS
20164 //Print-out special content
20165
20166 if (substr($vetor[0],0,3) == "\xbb\xa4\xac") { //identifier has been identified!
20167
20168 $objattr = $this->_getObjAttr($vetor[0]);
20169
20170 /*-- TABLES --*/
20171 if ($objattr['type'] == 'nestedtable') {
20172 if ($objattr['nestedcontent']) {
20173 $level = $objattr['level'];
20174 $table = &$this->table[$level][$objattr['table']];
20175 if ($this->cacheTables) {
20176 $fh = fopen($table['cache'], "r+b");
20177 $cell = $this->_uncacheCell($table['cells'][$objattr['row']][$objattr['col']], '', $fh);
20178 }
20179 else {
20180 $fh = null;
20181 $cell = &$table['cells'][$objattr['row']][$objattr['col']];
20182 }
20183 $this->finishFlowingBlock(false,'nestedtable');
20184 $save_dw = $this->divwidth ;
20185 $save_buffer = $this->cellBorderBuffer;
20186 $this->cellBorderBuffer = array();
20187 $ncx = $this->x;
20188 list($dummyx,$w) = $this->_tableGetWidth($table, $objattr['row'], $objattr['col'], $fh);
20189 $ntw = $this->table[($level+1)][$objattr['nestedcontent']]['w']; // nested table width
20190 if (!$this->simpleTables){
20191 if ($this->packTableData) {
20192 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($cell['borderbin']);
20193 }
20194 else {
20195 $br = $cell['border_details']['R']['w'];
20196 $bl = $cell['border_details']['L']['w'];
20197 }
20198 if ($table['borders_separate']) {
20199 $innerw = $w - $bl - $br - $cell['padding']['L'] - $cell['padding']['R'] - $table['border_spacing_H'];
20200 }
20201 else {
20202 $innerw = $w - $bl/2 - $br/2 - $cell['padding']['L'] - $cell['padding']['R'];
20203 }
20204 }
20205 else if ($this->simpleTables){
20206 if ($table['borders_separate']) {
20207 $innerw = $w - $table['simple']['border_details']['L']['w'] - $table['simple']['border_details']['R']['w'] - $cell['padding']['L'] - $cell['padding']['R'] - $table['border_spacing_H'];
20208 }
20209 else {
20210 $innerw = $w - $table['simple']['border_details']['L']['w']/2 - $table['simple']['border_details']['R']['w']/2 - $cell['padding']['L'] - $cell['padding']['R'];
20211 }
20212 }
20213 if ($cell['a']=='C' || $this->table[($level+1)][$objattr['nestedcontent']]['a']=='C') {
20214 $ncx += ($innerw-$ntw)/2;
20215 }
20216 elseif ($cell['a']=='R' || $this->table[($level+1)][$objattr['nestedcontent']]['a']=='R') {
20217 $ncx += $innerw- $ntw;
20218 }
20219 $this->x = $ncx ;
20220 if ($this->cacheTables) { fclose($fh); }
20221
20222 $this->_tableWrite($this->table[($level+1)][$objattr['nestedcontent']]);
20223 $this->cellBorderBuffer = $save_buffer;
20224 $this->x = $bak_x ;
20225 $this->divwidth = $save_dw;
20226 $this->newFlowingBlock( $this->divwidth,$this->divheight,$align,$is_table,$is_list,$blockstate,false,$blockdir);
20227 }
20228 }
20229 else {
20230 /*-- END TABLES --*/
20231 if ($is_table) { // *TABLES*
20232 $maxWidth = $this->divwidth; // *TABLES*
20233 } // *TABLES*
20234 else { // *TABLES*
20235 $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']);
20236 } // *TABLES*
20237
20238 /*-- CSS-IMAGE-FLOAT --*/
20239 // If float (already) exists at this level
20240 if (isset($this->floatmargins['R']) && $this->y <= $this->floatmargins['R']['y1'] && $this->y >= $this->floatmargins['R']['y0']) { $maxWidth -= $this->floatmargins['R']['w']; }
20241 if (isset($this->floatmargins['L']) && $this->y <= $this->floatmargins['L']['y1'] && $this->y >= $this->floatmargins['L']['y0']) { $maxWidth -= $this->floatmargins['L']['w']; }
20242 /*-- END CSS-IMAGE-FLOAT --*/
20243
20244 list($skipln) = $this->inlineObject($objattr['type'], '', $this->y, $objattr,$this->lMargin, ($this->flowingBlockAttr['contentWidth']/_MPDFK), $maxWidth, $this->flowingBlockAttr['height'], false, $is_table);
20245 // 1 -> New line needed because of width
20246 // -1 -> Will fit width on line but NEW PAGE REQUIRED because of height
20247 // -2 -> Will not fit on line therefore needs new line but thus NEW PAGE REQUIRED
20248 $iby = $this->y;
20249 $oldpage = $this->page;
20250 $oldcol = $this->CurrCol;
20251 if (($skipln == 1 || $skipln == -2) && !isset($objattr['float'])) {
20252 $this->finishFlowingBlock(false,$objattr['type']);
20253 $this->newFlowingBlock( $this->divwidth,$this->divheight,$align,$is_table,$is_list,$blockstate,false,$blockdir);
20254 }
20255 $thispage = $this->page;
20256 if ($this->CurrCol!=$oldcol) { $changedcol = true; }
20257 else { $changedcol=false; }
20258
20259 // the previous lines can already have triggered page break or column change
20260 if (!$changedcol && $skipln <0 && $this->AcceptPageBreak() && $thispage==$oldpage) {
20261
20262 $this->AddPage($this->CurOrientation);
20263
20264 // Added to correct Images already set on line before page advanced
20265 // i.e. if second inline image on line is higher than first and forces new page
20266 if (count($this->objectbuffer)) {
20267 $yadj = $iby - $this->y;
20268 foreach($this->objectbuffer AS $ib=>$val) {
20269 if ($this->objectbuffer[$ib]['OUTER-Y'] ) $this->objectbuffer[$ib]['OUTER-Y'] -= $yadj;
20270 if ($this->objectbuffer[$ib]['BORDER-Y']) $this->objectbuffer[$ib]['BORDER-Y'] -= $yadj;
20271 if ($this->objectbuffer[$ib]['INNER-Y']) $this->objectbuffer[$ib]['INNER-Y'] -= $yadj;
20272 }
20273 }
20274 }
20275
20276 // Added to correct for OddEven Margins
20277 if ($this->page != $oldpage) {
20278 if (($this->page-$oldpage) % 2 == 1) {
20279 $bak_x += $this->MarginCorrection;
20280 }
20281 $oldpage = $this->page;
20282 $y = $this->tMargin - $paint_ht_corr ;
20283 $this->oldy = $this->tMargin - $paint_ht_corr ;
20284 $old_height = 0;
20285 }
20286 $this->x = $bak_x;
20287 /*-- COLUMNS --*/
20288 // COLS
20289 // OR COLUMN CHANGE
20290 if ($this->CurrCol != $oldcolumn) {
20291 if ($this->directionality == 'rtl') { // *RTL*
20292 $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap); // *RTL*
20293 } // *RTL*
20294 else { // *RTL*
20295 $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap);
20296 } // *RTL*
20297 $this->x = $bak_x;
20298 $oldcolumn = $this->CurrCol;
20299 $y = $this->y0 - $paint_ht_corr ;
20300 $this->oldy = $this->y0 - $paint_ht_corr ;
20301 $old_height = 0;
20302 }
20303 /*-- END COLUMNS --*/
20304
20305 /*-- CSS-IMAGE-FLOAT --*/
20306 if ($objattr['type'] == 'image' && isset($objattr['float'])) {
20307 $fy = $this->y;
20308
20309 // DIV TOP MARGIN/BORDER/PADDING
20310 if ($this->flowingBlockAttr['newblock'] && ($this->flowingBlockAttr['blockstate']==1 || $this->flowingBlockAttr['blockstate']==3) && $this->flowingBlockAttr['lineCount']== 0) {
20311 $fy += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w'];
20312 }
20313
20314 if ($objattr['float']=='R') {
20315 $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']);
20316
20317
20318 }
20319 else if ($objattr['float']=='L') {
20320 $fx = $this->lMargin + ($this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_left']);
20321 }
20322 $w = $objattr['width'];
20323 $h = abs($objattr['height']);
20324
20325 $widthLeft = $maxWidth - ($this->flowingBlockAttr['contentWidth']/_MPDFK);
20326 $maxHeight = $this->h - ($this->tMargin + $this->margin_header + $this->bMargin + 10) ;
20327 // For Images
20328 $extraWidth = ($objattr['border_left']['w'] + $objattr['border_right']['w'] + $objattr['margin_left']+ $objattr['margin_right']);
20329 $extraHeight = ($objattr['border_top']['w'] + $objattr['border_bottom']['w'] + $objattr['margin_top']+ $objattr['margin_bottom']);
20330
20331 if ($objattr['itype'] == 'wmf' || $objattr['itype'] == 'svg') {
20332 $file = $objattr['file'];
20333 $info=$this->formobjects[$file];
20334 }
20335 else {
20336 $file = $objattr['file'];
20337 $info=$this->images[$file];
20338 }
20339 $img_w = $w - $extraWidth ;
20340 $img_h = $h - $extraHeight ;
20341 if ($objattr['border_left']['w']) {
20342 $objattr['BORDER-WIDTH'] = $img_w + (($objattr['border_left']['w'] + $objattr['border_right']['w'])/2) ;
20343 $objattr['BORDER-HEIGHT'] = $img_h + (($objattr['border_top']['w'] + $objattr['border_bottom']['w'])/2) ;
20344 $objattr['BORDER-X'] = $fx + $objattr['margin_left'] + (($objattr['border_left']['w'])/2) ;
20345 $objattr['BORDER-Y'] = $fy + $objattr['margin_top'] + (($objattr['border_top']['w'])/2) ;
20346 }
20347 $objattr['INNER-WIDTH'] = $img_w;
20348 $objattr['INNER-HEIGHT'] = $img_h;
20349 $objattr['INNER-X'] = $fx + $objattr['margin_left'] + ($objattr['border_left']['w']);
20350 $objattr['INNER-Y'] = $fy + $objattr['margin_top'] + ($objattr['border_top']['w']) ;
20351 $objattr['ID'] = $info['i'];
20352 $objattr['OUTER-WIDTH'] = $w;
20353 $objattr['OUTER-HEIGHT'] = $h;
20354 $objattr['OUTER-X'] = $fx;
20355 $objattr['OUTER-Y'] = $fy;
20356 if ($objattr['float']=='R') {
20357 // If R float already exists at this level
20358 $this->floatmargins['R']['skipline'] = false;
20359 if (isset($this->floatmargins['R']['y1']) && $this->floatmargins['R']['y1'] > 0 && $fy < $this->floatmargins['R']['y1']) {
20360 $this->WriteFlowingBlock($vetor[0]);
20361 }
20362 // If L float already exists at this level
20363 else if (isset($this->floatmargins['L']['y1']) && $this->floatmargins['L']['y1'] > 0 && $fy < $this->floatmargins['L']['y1']) {
20364 // Final check distance between floats is not now too narrow to fit text
20365 $mw = 2*$this->GetCharWidth('W',false);
20366 if (($this->blk[$this->blklvl]['inner_width'] - $w - $this->floatmargins['L']['w']) < $mw) {
20367 $this->WriteFlowingBlock($vetor[0]);
20368 }
20369 else {
20370 $this->floatmargins['R']['x'] = $fx;
20371 $this->floatmargins['R']['w'] = $w;
20372 $this->floatmargins['R']['y0'] = $fy;
20373 $this->floatmargins['R']['y1'] = $fy + $h;
20374 if ($skipln == 1) {
20375 $this->floatmargins['R']['skipline'] = true;
20376 $this->floatmargins['R']['id'] = count($this->floatbuffer)+0;
20377 $objattr['skipline'] = true;
20378 }
20379 $this->floatbuffer[] = $objattr;
20380 }
20381 }
20382 else {
20383 $this->floatmargins['R']['x'] = $fx;
20384 $this->floatmargins['R']['w'] = $w;
20385 $this->floatmargins['R']['y0'] = $fy;
20386 $this->floatmargins['R']['y1'] = $fy + $h;
20387 if ($skipln == 1) {
20388 $this->floatmargins['R']['skipline'] = true;
20389 $this->floatmargins['R']['id'] = count($this->floatbuffer)+0;
20390 $objattr['skipline'] = true;
20391 }
20392 $this->floatbuffer[] = $objattr;
20393 }
20394 }
20395 else if ($objattr['float']=='L') {
20396 // If L float already exists at this level
20397 $this->floatmargins['L']['skipline'] = false;
20398 if (isset($this->floatmargins['L']['y1']) && $this->floatmargins['L']['y1'] > 0 && $fy < $this->floatmargins['L']['y1']) {
20399 $this->floatmargins['L']['skipline'] = false;
20400 $this->WriteFlowingBlock($vetor[0]);
20401 }
20402 // If R float already exists at this level
20403 else if (isset($this->floatmargins['R']['y1']) && $this->floatmargins['R']['y1'] > 0 && $fy < $this->floatmargins['R']['y1']) {
20404 // Final check distance between floats is not now too narrow to fit text
20405 $mw = 2*$this->GetCharWidth('W',false);
20406 if (($this->blk[$this->blklvl]['inner_width'] - $w - $this->floatmargins['R']['w']) < $mw) {
20407 $this->WriteFlowingBlock($vetor[0]);
20408 }
20409 else {
20410 $this->floatmargins['L']['x'] = $fx + $w;
20411 $this->floatmargins['L']['w'] = $w;
20412 $this->floatmargins['L']['y0'] = $fy;
20413 $this->floatmargins['L']['y1'] = $fy + $h;
20414 if ($skipln == 1) {
20415 $this->floatmargins['L']['skipline'] = true;
20416 $this->floatmargins['L']['id'] = count($this->floatbuffer)+0;
20417 $objattr['skipline'] = true;
20418 }
20419 $this->floatbuffer[] = $objattr;
20420 }
20421 }
20422 else {
20423 $this->floatmargins['L']['x'] = $fx + $w;
20424 $this->floatmargins['L']['w'] = $w;
20425 $this->floatmargins['L']['y0'] = $fy;
20426 $this->floatmargins['L']['y1'] = $fy + $h;
20427 if ($skipln == 1) {
20428 $this->floatmargins['L']['skipline'] = true;
20429 $this->floatmargins['L']['id'] = count($this->floatbuffer)+0;
20430 $objattr['skipline'] = true;
20431 }
20432 $this->floatbuffer[] = $objattr;
20433 }
20434 }
20435 }
20436 else {
20437 /*-- END CSS-IMAGE-FLOAT --*/
20438 $this->WriteFlowingBlock($vetor[0]);
20439 /*-- CSS-IMAGE-FLOAT --*/
20440 }
20441 /*-- END CSS-IMAGE-FLOAT --*/
20442 } // *TABLES*
20443
20444 } // END If special content
20445 else { //THE text
20446 if ($this->tableLevel) { $paint_ht_corr = 0; } // To move the y up when new column/page started if div border needed
20447 else { $paint_ht_corr = $this->blk[$this->blklvl]['border_top']['w']; }
20448
20449 if ($vetor[0] == "\n") { //We are reading a <BR> now turned into newline ("\n")
20450 if ($this->flowingBlockAttr['content']) {
20451 $this->finishFlowingBlock(false,'br');
20452 }
20453 else if ($is_table) {
20454 $this->y+= $this->_computeLineheight($this->table_lineheight);
20455 }
20456 else if (!$is_table) {
20457 $this->DivLn($this->lineheight);
20458 if ($this->ColActive) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
20459 }
20460 // Added to correct for OddEven Margins
20461 if ($this->page != $oldpage) {
20462 if (($this->page-$oldpage) % 2 == 1) {
20463 $bak_x += $this->MarginCorrection;
20464 }
20465 $oldpage = $this->page;
20466 $y = $this->tMargin - $paint_ht_corr ;
20467 $this->oldy = $this->tMargin - $paint_ht_corr ;
20468 $old_height = 0;
20469 }
20470 $this->x = $bak_x;
20471 /*-- COLUMNS --*/
20472 // COLS
20473 // OR COLUMN CHANGE
20474 if ($this->CurrCol != $oldcolumn) {
20475 if ($this->directionality == 'rtl') { // *RTL*
20476 $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap); // *RTL*
20477 } // *RTL*
20478 else { // *RTL*
20479 $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap);
20480 } // *RTL*
20481 $this->x = $bak_x;
20482 $oldcolumn = $this->CurrCol;
20483 $y = $this->y0 - $paint_ht_corr ;
20484 $this->oldy = $this->y0 - $paint_ht_corr ;
20485 $old_height = 0;
20486 }
20487 /*-- END COLUMNS --*/
20488 $this->newFlowingBlock( $this->divwidth,$this->divheight,$align,$is_table,$is_list,$blockstate,false,$blockdir);
20489 }
20490 else {
20491 $this->WriteFlowingBlock( $vetor[0]);
20492
20493 // Added to correct for OddEven Margins
20494 if ($this->page != $oldpage) {
20495 if (($this->page-$oldpage) % 2 == 1) {
20496 $bak_x += $this->MarginCorrection;
20497 $this->x = $bak_x;
20498 }
20499 $oldpage = $this->page;
20500 $y = $this->tMargin - $paint_ht_corr ;
20501 $this->oldy = $this->tMargin - $paint_ht_corr ;
20502 $old_height = 0;
20503 }
20504 /*-- COLUMNS --*/
20505 // COLS
20506 // OR COLUMN CHANGE
20507 if ($this->CurrCol != $oldcolumn) {
20508 if ($this->directionality == 'rtl') { // *RTL*
20509 $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap); // *RTL*
20510 } // *RTL*
20511 else { // *RTL*
20512 $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap);
20513 } // *RTL*
20514 $this->x = $bak_x;
20515 $oldcolumn = $this->CurrCol;
20516 $y = $this->y0 - $paint_ht_corr ;
20517 $this->oldy = $this->y0 - $paint_ht_corr ;
20518 $old_height = 0;
20519 }
20520 /*-- END COLUMNS --*/
20521 }
20522
20523
20524 }
20525
20526 //Check if it is the last element. If so then finish printing the block
20527 if ($i == ($array_size-1)) {
20528 $this->finishFlowingBlock(true); // true = END of flowing block
20529 // Added to correct for OddEven Margins
20530 if ($this->page != $oldpage) {
20531 if (($this->page-$oldpage) % 2 == 1) {
20532 $bak_x += $this->MarginCorrection;
20533 $this->x = $bak_x;
20534 }
20535 $oldpage = $this->page;
20536 $y = $this->tMargin - $paint_ht_corr ;
20537 $this->oldy = $this->tMargin - $paint_ht_corr ;
20538 $old_height = 0;
20539 }
20540
20541 /*-- COLUMNS --*/
20542 // COLS
20543 // OR COLUMN CHANGE
20544 if ($this->CurrCol != $oldcolumn) {
20545 if ($this->directionality == 'rtl') { // *RTL*
20546 $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap); // *RTL*
20547 } // *RTL*
20548 else { // *RTL*
20549 $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth+$this->ColGap);
20550 } // *RTL*
20551 $this->x = $bak_x;
20552 $oldcolumn = $this->CurrCol;
20553 $y = $this->y0 - $paint_ht_corr ;
20554 $this->oldy = $this->y0 - $paint_ht_corr ;
20555 $old_height = 0;
20556 }
20557 /*-- END COLUMNS --*/
20558
20559 }
20560
20561 // RESETTING VALUES
20562 $this->SetTColor($this->ConvertColor(0));
20563 $this->SetDColor($this->ConvertColor(0));
20564 $this->SetFColor($this->ConvertColor(255));
20565 $this->colorarray = '';
20566 $this->spanbgcolorarray = '';
20567 $this->spanbgcolor = false;
20568 $this->spanborder = false;
20569 $this->spanborddet = array();
20570 $this->HREF = '';
20571 $this->textparam = array();
20572 $this->SetTextOutline();
20573 $this->SUP = false;
20574 $this->SUB = false;
20575
20576 $this->strike = false;
20577 $this->textshadow = '';
20578
20579 $this->currentfontfamily = '';
20580 $this->currentfontsize = '';
20581 $this->currentfontstyle = '';
20582 /*-- TABLES --*/
20583 if ($this->tableLevel) {
20584 $this->SetLineHeight('',$this->table_lineheight); // *TABLES*
20585 }
20586 else
20587 /*-- END TABLES --*/
20588 /*-- LISTS --*/
20589 if ($is_list && $this->list_lineheight[$this->listlvl][$this->listOcc]) {
20590 $this->SetLineHeight('',$this->list_lineheight[$this->listlvl][$this->listOcc]); // sets default line height
20591 }
20592 else
20593 /*-- END LISTS --*/
20594 if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) {
20595 $this->SetLineHeight('',$this->blk[$this->blklvl]['line_height']); // sets default line height
20596 }
20597 $this->ResetStyles();
20598 $this->toupper = false;
20599 $this->tolower = false;
20600 $this->capitalize = false;
20601 $this->kerning = false;
20602 $this->lSpacingCSS = '';
20603 $this->wSpacingCSS = '';
20604 $this->fixedlSpacing = false;
20605 $this->minwSpacing = 0;
20606 $this->SetDash();
20607 $this->dash_on = false;
20608 $this->dotted_on = false;
20609
20610 }//end of for(i=0;i<arraysize;i++)
20611
20612
20613 // PAINT DIV BORDER // DISABLED IN COLUMNS AS DOESN'T WORK WHEN BROKEN ACROSS COLS??
20614 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)) {
20615 $bottom_y = $this->y; // Does not include Bottom Margin
20616 if (isset($this->blk[$this->blklvl]['startpage']) && $this->blk[$this->blklvl]['startpage'] != $this->page && $blockstate != 1) {
20617 $this->PaintDivBB('pagetop',$blockstate);
20618 }
20619
20620 else if ($blockstate != 1) {
20621 $this->PaintDivBB('',$blockstate);
20622 }
20623 $this->y = $bottom_y;
20624 $this->x = $bak_x;
20625 }
20626
20627 // Reset Font
20628 $this->SetFontSize($this->default_font_size,false);
20629
20630
20631 }
20632
20633 function _setDashBorder($style, $div, $cp, $side) {
20634 if ($style == 'dashed' && (($side=='L' || $side=='R') || ($side=='T' && $div != 'pagetop' && !$cp) || ($side=='B' && $div!='pagebottom') )) {
20635 $dashsize = 2; // final dash will be this + 1*linewidth
20636 $dashsizek = 1.5; // ratio of Dash/Blank
20637 $this->SetDash($dashsize,($dashsize/$dashsizek)+($this->LineWidth*2));
20638 }
20639 else if ($style == 'dotted' || ($side=='T' && ($div == 'pagetop' || $cp)) || ($side=='B' && $div == 'pagebottom')) {
20640 //Round join and cap
20641 $this->SetLineJoin(1);
20642 $this->SetLineCap(1);
20643 $this->SetDash(0.001,($this->LineWidth*3));
20644 }
20645 }
20646
20647 function _setBorderLine($b, $k=1) {
20648 $this->SetLineWidth($b['w']/$k);
20649 $this->SetDColor($b['c']);
20650 if ($b['c'][0]==5) { // RGBa
20651 $this->SetAlpha($b['c'][4], 'Normal', false, 'S')."\n";
20652 }
20653 else if ($b['c'][0]==6) { // CMYKa
20654 $this->SetAlpha($b['c'][5], 'Normal', false, 'S')."\n";
20655 }
20656 }
20657
20658 // mPDF 5.6.52
20659 function PaintDivBB($divider='',$blockstate=0,$blvl=0) {
20660 // Borders & backgrounds are done elsewhere for columns - messes up the repositioning in printcolumnbuffer
20661 if ($this->ColActive) { return ; } // *COLUMNS*
20662 $save_y = $this->y;
20663 if (!$blvl) { $blvl = $this->blklvl; }
20664 $x0 = $x1 = $y0 = $y1 = 0;
20665
20666 // Added mPDF 3.0 Float DIV
20667 if (isset($this->blk[$blvl]['bb_painted'][$this->page]) && $this->blk[$blvl]['bb_painted'][$this->page]) { return; } // *CSS-FLOAT*
20668
20669 if (isset($this->blk[$blvl]['x0'])) { $x0 = $this->blk[$blvl]['x0']; } // left
20670 if (isset($this->blk[$blvl]['y1'])) { $y1 = $this->blk[$blvl]['y1']; } // bottom
20671
20672 // Added mPDF 3.0 Float DIV - ensures backgrounds/borders are drawn to bottom of page
20673 if ($y1==0) {
20674 if ($divider=='pagebottom') { $y1 = $this->h-$this->bMargin; }
20675 else { $y1 = $this->y; }
20676 }
20677
20678 if (isset($this->blk[$blvl]['startpage']) && $this->blk[$blvl]['startpage'] != $this->page) { $continuingpage = true; } else { $continuingpage = false; }
20679
20680 if (isset($this->blk[$blvl]['y0'])) { $y0 = $this->blk[$blvl]['y0']; }
20681 $h = $y1 - $y0;
20682 $w = $this->blk[$blvl]['width'];
20683 $x1 = $x0 + $w;
20684
20685 // Set border-widths as used here
20686 $border_top = $this->blk[$blvl]['border_top']['w'];
20687 $border_bottom = $this->blk[$blvl]['border_bottom']['w'];
20688 $border_left = $this->blk[$blvl]['border_left']['w'];
20689 $border_right = $this->blk[$blvl]['border_right']['w'];
20690 if (!$this->blk[$blvl]['border_top'] || $divider == 'pagetop' || $continuingpage) {
20691 $border_top = 0;
20692 }
20693 if (!$this->blk[$blvl]['border_bottom'] || $blockstate == 1 || $divider == 'pagebottom') {
20694 $border_bottom = 0;
20695 }
20696
20697 $brTL_H = 0;
20698 $brTL_V = 0;
20699 $brTR_H = 0;
20700 $brTR_V = 0;
20701 $brBL_H = 0;
20702 $brBL_V = 0;
20703 $brBR_H = 0;
20704 $brBR_V = 0;
20705
20706 $brset = false;
20707 /*-- BORDER-RADIUS --*/
20708 if (isset($this->blk[$blvl]['border_radius_TL_H'])) { $brTL_H = $this->blk[$blvl]['border_radius_TL_H']; $brset = true; }
20709 if (isset($this->blk[$blvl]['border_radius_TL_V'])) { $brTL_V = $this->blk[$blvl]['border_radius_TL_V']; $brset = true; }
20710 if (isset($this->blk[$blvl]['border_radius_TR_H'])) { $brTR_H = $this->blk[$blvl]['border_radius_TR_H']; $brset = true; }
20711 if (isset($this->blk[$blvl]['border_radius_TR_V'])) { $brTR_V = $this->blk[$blvl]['border_radius_TR_V']; $brset = true; }
20712 if (isset($this->blk[$blvl]['border_radius_BR_H'])) { $brBR_H = $this->blk[$blvl]['border_radius_BR_H']; $brset = true; }
20713 if (isset($this->blk[$blvl]['border_radius_BR_V'])) { $brBR_V = $this->blk[$blvl]['border_radius_BR_V']; $brset = true; }
20714 if (isset($this->blk[$blvl]['border_radius_BL_H'])) { $brBL_H = $this->blk[$blvl]['border_radius_BL_H']; $brset = true; }
20715 if (isset($this->blk[$blvl]['border_radius_BL_V'])) { $brBL_V = $this->blk[$blvl]['border_radius_BL_V']; $brset = true; }
20716
20717 // mPDF 5.4.17
20718 //if (!$this->blk[$blvl]['border_top'] || $divider == 'pagetop' || $continuingpage || $this->keep_block_together) {
20719 if (!$this->blk[$blvl]['border_top'] || $divider == 'pagetop' || $continuingpage) {
20720 $brTL_H = 0;
20721 $brTL_V = 0;
20722 $brTR_H = 0;
20723 $brTR_V = 0;
20724 }
20725 // mPDF 5.4.17
20726 //if (!$this->blk[$blvl]['border_bottom'] || $blockstate == 1 || $divider == 'pagebottom' || $this->keep_block_together) {
20727 if (!$this->blk[$blvl]['border_bottom'] || $blockstate == 1 || $divider == 'pagebottom') {
20728 $brBL_H = 0;
20729 $brBL_V = 0;
20730 $brBR_H = 0;
20731 $brBR_V = 0;
20732 }
20733
20734 // Disallow border-radius if it is smaller than the border width.
20735 if ($brTL_H < min($border_left, $border_top)) { $brTL_H = $brTL_V = 0; }
20736 if ($brTL_V < min($border_left, $border_top)) { $brTL_V = $brTL_H = 0; }
20737 if ($brTR_H < min($border_right, $border_top)) { $brTR_H = $brTR_V = 0; }
20738 if ($brTR_V < min($border_right, $border_top)) { $brTR_V = $brTR_H = 0; }
20739 if ($brBL_H < min($border_left, $border_bottom)) { $brBL_H = $brBL_V = 0; }
20740 if ($brBL_V < min($border_left, $border_bottom)) { $brBL_V = $brBL_H = 0; }
20741 if ($brBR_H < min($border_right, $border_bottom)) { $brBR_H = $brBR_V = 0; }
20742 if ($brBR_V < min($border_right, $border_bottom)) { $brBR_V = $brBR_H = 0; }
20743
20744 // CHECK FOR radii that sum to > width or height of div ********
20745 $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));
20746 if ($f < 1) {
20747 $brTL_H *= $f;
20748 $brTL_V *= $f;
20749 $brTR_H *= $f;
20750 $brTR_V *= $f;
20751 $brBL_H *= $f;
20752 $brBL_V *= $f;
20753 $brBR_H *= $f;
20754 $brBR_V *= $f;
20755 }
20756 /*-- END BORDER-RADIUS --*/
20757
20758 $tbcol = $this->ConvertColor(255);
20759 for($l=0; $l <= $blvl; $l++) {
20760 if ($this->blk[$l]['bgcolor']) {
20761 $tbcol = $this->blk[$l]['bgcolorarray'];
20762 }
20763 }
20764
20765 // BORDERS
20766 if (isset($this->blk[$blvl]['y0']) && $this->blk[$blvl]['y0']) { $y0 = $this->blk[$blvl]['y0']; }
20767 $h = $y1 - $y0;
20768 $w = $this->blk[$blvl]['width'];
20769
20770 //if ($this->blk[$blvl]['border_top']) {
20771 // Reinstate line above for dotted line divider when block border crosses a page
20772 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
20773 $tbd = $this->blk[$blvl]['border_top'];
20774
20775 // mPDF 5.4.18
20776 $legend = '';
20777 if (isset($this->blk[$blvl]['border_legend']) && $this->blk[$blvl]['border_legend']) {
20778 $legend = $this->blk[$blvl]['border_legend']; // Same structure array as textbuffer
20779 $txt = ltrim($legend[0]);
20780
20781 //Set font, size, style, color
20782 $this->SetFont($legend[4],$legend[2],$legend[11]);
20783 if ($legend[3]) {
20784 $cor = $legend[3];
20785 $this->SetTColor($cor);
20786 }
20787 $stringWidth = $this->GetStringWidth($txt );
20788 $save_x = $this->x;
20789 $save_y = $this->y;
20790 $save_currentfontfamily = $this->FontFamily;
20791 $save_currentfontsize = $this->FontSizePt;
20792 $save_currentfontstyle = $this->FontStyle.($this->U ? 'U' : '').($this->S ? 'S' : '');
20793 $this->y = $y0 - $this->FontSize/2 + $this->blk[$blvl]['border_top']['w']/2;
20794 $this->x = $x0 + $this->blk[$blvl]['padding_left'] + $this->blk[$blvl]['border_left']['w'];
20795
20796 // Set the distance from the border line to the text ? make configurable variable
20797 $gap = 0.2 * $this->FontSize;
20798
20799 $legbreakL = $this->x - $gap;
20800 $legbreakR = $this->x + $stringWidth + $gap;
20801
20802 $this->Cell( $stringWidth, $this->FontSize, $txt , '', 0, 'C', $fill, '', 0, 0,0,'M', $fill);
20803 // Reset
20804 $this->x = $save_x;
20805 $this->y = $save_y;
20806 $this->SetFont($save_currentfontfamily,$save_currentfontstyle,$save_currentfontsize);
20807 $this->SetTColor($this->ConvertColor(0));
20808 }
20809
20810 if (isset($tbd['s']) && $tbd['s']) {
20811 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') {
20812 $this->_out('q');
20813 $this->SetLineWidth(0);
20814 $this->_out(sprintf('%.3F %.3F m ',($x0)*_MPDFK, ($this->h-($y0))*_MPDFK));
20815 $this->_out(sprintf('%.3F %.3F l ',($x0 + $border_left)*_MPDFK, ($this->h-($y0 + $border_top))*_MPDFK));
20816 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w - $border_right)*_MPDFK, ($this->h-($y0 + $border_top))*_MPDFK));
20817 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w)*_MPDFK, ($this->h-($y0))*_MPDFK));
20818 $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
20819 }
20820
20821 $this->_setBorderLine($tbd);
20822 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') {
20823 $legbreakL -= $border_top/2; // because line cap different
20824 $legbreakR += $border_top/2;
20825 $this->_setDashBorder($tbd['style'],$divider,$continuingpage,'T');
20826 }
20827 /*-- BORDER-RADIUS --*/
20828 else if (($brTL_V && $brTL_H) || ($brTR_V && $brTR_H) || $tbd['style']=='solid' || $tbd['style']=='double' ) { // mPDF 5.6.58
20829 $this->SetLineJoin(0);
20830 $this->SetLineCap(0);
20831 }
20832 $s = '';
20833 if ($brTR_H && $brTR_V) {
20834 $s .= ($this->_EllipseArc($x0 + $w - $brTR_H, $y0 + $brTR_V, $brTR_H - $border_top/2 , $brTR_V - $border_top/2 , 1, 2, true))."\n";
20835 }
20836 else
20837 /*-- END BORDER-RADIUS --*/
20838 if ($tbd['style']=='solid' || $tbd['style']=='double') {
20839 $s .= (sprintf('%.3F %.3F m ',($x0 + $w)*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20840 }
20841 else {
20842 $s .= (sprintf('%.3F %.3F m ',($x0 + $w - ($border_top/2))*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20843 }
20844 /*-- BORDER-RADIUS --*/
20845 if ($brTL_H && $brTL_V ) {
20846 // mPDF 5.4.18
20847 if ($legend) {
20848 if ($legbreakR < ($x0 + $w - $brTR_H)) {
20849 $s .= (sprintf('%.3F %.3F l ', $legbreakR*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20850 }
20851 if ($legbreakL > ($x0 + $brTL_H )) {
20852 $s .= (sprintf('%.3F %.3F m ',$legbreakL*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20853 $s .= (sprintf('%.3F %.3F l ',($x0 + $brTL_H )*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK)."\n");
20854 }
20855 else {
20856 $s .= (sprintf('%.3F %.3F m ',($x0 + $brTL_H )*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20857 }
20858 }
20859 else {
20860 $s .= (sprintf('%.3F %.3F l ',($x0 + $brTL_H )*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20861 }
20862 $s .= ($this->_EllipseArc($x0 + $brTL_H, $y0 + $brTL_V, $brTL_H - $border_top/2 , $brTL_V - $border_top/2 , 2, 1))."\n";
20863 }
20864 else {
20865 /*-- END BORDER-RADIUS --*/
20866 // mPDF 5.4.18
20867 if ($legend) {
20868 if ($legbreakR < ($x0 + $w)) {
20869 $s .= (sprintf('%.3F %.3F l ',$legbreakR*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20870 }
20871 if ($legbreakL > ($x0)) {
20872 $s .= (sprintf('%.3F %.3F m ',$legbreakL*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20873 if ($tbd['style']=='solid' || $tbd['style']=='double') {
20874 $s .= (sprintf('%.3F %.3F l ',($x0)*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20875 }
20876 else {
20877 $s .= (sprintf('%.3F %.3F l ',($x0 + ($border_top/2))*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20878 }
20879 }
20880 else if ($tbd['style']=='solid' || $tbd['style']=='double') {
20881 $s .= (sprintf('%.3F %.3F m ', ($x0)*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20882 }
20883 else {
20884 $s .= (sprintf('%.3F %.3F m ', ($x0 + $border_top/2)*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20885 }
20886 }
20887 else if ($tbd['style']=='solid' || $tbd['style']=='double') {
20888 $s .= (sprintf('%.3F %.3F l ',($x0)*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20889 }
20890 else {
20891 $s .= (sprintf('%.3F %.3F l ',($x0 + ($border_top/2))*_MPDFK, ($this->h-($y0 + ($border_top/2)))*_MPDFK))."\n";
20892 }
20893 /*-- BORDER-RADIUS --*/
20894 }
20895 /*-- END BORDER-RADIUS --*/
20896 $s .= 'S'."\n";
20897 $this->_out($s);
20898
20899 if ($tbd['style']=='double') {
20900 $this->SetLineWidth($tbd['w']/3);
20901 $this->SetDColor($tbcol);
20902 $this->_out($s);
20903 }
20904 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') { $this->_out('Q'); }
20905
20906 // Reset Corners and Dash off
20907 $this->SetLineWidth(0.1); // mPDF 5.6.57
20908 $this->SetDColor($this->ConvertColor(0));
20909 $this->SetLineJoin(2);
20910 $this->SetLineCap(2);
20911 $this->SetDash();
20912 }
20913 }
20914 //if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1) {
20915 // Reinstate line above for dotted line divider when block border crosses a page
20916 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
20917 $tbd = $this->blk[$blvl]['border_bottom'];
20918 if (isset($tbd['s']) && $tbd['s']) {
20919 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') {
20920 $this->_out('q');
20921 $this->SetLineWidth(0);
20922 $this->_out(sprintf('%.3F %.3F m ',($x0)*_MPDFK, ($this->h-($y0 + $h))*_MPDFK));
20923 $this->_out(sprintf('%.3F %.3F l ',($x0 + $border_left)*_MPDFK, ($this->h-($y0 + $h - $border_bottom))*_MPDFK));
20924 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w - $border_right)*_MPDFK, ($this->h-($y0 + $h - $border_bottom))*_MPDFK));
20925 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w)*_MPDFK, ($this->h-($y0 + $h))*_MPDFK));
20926 $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
20927 }
20928
20929 $this->_setBorderLine($tbd);
20930 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],$divider,$continuingpage,'B'); }
20931 /*-- BORDER-RADIUS --*/
20932 else if (($brBL_V && $brBL_H) || ($brBR_V && $brBR_H) || $tbd['style']=='solid' || $tbd['style']=='double' ) { // mPDF 5.6.58
20933 $this->SetLineJoin(0);
20934 $this->SetLineCap(0);
20935 }
20936 $s = '';
20937 if ($brBL_H && $brBL_V) {
20938 $s .= ($this->_EllipseArc($x0 + $brBL_H, $y0 + $h - $brBL_V, $brBL_H - $border_bottom/2 , $brBL_V - $border_bottom/2 , 3, 2, true))."\n";
20939 }
20940 else
20941 /*-- END BORDER-RADIUS --*/
20942 if ($tbd['style']=='solid' || $tbd['style']=='double') {
20943 $s .= (sprintf('%.3F %.3F m ',($x0)*_MPDFK, ($this->h-($y0 + $h - ($border_bottom/2)))*_MPDFK))."\n";
20944 }
20945 else {
20946 $s .= (sprintf('%.3F %.3F m ',($x0 + ($border_bottom/2))*_MPDFK, ($this->h-($y0 + $h - ($border_bottom/2)))*_MPDFK))."\n";
20947 }
20948 /*-- BORDER-RADIUS --*/
20949 if ($brBR_H && $brBR_V ) {
20950 $s .= (sprintf('%.3F %.3F l ',($x0 + $w - ($border_bottom/2) - $brBR_H )*_MPDFK, ($this->h-($y0 + $h - ($border_bottom/2)))*_MPDFK))."\n";
20951 $s .= ($this->_EllipseArc($x0 + $w - $brBR_H, $y0 + $h - $brBR_V, $brBR_H - $border_bottom/2 , $brBR_V - $border_bottom/2 , 4, 1))."\n";
20952 }
20953 else
20954 /*-- END BORDER-RADIUS --*/
20955 if ($tbd['style']=='solid' || $tbd['style']=='double') {
20956 $s .= (sprintf('%.3F %.3F l ',($x0 + $w)*_MPDFK, ($this->h-($y0 + $h - ($border_bottom/2)))*_MPDFK))."\n";
20957 }
20958 else {
20959 $s .= (sprintf('%.3F %.3F l ',($x0 + $w - ($border_bottom/2))*_MPDFK, ($this->h-($y0 + $h - ($border_bottom/2)))*_MPDFK))."\n";
20960 }
20961 $s .= 'S'."\n";
20962 $this->_out($s);
20963
20964 if ($tbd['style']=='double') {
20965 $this->SetLineWidth($tbd['w']/3);
20966 $this->SetDColor($tbcol);
20967 $this->_out($s);
20968 }
20969 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') { $this->_out('Q'); }
20970
20971
20972 // Reset Corners and Dash off
20973 $this->SetLineWidth(0.1); // mPDF 5.6.57
20974 $this->SetDColor($this->ConvertColor(0));
20975 $this->SetLineJoin(2);
20976 $this->SetLineCap(2);
20977 $this->SetDash();
20978 }
20979 }
20980 if ($this->blk[$blvl]['border_left']) {
20981 $tbd = $this->blk[$blvl]['border_left'];
20982 if (isset($tbd['s']) && $tbd['s']) {
20983 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') {
20984 $this->_out('q');
20985 $this->SetLineWidth(0);
20986 $this->_out(sprintf('%.3F %.3F m ',($x0)*_MPDFK, ($this->h-($y0))*_MPDFK));
20987 $this->_out(sprintf('%.3F %.3F l ',($x0 + $border_left)*_MPDFK, ($this->h-($y0+$border_top))*_MPDFK));
20988 $this->_out(sprintf('%.3F %.3F l ',($x0 + $border_left)*_MPDFK, ($this->h-($y0 + $h - $border_bottom))*_MPDFK));
20989 $this->_out(sprintf('%.3F %.3F l ',($x0)*_MPDFK, ($this->h-($y0 + $h))*_MPDFK));
20990 $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
20991 }
20992
20993 $this->_setBorderLine($tbd);
20994 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],$divider,$continuingpage,'L'); }
20995 /*-- BORDER-RADIUS --*/
20996 else if (($brTL_V && $brTL_H) || ($brBL_V && $brBL_H) || $tbd['style']=='solid' || $tbd['style']=='double' ) { // mPDF 5.6.58
20997 $this->SetLineJoin(0);
20998 $this->SetLineCap(0);
20999 }
21000 $s = '';
21001 if ($brTL_V && $brTL_H) {
21002 $s .= ($this->_EllipseArc($x0 + $brTL_H, $y0 + $brTL_V, $brTL_H - $border_left/2 , $brTL_V - $border_left/2, 2, 2, true))."\n";
21003 }
21004 else
21005 /*-- END BORDER-RADIUS --*/
21006 if ($tbd['style']=='solid' || $tbd['style']=='double') {
21007 $s .= (sprintf('%.3F %.3F m ',($x0 + ($border_left/2))*_MPDFK, ($this->h-($y0))*_MPDFK))."\n";
21008 }
21009 else {
21010 $s .= (sprintf('%.3F %.3F m ',($x0 + ($border_left/2))*_MPDFK, ($this->h-($y0 + ($border_left/2)))*_MPDFK))."\n";
21011 }
21012 /*-- BORDER-RADIUS --*/
21013 if ($brBL_V && $brBL_H ) {
21014 $s .= (sprintf('%.3F %.3F l ',($x0 + ($border_left/2))*_MPDFK, ($this->h-($y0 + $h - ($border_left/2)- $brBL_V) )*_MPDFK))."\n";
21015 $s .= ($this->_EllipseArc($x0 + $brBL_H, $y0 + $h - $brBL_V, $brBL_H - $border_left/2 , $brBL_V - $border_left/2, 3, 1))."\n";
21016 }
21017 else
21018 /*-- END BORDER-RADIUS --*/
21019 if ($tbd['style']=='solid' || $tbd['style']=='double') {
21020 $s .= (sprintf('%.3F %.3F l ',($x0 + ($border_left/2))*_MPDFK, ($this->h-($y0 + $h) )*_MPDFK))."\n";
21021 }
21022 else {
21023 $s .= (sprintf('%.3F %.3F l ',($x0 + ($border_left/2))*_MPDFK, ($this->h-($y0 + $h - ($border_left/2)) )*_MPDFK))."\n";
21024 }
21025 $s .= 'S'."\n";
21026 $this->_out($s);
21027
21028 if ($tbd['style']=='double') {
21029 $this->SetLineWidth($tbd['w']/3);
21030 $this->SetDColor($tbcol);
21031 $this->_out($s);
21032 }
21033 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') { $this->_out('Q'); }
21034
21035 // Reset Corners and Dash off
21036 $this->SetLineWidth(0.1); // mPDF 5.6.57
21037 $this->SetDColor($this->ConvertColor(0));
21038 $this->SetLineJoin(2);
21039 $this->SetLineCap(2);
21040 $this->SetDash();
21041 }
21042 }
21043 if ($this->blk[$blvl]['border_right']) {
21044 $tbd = $this->blk[$blvl]['border_right'];
21045 if (isset($tbd['s']) && $tbd['s']) {
21046 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') {
21047 $this->_out('q');
21048 $this->SetLineWidth(0);
21049 $this->_out(sprintf('%.3F %.3F m ',($x0 + $w)*_MPDFK, ($this->h-($y0))*_MPDFK));
21050 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w - $border_right)*_MPDFK, ($this->h-($y0+$border_top))*_MPDFK));
21051 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w - $border_right)*_MPDFK, ($this->h-($y0 + $h - $border_bottom))*_MPDFK));
21052 $this->_out(sprintf('%.3F %.3F l ',($x0 + $w)*_MPDFK, ($this->h-($y0 + $h))*_MPDFK));
21053 $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
21054 }
21055
21056 $this->_setBorderLine($tbd);
21057 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],$divider,$continuingpage,'R'); }
21058 /*-- BORDER-RADIUS --*/
21059 else if (($brTR_V && $brTR_H) || ($brBR_V && $brBR_H) || $tbd['style']=='solid' || $tbd['style']=='double' ) { // mPDF 5.6.58
21060 $this->SetLineJoin(0);
21061 $this->SetLineCap(0);
21062 }
21063 $s = '';
21064 if ($brBR_V && $brBR_H) {
21065 $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";
21066 }
21067 else
21068 /*-- END BORDER-RADIUS --*/
21069 if ($tbd['style']=='solid' || $tbd['style']=='double') {
21070 $s .= (sprintf('%.3F %.3F m ',($x0 + $w - ($border_right/2))*_MPDFK, ($this->h-($y0 + $h))*_MPDFK))."\n";
21071 }
21072 else {
21073 $s .= (sprintf('%.3F %.3F m ',($x0 + $w - ($border_right/2))*_MPDFK, ($this->h-($y0 + $h - ($border_right/2)))*_MPDFK))."\n";
21074 }
21075 /*-- BORDER-RADIUS --*/
21076 if ($brTR_V && $brTR_H ) {
21077 $s .= (sprintf('%.3F %.3F l ',($x0 + $w - ($border_right/2))*_MPDFK, ($this->h-($y0 + ($border_right/2) + $brTR_V) )*_MPDFK))."\n";
21078 $s .= ($this->_EllipseArc($x0 + $w - $brTR_H, $y0 + $brTR_V, $brTR_H - $border_right/2 , $brTR_V - $border_right/2, 1, 1))."\n";
21079 }
21080 else
21081 /*-- END BORDER-RADIUS --*/
21082 if ($tbd['style']=='solid' || $tbd['style']=='double') {
21083 $s .= (sprintf('%.3F %.3F l ',($x0 + $w - ($border_right/2))*_MPDFK, ($this->h-($y0) )*_MPDFK))."\n";
21084 }
21085 else {
21086 $s .= (sprintf('%.3F %.3F l ',($x0 + $w - ($border_right/2))*_MPDFK, ($this->h-($y0 + ($border_right/2)) )*_MPDFK))."\n";
21087 }
21088 $s .= 'S'."\n";
21089 $this->_out($s);
21090
21091 if ($tbd['style']=='double') {
21092 $this->SetLineWidth($tbd['w']/3);
21093 $this->SetDColor($tbcol);
21094 $this->_out($s);
21095 }
21096 if (!$brset && $tbd['style']!='dotted' && $tbd['style']!='dashed') { $this->_out('Q'); }
21097
21098 // Reset Corners and Dash off
21099 $this->SetLineWidth(0.1); // mPDF 5.6.57
21100 $this->SetDColor($this->ConvertColor(0));
21101 $this->SetLineJoin(2);
21102 $this->SetLineCap(2);
21103 $this->SetDash();
21104 }
21105 }
21106
21107
21108 $this->SetDash();
21109 $this->y = $save_y;
21110
21111
21112 // BACKGROUNDS are disabled in columns/kbt/headers - messes up the repositioning in printcolumnbuffer
21113 if ($this->ColActive || $this->kwt || $this->keep_block_together) { return ; }
21114
21115
21116 $bgx0 = $x0;
21117 $bgx1 = $x1;
21118 $bgy0 = $y0;
21119 $bgy1 = $y1;
21120
21121 // Defined br values represent the radius of the outer curve - need to take border-width/2 from each radius for drawing the borders
21122 if (isset($this->blk[$blvl]['background_clip']) && $this->blk[$blvl]['background_clip'] == 'padding-box') {
21123 $brbgTL_H = max(0, $brTL_H - $this->blk[$blvl]['border_left']['w']);
21124 $brbgTL_V = max(0, $brTL_V - $this->blk[$blvl]['border_top']['w']);
21125 $brbgTR_H = max(0, $brTR_H - $this->blk[$blvl]['border_right']['w']);
21126 $brbgTR_V = max(0, $brTR_V - $this->blk[$blvl]['border_top']['w']);
21127 $brbgBL_H = max(0, $brBL_H - $this->blk[$blvl]['border_left']['w']);
21128 $brbgBL_V = max(0, $brBL_V - $this->blk[$blvl]['border_bottom']['w']);
21129 $brbgBR_H = max(0, $brBR_H - $this->blk[$blvl]['border_right']['w']);
21130 $brbgBR_V = max(0, $brBR_V - $this->blk[$blvl]['border_bottom']['w']);
21131 $bgx0 += $this->blk[$blvl]['border_left']['w'];
21132 $bgx1 -= $this->blk[$blvl]['border_right']['w'];
21133 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
21134 $bgy0 += $this->blk[$blvl]['border_top']['w'];
21135 }
21136 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
21137 $bgy1 -= $this->blk[$blvl]['border_bottom']['w'];
21138 }
21139 }
21140 // mPDF 5.6.09
21141 else if (isset($this->blk[$blvl]['background_clip']) && $this->blk[$blvl]['background_clip'] == 'content-box') {
21142 $brbgTL_H = max(0, $brTL_H - $this->blk[$blvl]['border_left']['w'] - $this->blk[$blvl]['padding_left']);
21143 $brbgTL_V = max(0, $brTL_V - $this->blk[$blvl]['border_top']['w'] - $this->blk[$blvl]['padding_top']);
21144 $brbgTR_H = max(0, $brTR_H - $this->blk[$blvl]['border_right']['w'] - $this->blk[$blvl]['padding_right']);
21145 $brbgTR_V = max(0, $brTR_V - $this->blk[$blvl]['border_top']['w'] - $this->blk[$blvl]['padding_top']);
21146 $brbgBL_H = max(0, $brBL_H - $this->blk[$blvl]['border_left']['w'] - $this->blk[$blvl]['padding_left']);
21147 $brbgBL_V = max(0, $brBL_V - $this->blk[$blvl]['border_bottom']['w'] - $this->blk[$blvl]['padding_bottom']);
21148 $brbgBR_H = max(0, $brBR_H - $this->blk[$blvl]['border_right']['w'] - $this->blk[$blvl]['padding_right']);
21149 $brbgBR_V = max(0, $brBR_V - $this->blk[$blvl]['border_bottom']['w'] - $this->blk[$blvl]['padding_bottom']);
21150 $bgx0 += $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'];
21151 $bgx1 -= $this->blk[$blvl]['border_right']['w'] + $this->blk[$blvl]['padding_right'];
21152 if (($this->blk[$blvl]['border_top']['w'] || $this->blk[$blvl]['padding_top']) && $divider != 'pagetop' && !$continuingpage) {
21153 $bgy0 += $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top'];
21154 }
21155 if (($this->blk[$blvl]['border_bottom']['w'] || $this->blk[$blvl]['padding_bottom']) && $blockstate != 1 && $divider != 'pagebottom') {
21156 $bgy1 -= $this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom'];
21157 }
21158 }
21159 else {
21160 $brbgTL_H = $brTL_H;
21161 $brbgTL_V = $brTL_V;
21162 $brbgTR_H = $brTR_H;
21163 $brbgTR_V = $brTR_V;
21164 $brbgBL_H = $brBL_H;
21165 $brbgBL_V = $brBL_V;
21166 $brbgBR_H = $brBR_H;
21167 $brbgBR_V = $brBR_V;
21168 }
21169
21170 // Set clipping path
21171 $s = ' q 0 w '; // Line width=0
21172 $s .= sprintf('%.3F %.3F m ', ($bgx0+$brbgTL_H )*_MPDFK, ($this->h-$bgy0)*_MPDFK); // start point TL before the arc
21173 /*-- BORDER-RADIUS --*/
21174 if ($brbgTL_H || $brbgTL_V) {
21175 $s .= $this->_EllipseArc($bgx0+$brbgTL_H, $bgy0+$brbgTL_V, $brbgTL_H , $brbgTL_V , 2); // segment 2 TL
21176 }
21177 /*-- END BORDER-RADIUS --*/
21178 $s .= sprintf('%.3F %.3F l ', ($bgx0)*_MPDFK, ($this->h-($bgy1-$brbgBL_V ))*_MPDFK); // line to BL
21179 /*-- BORDER-RADIUS --*/
21180 if ($brbgBL_H || $brbgBL_V) {
21181 $s .= $this->_EllipseArc($bgx0+$brbgBL_H, $bgy1-$brbgBL_V, $brbgBL_H , $brbgBL_V , 3); // segment 3 BL
21182 }
21183 /*-- END BORDER-RADIUS --*/
21184 $s .= sprintf('%.3F %.3F l ', ($bgx1-$brbgBR_H )*_MPDFK, ($this->h-($bgy1))*_MPDFK); // line to BR
21185 /*-- BORDER-RADIUS --*/
21186 if ($brbgBR_H || $brbgBR_V) {
21187 $s .= $this->_EllipseArc($bgx1-$brbgBR_H, $bgy1-$brbgBR_V, $brbgBR_H , $brbgBR_V , 4); // segment 4 BR
21188 }
21189 /*-- END BORDER-RADIUS --*/
21190 $s .= sprintf('%.3F %.3F l ', ($bgx1)*_MPDFK, ($this->h-($bgy0+$brbgTR_V))*_MPDFK); // line to TR
21191 /*-- BORDER-RADIUS --*/
21192 if ($brbgTR_H || $brbgTR_V) {
21193 $s .= $this->_EllipseArc($bgx1-$brbgTR_H, $bgy0+$brbgTR_V, $brbgTR_H , $brbgTR_V , 1); // segment 1 TR
21194 }
21195 /*-- END BORDER-RADIUS --*/
21196 $s .= sprintf('%.3F %.3F l ', ($bgx0+$brbgTL_H )*_MPDFK, ($this->h-$bgy0)*_MPDFK); // line to TL
21197
21198
21199 // Box Shadow
21200 $shadow = '';
21201 if (isset($this->blk[$blvl]['box_shadow']) && $this->blk[$blvl]['box_shadow'] && $h > 0) {
21202 foreach($this->blk[$blvl]['box_shadow'] AS $sh) {
21203 // Colors
21204 if ($sh['col']{0}==1) {
21205 $colspace = 'Gray';
21206 if ($sh['col']{2}==1) { $col1 = '1'.$sh['col'][1].'1'.$sh['col'][3]; }
21207 else { $col1 = '1'.$sh['col'][1].'1'.chr(100); }
21208 $col2 = '1'.$sh['col'][1].'1'.chr(0);
21209 }
21210 else if ($sh['col']{0}==4) { // CMYK
21211 $colspace = 'CMYK';
21212 $col1 = '6'.$sh['col'][1].$sh['col'][2].$sh['col'][3].$sh['col'][4].chr(100);
21213 $col2 = '6'.$sh['col'][1].$sh['col'][2].$sh['col'][3].$sh['col'][4].chr(0);
21214 }
21215 else if ($sh['col']{0}==5) { // RGBa
21216 $colspace = 'RGB';
21217 $col1 = '5'.$sh['col'][1].$sh['col'][2].$sh['col'][3].$sh['col'][4];
21218 $col2 = '5'.$sh['col'][1].$sh['col'][2].$sh['col'][3].chr(0);
21219 }
21220 else if ($sh['col']{0}==6) { // CMYKa
21221 $colspace = 'CMYK';
21222 $col1 = '6'.$sh['col'][1].$sh['col'][2].$sh['col'][3].$sh['col'][4].$sh['col'][5];
21223 $col2 = '6'.$sh['col'][1].$sh['col'][2].$sh['col'][3].$sh['col'][4].chr(0);
21224 }
21225 else {
21226 $colspace = 'RGB';
21227 $col1 = '5'.$sh['col'][1].$sh['col'][2].$sh['col'][3].chr(100);
21228 $col2 = '5'.$sh['col'][1].$sh['col'][2].$sh['col'][3].chr(0);
21229 }
21230
21231 // Use clipping path as set above (and rectangle around page) to clip area outside box
21232 $shadow .= $s; // Use the clipping path with W*
21233 $shadow .= sprintf('0 %.3F m %.3F %.3F l ', $this->h*_MPDFK, $this->w*_MPDFK, $this->h*_MPDFK);
21234 $shadow .= sprintf('%.3F 0 l 0 0 l 0 %.3F l ', $this->w*_MPDFK, $this->h*_MPDFK);
21235 $shadow .= 'W n'."\n";
21236
21237 $sh['blur'] = abs($sh['blur']); // cannot have negative blur value
21238 // Ensure spread/blur do not make effective shadow width/height < 0
21239 // Could do more complex things but this just adjusts spread value
21240 if (-$sh['spread'] + $sh['blur']/2 > min($w/2, $h/2)) {
21241 $sh['spread'] = $sh['blur']/2 - min($w/2, $h/2) + 0.01;
21242 }
21243 // Shadow Offset
21244 if ($sh['x'] || $sh['y']) $shadow .= sprintf(' q 1 0 0 1 %.4F %.4F cm', $sh['x']*_MPDFK, -$sh['y']*_MPDFK)."\n";
21245
21246 // Set path for INNER shadow
21247 $shadow .= ' q 0 w ';
21248 $shadow .= $this->SetFColor($col1, true)."\n";
21249 if ($col1{0}==5 && ord($col1{4})<100) { // RGBa
21250 $shadow .= $this->SetAlpha(ord($col1{4})/100, 'Normal', true, 'F')."\n";
21251 }
21252 else if ($col1{0}==6 && ord($col1{5})<100) { // CMYKa
21253 $shadow .= $this->SetAlpha(ord($col1{5})/100, 'Normal', true, 'F')."\n";
21254 }
21255 else if ($col1{0}==1 && $col1{2}==1 && ord($col1{3})<100) { // Gray
21256 $shadow .= $this->SetAlpha(ord($col1{3})/100, 'Normal', true, 'F')."\n";
21257 }
21258
21259 // Blur edges
21260 $mag = 0.551784; // Bezier Control magic number for 4-part spline for circle/ellipse
21261 $mag2 = 0.551784; // Bezier Control magic number to fill in edge of blurred rectangle
21262 $d1 = $sh['spread']+$sh['blur']/2;
21263 $d2 = $sh['spread']-$sh['blur']/2;
21264 $bl = $sh['blur'];
21265 $x00 = $x0 - $d1;
21266 $y00 = $y0 - $d1;
21267 $w00 = $w + $d1*2;
21268 $h00 = $h + $d1*2;
21269
21270 // If any border-radius is greater width-negative spread(inner edge), ignore radii for shadow or screws up
21271 $flatten = false;
21272 if (max($brbgTR_H, $brbgTL_H, $brbgBR_H, $brbgBL_H) >= $w+$d2) { $flatten = true; }
21273 if (max($brbgTR_V, $brbgTL_V, $brbgBR_V, $brbgBL_V) >= $h+$d2) { $flatten = true; }
21274
21275
21276 // TOP RIGHT corner
21277 $p1x = $x00+$w00-$d1-$brbgTR_H; $p1c2x = $p1x +($d2+$brbgTR_H)*$mag;
21278 $p1y = $y00+$bl;
21279 $p2x = $x00+$w00-$d1-$brbgTR_H; $p2c2x = $p2x + ($d1+$brbgTR_H)*$mag;
21280 $p2y = $y00; $p2c1y = $p2y + $bl/2;
21281 $p3x = $x00+$w00; $p3c2x = $p3x - $bl/2;
21282 $p3y = $y00+$d1+$brbgTR_V; $p3c1y = $p3y - ($d1+$brbgTR_V)*$mag;
21283 $p4x = $x00+$w00-$bl;
21284 $p4y = $y00+$d1+$brbgTR_V; $p4c2y = $p4y - ($d2+$brbgTR_V)*$mag;
21285 if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) {
21286 $p1x = $x00+$w00-$bl; $p1c2x = $p1x;
21287 $p2x = $x00+$w00-$bl; $p2c2x = $p2x + $bl*$mag2;
21288 $p3y = $y00+$bl; $p3c1y = $p3y - $bl*$mag2;
21289 $p4y = $y00+$bl; $p4c2y = $p4y ;
21290 }
21291
21292 $shadow .= sprintf('%.3F %.3F m ', ($p1x )*_MPDFK, ($this->h-($p1y ))*_MPDFK);
21293 $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);
21294 $patch_array[0]['f']=0;
21295 $patch_array[0]['points']=array($p1x,$p1y, $p1x,$p1y,
21296 $p2x,$p2c1y, $p2x,$p2y, $p2c2x,$p2y,
21297 $p3x,$p3c1y, $p3x,$p3y, $p3c2x,$p3y,
21298 $p4x,$p4y, $p4x,$p4y, $p4x,$p4c2y,
21299 $p1c2x,$p1y);
21300 $patch_array[0]['colors'] = array($col1,$col2,$col2,$col1);
21301
21302
21303 // RIGHT
21304 $p1x = $x00+$w00; // control point only matches p3 preceding
21305 $p1y = $y00+$d1+$brbgTR_V;
21306 $p2x = $x00+$w00-$bl; // control point only matches p4 preceding
21307 $p2y = $y00+$d1+$brbgTR_V;
21308 $p3x = $x00+$w00-$bl;
21309 $p3y = $y00+$h00-$d1-$brbgBR_V;
21310 $p4x = $x00+$w00; $p4c1x = $p4x-$bl/2;
21311 $p4y = $y00+$h00-$d1-$brbgBR_V;
21312 if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) {
21313 $p1y = $y00+$bl;
21314 $p2y = $y00+$bl;
21315 }
21316 if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) {
21317 $p3y = $y00+$h00-$bl;
21318 $p4y = $y00+$h00-$bl;
21319 }
21320
21321 $shadow .= sprintf('%.3F %.3F l ', ($p3x )*_MPDFK, ($this->h-($p3y ))*_MPDFK);
21322 $patch_array[1]['f']=2;
21323 $patch_array[1]['points']=array($p2x,$p2y,
21324 $p3x,$p3y, $p3x,$p3y, $p3x,$p3y,
21325 $p4c1x,$p4y, $p4x,$p4y, $p4x,$p4y,
21326 $p1x,$p1y);
21327 $patch_array[1]['colors'] = array($col1,$col2);
21328
21329
21330 // BOTTOM RIGHT corner
21331 $p1x = $x00+$w00-$bl; // control points only matches p3 preceding
21332 $p1y = $y00+$h00-$d1-$brbgBR_V; $p1c2y = $p1y + ($d2+$brbgBR_V)*$mag;
21333 $p2x = $x00+$w00; // control point only matches p4 preceding
21334 $p2y = $y00+$h00-$d1-$brbgBR_V; $p2c2y = $p2y + ($d1+$brbgBR_V)*$mag;
21335 $p3x = $x00+$w00-$d1-$brbgBR_H; $p3c1x = $p3x + ($d1+$brbgBR_H)*$mag;
21336 $p3y = $y00+$h00; $p3c2y = $p3y - $bl/2;
21337 $p4x = $x00+$w00-$d1-$brbgBR_H; $p4c2x = $p4x + ($d2+$brbgBR_H)*$mag;
21338 $p4y = $y00+$h00-$bl;
21339
21340 if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) {
21341 $p1y = $y00+$h00-$bl; $p1c2y = $p1y;
21342 $p2y = $y00+$h00-$bl; $p2c2y = $p2y + $bl*$mag2;
21343 $p3x = $x00+$w00-$bl; $p3c1x = $p3x + $bl*$mag2;
21344 $p4x = $x00+$w00-$bl; $p4c2x = $p4x;
21345 }
21346
21347 $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);
21348 $patch_array[2]['f']=2;
21349 $patch_array[2]['points']=array($p2x,$p2c2y,
21350 $p3c1x,$p3y, $p3x,$p3y, $p3x,$p3c2y,
21351 $p4x,$p4y, $p4x,$p4y, $p4c2x,$p4y,
21352 $p1x,$p1c2y);
21353 $patch_array[2]['colors'] = array($col2,$col1);
21354
21355
21356
21357 // BOTTOM
21358 $p1x = $x00+$w00-$d1-$brbgBR_H; // control point only matches p3 preceding
21359 $p1y = $y00+$h00;
21360 $p2x = $x00+$w00-$d1-$brbgBR_H; // control point only matches p4 preceding
21361 $p2y = $y00+$h00-$bl;
21362 $p3x = $x00+$d1+$brbgBL_H;
21363 $p3y = $y00+$h00-$bl;
21364 $p4x = $x00+$d1+$brbgBL_H;
21365 $p4y = $y00+$h00; $p4c1y = $p4y - $bl/2;
21366
21367 if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) {
21368 $p1x = $x00+$w00-$bl;
21369 $p2x = $x00+$w00-$bl;
21370 }
21371 if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) {
21372 $p3x = $x00+$bl;
21373 $p4x = $x00+$bl;
21374 }
21375
21376 $shadow .= sprintf('%.3F %.3F l ', ($p3x )*_MPDFK, ($this->h-($p3y ))*_MPDFK);
21377 $patch_array[3]['f']=2;
21378 $patch_array[3]['points']=array($p2x,$p2y,
21379 $p3x,$p3y, $p3x,$p3y, $p3x,$p3y,
21380 $p4x,$p4c1y, $p4x,$p4y, $p4x,$p4y,
21381 $p1x,$p1y);
21382 $patch_array[3]['colors'] = array($col1,$col2);
21383
21384 // BOTTOM LEFT corner
21385 $p1x = $x00+$d1+$brbgBL_H; $p1c2x = $p1x - ($d2+$brbgBL_H)*$mag; // control points only matches p3 preceding
21386 $p1y = $y00+$h00-$bl;
21387 $p2x = $x00+$d1+$brbgBL_H; $p2c2x = $p2x - ($d1+$brbgBL_H)*$mag; // control point only matches p4 preceding
21388 $p2y = $y00+$h00;
21389 $p3x = $x00; $p3c2x = $p3x + $bl/2;
21390 $p3y = $y00+$h00-$d1-$brbgBL_V; $p3c1y = $p3y + ($d1+$brbgBL_V)*$mag;
21391 $p4x = $x00+$bl;
21392 $p4y = $y00+$h00-$d1-$brbgBL_V; $p4c2y = $p4y + ($d2+$brbgBL_V)*$mag;
21393 if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) {
21394 $p1x = $x00+$bl; $p1c2x = $p1x;
21395 $p2x = $x00+$bl; $p2c2x = $p2x - $bl*$mag2;
21396 $p3y = $y00+$h00-$bl; $p3c1y = $p3y + $bl*$mag2;
21397 $p4y = $y00+$h00-$bl; $p4c2y = $p4y;
21398 }
21399
21400 $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);
21401 $patch_array[4]['f']=2;
21402 $patch_array[4]['points']=array($p2c2x,$p2y,
21403 $p3x,$p3c1y, $p3x,$p3y, $p3c2x,$p3y,
21404 $p4x,$p4y, $p4x,$p4y, $p4x,$p4c2y,
21405 $p1c2x,$p1y);
21406 $patch_array[4]['colors'] = array($col2,$col1);
21407
21408
21409 // LEFT - joins on the right (C3-C4 of previous): f = 2
21410 $p1x = $x00; // control point only matches p3 preceding
21411 $p1y = $y00+$h00-$d1-$brbgBL_V;
21412 $p2x = $x00+$bl; // control point only matches p4 preceding
21413 $p2y = $y00+$h00-$d1-$brbgBL_V;
21414 $p3x = $x00+$bl;
21415 $p3y = $y00+$d1+$brbgTL_V;
21416 $p4x = $x00; $p4c1x = $p4x + $bl/2;
21417 $p4y = $y00+$d1+$brbgTL_V;
21418 if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) {
21419 $p1y = $y00+$h00-$bl;
21420 $p2y = $y00+$h00-$bl;
21421 }
21422 if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) {
21423 $p3y = $y00+$bl;
21424 $p4y = $y00+$bl;
21425 }
21426
21427 $shadow .= sprintf('%.3F %.3F l ', ($p3x )*_MPDFK, ($this->h-($p3y ))*_MPDFK);
21428 $patch_array[5]['f']=2;
21429 $patch_array[5]['points']=array($p2x,$p2y,
21430 $p3x,$p3y, $p3x,$p3y, $p3x,$p3y,
21431 $p4c1x,$p4y, $p4x,$p4y, $p4x,$p4y,
21432 $p1x,$p1y);
21433 $patch_array[5]['colors'] = array($col1,$col2);
21434
21435 // TOP LEFT corner
21436 $p1x = $x00+$bl; // control points only matches p3 preceding
21437 $p1y = $y00+$d1+$brbgTL_V; $p1c2y = $p1y - ($d2+$brbgTL_V)*$mag;
21438 $p2x = $x00; // control point only matches p4 preceding
21439 $p2y = $y00+$d1+$brbgTL_V; $p2c2y = $p2y - ($d1+$brbgTL_V)*$mag;
21440 $p3x = $x00+$d1+$brbgTL_H; $p3c1x = $p3x - ($d1+$brbgTL_H)*$mag;
21441 $p3y = $y00; $p3c2y = $p3y + $bl/2;
21442 $p4x = $x00+$d1+$brbgTL_H; $p4c2x = $p4x - ($d2+$brbgTL_H)*$mag;
21443 $p4y = $y00+$bl;
21444
21445 if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) {
21446 $p1y = $y00+$bl; $p1c2y = $p1y;
21447 $p2y = $y00+$bl; $p2c2y = $p2y - $bl*$mag2;
21448 $p3x = $x00+$bl; $p3c1x = $p3x - $bl*$mag2;
21449 $p4x = $x00+$bl; $p4c2x = $p4x ;
21450 }
21451
21452 $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);
21453 $patch_array[6]['f']=2;
21454 $patch_array[6]['points']=array($p2x,$p2c2y,
21455 $p3c1x,$p3y, $p3x,$p3y, $p3x,$p3c2y,
21456 $p4x,$p4y, $p4x,$p4y, $p4c2x,$p4y,
21457 $p1x,$p1c2y);
21458 $patch_array[6]['colors'] = array($col2,$col1);
21459
21460
21461 // TOP - joins on the right (C3-C4 of previous): f = 2
21462 $p1x = $x00+$d1+$brbgTL_H; // control point only matches p3 preceding
21463 $p1y = $y00;
21464 $p2x = $x00+$d1+$brbgTL_H; // control point only matches p4 preceding
21465 $p2y = $y00+$bl;
21466 $p3x = $x00+$w00-$d1-$brbgTR_H;
21467 $p3y = $y00+$bl;
21468 $p4x = $x00+$w00-$d1-$brbgTR_H;
21469 $p4y = $y00; $p4c1y = $p4y + $bl/2;
21470 if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) {
21471 $p1x = $x00+$bl;
21472 $p2x = $x00+$bl;
21473 }
21474 if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) {
21475 $p3x = $x00+$w00-$bl;
21476 $p4x = $x00+$w00-$bl;
21477 }
21478
21479 $shadow .= sprintf('%.3F %.3F l ', ($p3x )*_MPDFK, ($this->h-($p3y ))*_MPDFK);
21480 $patch_array[7]['f']=2;
21481 $patch_array[7]['points']=array($p2x,$p2y,
21482 $p3x,$p3y, $p3x,$p3y, $p3x,$p3y,
21483 $p4x,$p4c1y, $p4x,$p4y, $p4x,$p4y,
21484 $p1x,$p1y);
21485 $patch_array[7]['colors'] = array($col1,$col2);
21486
21487 $shadow .= ' h f Q '."\n"; // Close path and Fill the inner solid shadow
21488
21489 if ($bl) $shadow .= $this->grad->CoonsPatchMesh($x00,$y00,$w00,$h00,$patch_array,$x00,$x00+$w00,$y00,$y00+$h00, $colspace, true);
21490
21491 if ($sh['x'] || $sh['y']) $shadow .= ' Q'."\n"; // Shadow Offset
21492 $shadow .= ' Q'."\n"; // Ends path no-op & Sets the clipping path
21493
21494 }
21495 }
21496
21497 $s .= ' W n '; // Ends path no-op & Sets the clipping path
21498
21499 if ($this->blk[$blvl]['bgcolor']) {
21500 $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); // mPDF 5.6.01
21501 }
21502 else if ($shadow) {
21503 $this->pageBackgrounds[$blvl][] = array('shadowonly'=>true, 'col'=>'', 'clippath'=>'', 'visibility'=>$this->visibility, 'shadow'=>$shadow, 'z-index'=>$this->current_layer); // mPDF 5.6.01
21504 }
21505
21506 /*-- BACKGROUNDS --*/
21507 if (isset($this->blk[$blvl]['gradient'])) {
21508 $g = $this->grad->parseBackgroundGradient($this->blk[$blvl]['gradient']);
21509 if ($g) {
21510 $gx = $x0;
21511 $gy = $y0;
21512 $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); // mPDF 5.6.01
21513 }
21514 }
21515 if (isset($this->blk[$blvl]['background-image'])) {
21516 if ($this->blk[$blvl]['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $this->blk[$blvl]['background-image']['gradient'] )) {
21517 $g = $this->grad->parseMozGradient( $this->blk[$blvl]['background-image']['gradient'] );
21518 if ($g) {
21519 $gx = $x0;
21520 $gy = $y0;
21521 // mPDF 5.6.11
21522 // origin specifies the background-positioning-area (bpa)
21523 if ($this->blk[$blvl]['background-image']['origin'] == 'padding-box') {
21524 $gx += $this->blk[$blvl]['border_left']['w'];
21525 $w -= ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['border_right']['w']);
21526 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
21527 $gy += $this->blk[$blvl]['border_top']['w'];
21528 }
21529 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
21530 $gy1 = $y1 - $this->blk[$blvl]['border_bottom']['w'];
21531 }
21532 else { $gy1 = $y1; }
21533 $h = $gy1 - $gy;
21534 }
21535 else if ($this->blk[$blvl]['background-image']['origin'] == 'content-box') {
21536 $gx += $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'];
21537 $w -= ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'] + $this->blk[$blvl]['border_right']['w'] + $this->blk[$blvl]['padding_right']);
21538 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
21539 $gy += $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top'];
21540 }
21541 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
21542 $gy1 = $y1 - ($this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom']);
21543 }
21544 else { $gy1 = $y1 - $this->blk[$blvl]['padding_bottom']; }
21545 $h = $gy1 - $gy;
21546 }
21547
21548 if (isset($this->blk[$blvl]['background-image']['size']['w']) && $this->blk[$blvl]['background-image']['size']['w']) {
21549 $size = $this->blk[$blvl]['background-image']['size'];
21550 if ($size['w']!='contain' && $size['w']!='cover') {
21551 if (stristr($size['w'] ,'%')) {
21552 $size['w'] += 0;
21553 $size['w'] /= 100;
21554 $w *= $size['w'];
21555 }
21556 else if ($size['w']!='auto') {
21557 $w = $size['w'];
21558 }
21559 if (stristr($size['h'] ,'%')) {
21560 $size['h'] += 0;
21561 $size['h'] /= 100;
21562 $h *= $size['h'];
21563 }
21564 else if ($size['h']!='auto') {
21565 $h = $size['h'];
21566 }
21567 }
21568 }
21569 $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); // mPDF 5.6.01
21570 }
21571 }
21572 else {
21573 $image_id = $this->blk[$blvl]['background-image']['image_id'];
21574 $orig_w = $this->blk[$blvl]['background-image']['orig_w'];
21575 $orig_h = $this->blk[$blvl]['background-image']['orig_h'];
21576 $x_pos = $this->blk[$blvl]['background-image']['x_pos'];
21577 $y_pos = $this->blk[$blvl]['background-image']['y_pos'];
21578 $x_repeat = $this->blk[$blvl]['background-image']['x_repeat'];
21579 $y_repeat = $this->blk[$blvl]['background-image']['y_repeat'];
21580 $resize = $this->blk[$blvl]['background-image']['resize'];
21581 $opacity = $this->blk[$blvl]['background-image']['opacity'];
21582 $itype = $this->blk[$blvl]['background-image']['itype'];
21583 $size = $this->blk[$blvl]['background-image']['size']; // mPDF 5.6.10
21584 // mPDF 5.6.10
21585 // origin specifies the background-positioning-area (bpa)
21586 $bpa = array('x'=>$x0, 'y'=>$y0, 'w'=>$w, 'h'=>$h);
21587 if ($this->blk[$blvl]['background-image']['origin'] == 'padding-box') {
21588 $bpa['x'] = $x0 + $this->blk[$blvl]['border_left']['w'];
21589 $bpa['w'] = $w - ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['border_right']['w']);
21590 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
21591 $bpa['y'] = $y0 + $this->blk[$blvl]['border_top']['w'];
21592 }
21593 else { $bpa['y'] = $y0; }
21594 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
21595 $bpay = $y1 - $this->blk[$blvl]['border_bottom']['w'];
21596 }
21597 else { $bpay = $y1; }
21598 $bpa['h'] = $bpay - $bpa['y'];
21599 }
21600 // mPDF 5.6.09
21601 else if ($this->blk[$blvl]['background-image']['origin'] == 'content-box') {
21602 $bpa['x'] = $x0 + $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'];
21603 $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']);
21604 if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) {
21605 $bpa['y'] = $y0 + $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top'];
21606 }
21607 else { $bpa['y'] = $y0 + $this->blk[$blvl]['padding_top']; }
21608 if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') {
21609 $bpay = $y1 - ($this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom']);
21610 }
21611 else { $bpay = $y1 - $this->blk[$blvl]['padding_bottom']; }
21612 $bpa['h'] = $bpay - $bpa['y'];
21613 }
21614 $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 ); // mPDF 5.6.01 5.6.10
21615 }
21616 }
21617 /*-- END BACKGROUNDS --*/
21618
21619 // Float DIV
21620 $this->blk[$blvl]['bb_painted'][$this->page] = true;
21621
21622 }
21623
21624 /*-- BORDER-RADIUS --*/
21625
21626 function _EllipseArc($x0, $y0, $rx, $ry, $seg = 1, $part=false, $start=false) { // Anticlockwise segment 1-4 TR-TL-BL-BR (part=1 or 2)
21627 $s = '';
21628 if ($rx<0) { $rx = 0; }
21629 if ($ry<0) { $ry = 0; }
21630 $rx *= _MPDFK;
21631 $ry *= _MPDFK;
21632 $astart = 0;
21633 if ($seg == 1) { // Top Right
21634 $afinish = 90;
21635 $nSeg = 4;
21636 }
21637 else if ($seg == 2) { // Top Left
21638 $afinish = 180;
21639 $nSeg = 8;
21640 }
21641 else if ($seg == 3) { // Bottom Left
21642 $afinish = 270;
21643 $nSeg = 12;
21644 }
21645 else { // Bottom Right
21646 $afinish = 360;
21647 $nSeg = 16;
21648 }
21649 $astart = deg2rad((float) $astart);
21650 $afinish = deg2rad((float) $afinish);
21651 $totalAngle = $afinish - $astart;
21652 $dt = $totalAngle / $nSeg; // segment angle
21653 $dtm = $dt/3;
21654 $x0 *= _MPDFK;
21655 $y0 = ($this->h - $y0) * _MPDFK;
21656 $t1 = $astart;
21657 $a0 = $x0 + ($rx * cos($t1));
21658 $b0 = $y0 + ($ry * sin($t1));
21659 $c0 = -$rx * sin($t1);
21660 $d0 = $ry * cos($t1);
21661 $op = false;
21662 for ($i = 1; $i <= $nSeg; $i++) {
21663 // Draw this bit of the total curve
21664 $t1 = ($i * $dt) + $astart;
21665 $a1 = $x0 + ($rx * cos($t1));
21666 $b1 = $y0 + ($ry * sin($t1));
21667 $c1 = -$rx * sin($t1);
21668 $d1 = $ry * cos($t1);
21669 if ($i>($nSeg-4) && (!$part || ($part == 1 && $i<=$nSeg-2) || ($part == 2 && $i>$nSeg-2))) {
21670 if ($start && !$op) {
21671 $s .= sprintf('%.3F %.3F m ', $a0, $b0);
21672 }
21673 $s .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($a0 + ($c0 * $dtm)), ($b0 + ($d0 * $dtm)), ($a1 - ($c1 * $dtm)) , ($b1 - ($d1 * $dtm)), $a1 , $b1 );
21674 $op = true;
21675 }
21676 $a0 = $a1;
21677 $b0 = $b1;
21678 $c0 = $c1;
21679 $d0 = $d1;
21680 }
21681 return $s;
21682 }
21683 /*-- END BORDER-RADIUS --*/
21684
21685
21686
21687 function PaintDivLnBorder($state=0,$blvl=0,$h) {
21688 // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom
21689 $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y + $h;
21690
21691 $save_y = $this->y;
21692
21693 $w = $this->blk[$blvl]['width'];
21694 $x0 = $this->x; // left
21695 $y0 = $this->y; // top
21696 $x1 = $this->x + $w; // bottom
21697 $y1 = $this->y + $h; // bottom
21698
21699 if ($this->blk[$blvl]['border_top'] && ($state==1 || $state==3)) {
21700 $tbd = $this->blk[$blvl]['border_top'];
21701 if (isset($tbd['s']) && $tbd['s']) {
21702 $this->_setBorderLine($tbd);
21703 $this->y = $y0 + ($tbd['w']/2);
21704 // mPDF 5.6.56
21705 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') {
21706 $this->_setDashBorder($tbd['style'],'',$continuingpage,'T');
21707 $this->Line($x0 + ($tbd['w']/2) , $this->y , $x0 + $w - ($tbd['w']/2), $this->y);
21708 }
21709 else {
21710 $this->SetLineJoin(0);
21711 $this->SetLineCap(0);
21712 $this->Line($x0, $this->y , $x0 + $w, $this->y);
21713 }
21714 $this->y += $tbd['w'];
21715 // Reset Corners and Dash off
21716 $this->SetLineJoin(2);
21717 $this->SetLineCap(2);
21718 $this->SetDash();
21719 }
21720 }
21721 if ($this->blk[$blvl]['border_left']) {
21722 $tbd = $this->blk[$blvl]['border_left'];
21723 if (isset($tbd['s']) && $tbd['s']) {
21724 $this->_setBorderLine($tbd);
21725 // mPDF 5.6.56
21726 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') {
21727 $this->y = $y0 + ($tbd['w']/2);
21728 $this->_setDashBorder($tbd['style'],'',$continuingpage,'L');
21729 $this->Line($x0 + ($tbd['w']/2), $this->y, $x0 + ($tbd['w']/2), $y0 + $h -($tbd['w']/2));
21730 }
21731 else {
21732 $this->y = $y0;
21733 $this->SetLineJoin(0);
21734 $this->SetLineCap(0);
21735 $this->Line($x0 + ($tbd['w']/2), $this->y, $x0 + ($tbd['w']/2), $y0 + $h);
21736 }
21737 $this->y += $tbd['w'];
21738 // Reset Corners and Dash off
21739 $this->SetLineJoin(2);
21740 $this->SetLineCap(2);
21741 $this->SetDash();
21742 }
21743 }
21744 if ($this->blk[$blvl]['border_right']) {
21745 $tbd = $this->blk[$blvl]['border_right'];
21746 if (isset($tbd['s']) && $tbd['s']) {
21747 $this->_setBorderLine($tbd);
21748 // mPDF 5.6.56
21749 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') {
21750 $this->y = $y0 + ($tbd['w']/2);
21751 $this->_setDashBorder($tbd['style'],'',$continuingpage,'R');
21752 $this->Line($x0 + $w - ($tbd['w']/2), $this->y, $x0 + $w - ($tbd['w']/2), $y0 + $h - ($tbd['w']/2));
21753 }
21754 else {
21755 $this->y = $y0;
21756 $this->SetLineJoin(0);
21757 $this->SetLineCap(0);
21758 $this->Line($x0 + $w - ($tbd['w']/2), $this->y, $x0 + $w - ($tbd['w']/2), $y0 + $h);
21759 }
21760 $this->y += $tbd['w'];
21761 // Reset Corners and Dash off
21762 $this->SetLineJoin(2);
21763 $this->SetLineCap(2);
21764 $this->SetDash();
21765 }
21766 }
21767 if ($this->blk[$blvl]['border_bottom'] && $state > 1) {
21768 $tbd = $this->blk[$blvl]['border_bottom'];
21769 if (isset($tbd['s']) && $tbd['s']) {
21770 $this->_setBorderLine($tbd);
21771 $this->y = $y0 + $h - ($tbd['w']/2);
21772 // mPDF 5.6.56
21773 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') {
21774 $this->_setDashBorder($tbd['style'],'',$continuingpage,'B');
21775 $this->Line($x0 + ($tbd['w']/2) , $this->y, $x0 + $w - ($tbd['w']/2), $this->y);
21776 }
21777 else {
21778 $this->SetLineJoin(0);
21779 $this->SetLineCap(0);
21780 $this->Line($x0, $this->y, $x0 + $w, $this->y);
21781 }
21782 $this->y += $tbd['w'];
21783 // Reset Corners and Dash off
21784 $this->SetLineJoin(2);
21785 $this->SetLineCap(2);
21786 $this->SetDash();
21787 }
21788 }
21789 $this->SetDash();
21790 $this->y = $save_y;
21791 }
21792
21793
21794 function PaintImgBorder($objattr,$is_table) {
21795 // Borders are disabled in columns - messes up the repositioning in printcolumnbuffer
21796 if ($this->ColActive) { return ; } // *COLUMNS*
21797 if ($is_table) { $k = $this->shrin_k; } else { $k = 1; }
21798 $h = (isset($objattr['BORDER-HEIGHT']) ? $objattr['BORDER-HEIGHT'] : 0);
21799 $w = (isset($objattr['BORDER-WIDTH']) ? $objattr['BORDER-WIDTH'] : 0);
21800 $x0 = (isset($objattr['BORDER-X']) ? $objattr['BORDER-X'] : 0);
21801 $y0 = (isset($objattr['BORDER-Y']) ? $objattr['BORDER-Y'] : 0);
21802
21803 // BORDERS
21804 if ($objattr['border_top']) {
21805 $tbd = $objattr['border_top'];
21806 if (!empty($tbd['s'])) {
21807 $this->_setBorderLine($tbd,$k);
21808 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],'','','T'); }
21809 $this->Line($x0, $y0, $x0 + $w, $y0);
21810 // Reset Corners and Dash off
21811 $this->SetLineJoin(2);
21812 $this->SetLineCap(2);
21813 $this->SetDash();
21814 }
21815 }
21816 if ($objattr['border_left']) {
21817 $tbd = $objattr['border_left'];
21818 if (!empty($tbd['s'])) {
21819 $this->_setBorderLine($tbd,$k);
21820 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],'','','L'); }
21821 $this->Line($x0, $y0, $x0, $y0 + $h);
21822 // Reset Corners and Dash off
21823 $this->SetLineJoin(2);
21824 $this->SetLineCap(2);
21825 $this->SetDash();
21826 }
21827 }
21828 if ($objattr['border_right']) {
21829 $tbd = $objattr['border_right'];
21830 if (!empty($tbd['s'])) {
21831 $this->_setBorderLine($tbd,$k);
21832 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],'','','R'); }
21833 $this->Line($x0 + $w, $y0, $x0 + $w, $y0 + $h);
21834 // Reset Corners and Dash off
21835 $this->SetLineJoin(2);
21836 $this->SetLineCap(2);
21837 $this->SetDash();
21838 }
21839 }
21840 if ($objattr['border_bottom']) {
21841 $tbd = $objattr['border_bottom'];
21842 if (!empty($tbd['s'])) {
21843 $this->_setBorderLine($tbd,$k);
21844 if ($tbd['style']=='dotted' || $tbd['style']=='dashed') { $this->_setDashBorder($tbd['style'],'','','B'); }
21845 $this->Line($x0, $y0 + $h, $x0 + $w, $y0 + $h);
21846 // Reset Corners and Dash off
21847 $this->SetLineJoin(2);
21848 $this->SetLineCap(2);
21849 $this->SetDash();
21850 }
21851 }
21852 $this->SetDash();
21853 $this->SetAlpha(1);
21854 }
21855
21856 /*-- END HTML-CSS --*/
21857
21858
21859
21860
21861 function Reset() {
21862 $this->SetTColor($this->ConvertColor(0));
21863 $this->SetDColor($this->ConvertColor(0));
21864 $this->SetFColor($this->ConvertColor(255));
21865 $this->SetAlpha(1);
21866 $this->colorarray = '';
21867
21868 $this->spanbgcolorarray = '';
21869 $this->spanbgcolor = false;
21870 $this->spanborder = false;
21871 $this->spanborddet = array();
21872
21873 $this->ResetStyles();
21874
21875 $this->HREF = '';
21876 $this->textparam = array();
21877 $this->SetTextOutline();
21878
21879 $this->SUP = false;
21880 $this->SUB = false;
21881 $this->strike = false;
21882 $this->textshadow = '';
21883
21884 $this->SetFont($this->default_font,'',0,false);
21885 $this->SetFontSize($this->default_font_size,false);
21886
21887 $this->currentfontfamily = '';
21888 $this->currentfontsize = '';
21889
21890 /*-- TABLES --*/
21891 if ($this->tableLevel) {
21892 $this->SetLineHeight('',$this->table_lineheight); // *TABLES*
21893 }
21894 else
21895 /*-- END TABLES --*/
21896 /*-- LISTS --*/
21897
21898 if ($this->listlvl && $this->list_lineheight[$this->listlvl][$this->bulletarray['occur']]) {
21899 $this->SetLineHeight('',$this->list_lineheight[$this->listlvl][$this->bulletarray['occur']]); // sets default line height
21900 }
21901 else
21902 /*-- END LISTS --*/
21903 if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) {
21904 $this->SetLineHeight('',$this->blk[$this->blklvl]['line_height']); // sets default line height
21905 }
21906
21907 $this->toupper = false;
21908 $this->tolower = false;
21909 $this->kerning = false;
21910 $this->lSpacingCSS = '';
21911 $this->wSpacingCSS = '';
21912 $this->fixedlSpacing = false;
21913 $this->minwSpacing = 0;
21914 $this->capitalize = false;
21915 $this->SetDash(); //restore to no dash
21916 $this->dash_on = false;
21917 $this->dotted_on = false;
21918 $this->divwidth = 0;
21919 $this->divheight = 0;
21920 $this->divalign = '';
21921 $this->divrevert = false;
21922 $this->oldy = -1;
21923
21924 $bodystyle = array();
21925 if (isset($this->cssmgr->CSS['BODY']['FONT-STYLE'])) { $bodystyle['FONT-STYLE'] = $this->cssmgr->CSS['BODY']['FONT-STYLE']; }
21926 if (isset($this->cssmgr->CSS['BODY']['FONT-WEIGHT'])) { $bodystyle['FONT-WEIGHT'] = $this->cssmgr->CSS['BODY']['FONT-WEIGHT']; }
21927 if (isset($this->cssmgr->CSS['BODY']['COLOR'])) { $bodystyle['COLOR'] = $this->cssmgr->CSS['BODY']['COLOR']; }
21928 if (isset($bodystyle)) { $this->setCSS($bodystyle,'BLOCK','BODY'); }
21929
21930 }
21931
21932 /*-- HTML-CSS --*/
21933 function ReadMetaTags($html) {
21934 // changes anykey=anyvalue to anykey="anyvalue" (only do this when this happens inside tags)
21935 $regexp = '/ (\\w+?)=([^\\s>"]+)/si';
21936 $html = preg_replace($regexp," \$1=\"\$2\"",$html);
21937 if (preg_match('/<title>(.*?)<\/title>/si',$html,$m)) {
21938 $this->SetTitle($m[1]);
21939 }
21940 preg_match_all('/<meta [^>]*?(name|content)="([^>]*?)" [^>]*?(name|content)="([^>]*?)".*?>/si',$html,$aux);
21941 $firstattr = $aux[1];
21942 $secondattr = $aux[3];
21943 for( $i = 0 ; $i < count($aux[0]) ; $i++) {
21944
21945 $name = ( strtoupper($firstattr[$i]) == "NAME" )? strtoupper($aux[2][$i]) : strtoupper($aux[4][$i]);
21946 $content = ( strtoupper($firstattr[$i]) == "CONTENT" )? $aux[2][$i] : $aux[4][$i];
21947 switch($name) {
21948 case "KEYWORDS": $this->SetKeywords($content); break;
21949 case "AUTHOR": $this->SetAuthor($content); break;
21950 case "DESCRIPTION": $this->SetSubject($content); break;
21951 }
21952 }
21953 }
21954
21955
21956 function ReadCharset($html) {
21957 // Charset conversion
21958 if ($this->allow_charset_conversion) {
21959 if (preg_match('/<head.*charset=([^\'\"\s]*).*<\/head>/si',$html,$m)) {
21960 if (strtoupper($m[1]) != 'UTF-8') {
21961 $this->charset_in = strtoupper($m[1]);
21962 }
21963 }
21964 }
21965 }
21966
21967 function setCSS($arrayaux,$type='',$tag='') { // type= INLINE | BLOCK | LIST // tag= BODY
21968 if (!is_array($arrayaux)) return; //Removes PHP Warning
21969 // Set font size first so that e.g. MARGIN 0.83em works on font size for this element
21970 if (isset($arrayaux['FONT-SIZE'])) {
21971 $v = $arrayaux['FONT-SIZE'];
21972 if(is_numeric($v[0])) {
21973 if ($type == 'BLOCK' && $this->blklvl>0 && isset($this->blk[$this->blklvl-1]['InlineProperties']) && isset($this->blk[$this->blklvl-1]['InlineProperties']['size'])) {
21974 $mmsize = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['InlineProperties']['size']);
21975 }
21976 else {
21977 $mmsize = $this->ConvertSize($v,$this->FontSize);
21978 }
21979 $this->SetFontSize( $mmsize*(_MPDFK),false ); //Get size in points (pt)
21980 }
21981 else{
21982 $v = strtoupper($v);
21983 if (isset($this->fontsizes[$v])) {
21984 $this->SetFontSize( $this->fontsizes[$v]* $this->default_font_size,false);
21985 }
21986 }
21987 if ($tag == 'BODY') { $this->SetDefaultFontSize($this->FontSizePt); }
21988 }
21989
21990
21991 if ($this->useLang && !$this->usingCoreFont) {
21992 if (isset($arrayaux['LANG']) && $arrayaux['LANG'] && $arrayaux['LANG'] != $this->default_lang && ((strlen($arrayaux['LANG']) == 5 && $arrayaux['LANG'] != 'UTF-8') || strlen($arrayaux['LANG']) == 2)) {
21993 list ($coreSuitable,$mpdf_pdf_unifonts) = GetLangOpts($arrayaux['LANG'], $this->useAdobeCJK);
21994 if ($mpdf_pdf_unifonts) { $this->RestrictUnicodeFonts($mpdf_pdf_unifonts); }
21995 else { $this->RestrictUnicodeFonts($this->default_available_fonts ); }
21996 if ($tag == 'BODY') {
21997 $this->currentLang = $arrayaux['LANG'];
21998 $this->default_lang = $arrayaux['LANG'];
21999 if ($mpdf_pdf_unifonts) { $this->default_available_fonts = $mpdf_pdf_unifonts; }
22000 }
22001 }
22002 else {
22003 $this->RestrictUnicodeFonts($this->default_available_fonts );
22004 }
22005 }
22006
22007 // FOR INLINE and BLOCK OR 'BODY'
22008 if (isset($arrayaux['FONT-FAMILY'])) {
22009 $v = $arrayaux['FONT-FAMILY'];
22010 //If it is a font list, get all font types
22011 $aux_fontlist = explode(",",$v);
22012 $found = 0;
22013 foreach($aux_fontlist AS $f) {
22014 $fonttype = trim($f);
22015 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
22016 $fonttype = preg_replace('/ /','',$fonttype);
22017 $v = strtolower(trim($fonttype));
22018 if (isset($this->fonttrans[$v]) && $this->fonttrans[$v]) { $v = $this->fonttrans[$v]; }
22019 if ((!$this->onlyCoreFonts && in_array($v,$this->available_unifonts)) ||
22020 in_array($v,array('ccourier','ctimes','chelvetica')) ||
22021 ($this->onlyCoreFonts && in_array($v,array('courier','times','helvetica','arial'))) ||
22022 in_array($v, array('sjis','uhc','big5','gb'))) {
22023 $fonttype = $v;
22024 $found = 1;
22025 break;
22026 }
22027 }
22028 if (!$found) {
22029 foreach($aux_fontlist AS $f) {
22030 $fonttype = trim($f);
22031 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
22032 $fonttype = preg_replace('/ /','',$fonttype);
22033 $v = strtolower(trim($fonttype));
22034 if (isset($this->fonttrans[$v]) && $this->fonttrans[$v]) { $v = $this->fonttrans[$v]; }
22035 if (in_array($v,$this->sans_fonts) || in_array($v,$this->serif_fonts) || in_array($v,$this->mono_fonts) ) {
22036 $fonttype = $v;
22037 break;
22038 }
22039 }
22040 }
22041
22042 if ($tag == 'BODY') {
22043 $this->SetDefaultFont($fonttype);
22044 }
22045 $this->SetFont($fonttype,$this->currentfontstyle,0,false);
22046 }
22047 else {
22048 $this->SetFont($this->currentfontfamily,$this->currentfontstyle,0,false);
22049 }
22050
22051 foreach($arrayaux as $k => $v) {
22052 if ($type != 'INLINE' && $tag != 'BODY' && $type != 'LIST') {
22053 switch($k){
22054 // BORDERS
22055 case 'BORDER-TOP':
22056 $this->blk[$this->blklvl]['border_top'] = $this->border_details($v);
22057 if ($this->blk[$this->blklvl]['border_top']['s']) { $this->blk[$this->blklvl]['border'] = 1; }
22058 break;
22059 case 'BORDER-BOTTOM':
22060 $this->blk[$this->blklvl]['border_bottom'] = $this->border_details($v);
22061 if ($this->blk[$this->blklvl]['border_bottom']['s']) { $this->blk[$this->blklvl]['border'] = 1; }
22062 break;
22063 case 'BORDER-LEFT':
22064 $this->blk[$this->blklvl]['border_left'] = $this->border_details($v);
22065 if ($this->blk[$this->blklvl]['border_left']['s']) { $this->blk[$this->blklvl]['border'] = 1; }
22066 break;
22067 case 'BORDER-RIGHT':
22068 $this->blk[$this->blklvl]['border_right'] = $this->border_details($v);
22069 if ($this->blk[$this->blklvl]['border_right']['s']) { $this->blk[$this->blklvl]['border'] = 1; }
22070 break;
22071
22072 // PADDING
22073 case 'PADDING-TOP':
22074 $this->blk[$this->blklvl]['padding_top'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22075 break;
22076 case 'PADDING-BOTTOM':
22077 $this->blk[$this->blklvl]['padding_bottom'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22078 break;
22079 case 'PADDING-LEFT':
22080 $this->blk[$this->blklvl]['padding_left'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22081 break;
22082 case 'PADDING-RIGHT':
22083 $this->blk[$this->blklvl]['padding_right'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22084 break;
22085
22086 // MARGINS
22087 case 'MARGIN-TOP':
22088 $tmp = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22089 if (isset($this->blk[$this->blklvl]['lastbottommargin'])) {
22090 if ($tmp > $this->blk[$this->blklvl]['lastbottommargin']) {
22091 $tmp -= $this->blk[$this->blklvl]['lastbottommargin'];
22092 }
22093 else {
22094 $tmp = 0;
22095 }
22096 }
22097 $this->blk[$this->blklvl]['margin_top'] = $tmp;
22098 break;
22099 case 'MARGIN-BOTTOM':
22100 $this->blk[$this->blklvl]['margin_bottom'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22101 break;
22102 case 'MARGIN-LEFT':
22103 $this->blk[$this->blklvl]['margin_left'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22104 break;
22105 case 'MARGIN-RIGHT':
22106 $this->blk[$this->blklvl]['margin_right'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22107 break;
22108
22109 /*-- BORDER-RADIUS --*/
22110 case 'BORDER-TOP-LEFT-RADIUS-H':
22111 $this->blk[$this->blklvl]['border_radius_TL_H'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22112 break;
22113 case 'BORDER-TOP-LEFT-RADIUS-V':
22114 $this->blk[$this->blklvl]['border_radius_TL_V'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22115 break;
22116 case 'BORDER-TOP-RIGHT-RADIUS-H':
22117 $this->blk[$this->blklvl]['border_radius_TR_H'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22118 break;
22119 case 'BORDER-TOP-RIGHT-RADIUS-V':
22120 $this->blk[$this->blklvl]['border_radius_TR_V'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22121 break;
22122 case 'BORDER-BOTTOM-LEFT-RADIUS-H':
22123 $this->blk[$this->blklvl]['border_radius_BL_H'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22124 break;
22125 case 'BORDER-BOTTOM-LEFT-RADIUS-V':
22126 $this->blk[$this->blklvl]['border_radius_BL_V'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22127 break;
22128 case 'BORDER-BOTTOM-RIGHT-RADIUS-H':
22129 $this->blk[$this->blklvl]['border_radius_BR_H'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22130 break;
22131 case 'BORDER-BOTTOM-RIGHT-RADIUS-V':
22132 $this->blk[$this->blklvl]['border_radius_BR_V'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22133 break;
22134 /*-- END BORDER-RADIUS --*/
22135
22136 case 'BOX-SHADOW':
22137 $bs = $this->cssmgr->setCSSboxshadow($v);
22138 if ($bs) { $this->blk[$this->blklvl]['box_shadow'] = $bs; }
22139 break;
22140
22141 case 'BACKGROUND-CLIP':
22142 if (strtoupper($v) == 'PADDING-BOX') { $this->blk[$this->blklvl]['background_clip'] = 'padding-box'; }
22143 else if (strtoupper($v) == 'CONTENT-BOX') { $this->blk[$this->blklvl]['background_clip'] = 'content-box'; } // mPDF 5.6.09
22144 break;
22145
22146 case 'PAGE-BREAK-AFTER':
22147 if (strtoupper($v) == 'AVOID') { $this->blk[$this->blklvl]['page_break_after_avoid'] = true; }
22148 else if (strtoupper($v) == 'ALWAYS' || strtoupper($v) == 'LEFT' || strtoupper($v) == 'RIGHT') { $this->blk[$this->blklvl]['page_break_after'] = strtoupper($v) ; }
22149 break;
22150
22151 case 'WIDTH':
22152 if (strtoupper($v) != 'AUTO') {
22153 $this->blk[$this->blklvl]['css_set_width'] = $this->ConvertSize($v,$this->blk[$this->blklvl-1]['inner_width'],$this->FontSize,false);
22154 }
22155 break;
22156
22157 case 'TEXT-INDENT':
22158 // Left as raw value (may include 1% or 2em)
22159 $this->blk[$this->blklvl]['text_indent'] = $v;
22160 break;
22161
22162 }//end of switch($k)
22163 }
22164
22165
22166 if ($type != 'INLINE' && $type != 'LIST') { // includes BODY tag
22167 switch($k){
22168
22169 case 'MARGIN-COLLAPSE': // Custom tag to collapse margins at top and bottom of page
22170 if (strtoupper($v) == 'COLLAPSE') { $this->blk[$this->blklvl]['margin_collapse'] = true; }
22171 break;
22172
22173 case 'LINE-HEIGHT':
22174 $this->blk[$this->blklvl]['line_height'] = $this->fixLineheight($v);
22175 if (!$this->blk[$this->blklvl]['line_height'] ) { $this->blk[$this->blklvl]['line_height'] = $this->normalLineheight; }
22176 break;
22177
22178 case 'TEXT-ALIGN': //left right center justify
22179 switch (strtoupper($v)) {
22180 case 'LEFT':
22181 $this->blk[$this->blklvl]['align']="L";
22182 break;
22183 case 'CENTER':
22184 $this->blk[$this->blklvl]['align']="C";
22185 break;
22186 case 'RIGHT':
22187 $this->blk[$this->blklvl]['align']="R";
22188 break;
22189 case 'JUSTIFY':
22190 $this->blk[$this->blklvl]['align']="J";
22191 break;
22192 }
22193 break;
22194
22195 /*-- BACKGROUNDS --*/
22196 case 'BACKGROUND-GRADIENT':
22197 if ($type == 'BLOCK') {
22198 $this->blk[$this->blklvl]['gradient'] = $v;
22199 }
22200 break;
22201 /*-- END BACKGROUNDS --*/
22202
22203 case 'DIRECTION':
22204 if ($v) { $this->blk[$this->blklvl]['direction'] = strtolower($v); }
22205 break;
22206
22207 }//end of switch($k)
22208 }
22209
22210 // FOR INLINE ONLY
22211 if ($type == 'INLINE' || $type == 'LIST') {
22212 switch($k){
22213 case 'DISPLAY': // Custom tag to collapse margins at top and bottom of page
22214 if (strtoupper($v) == 'NONE') { $this->inlineDisplayOff = true; }
22215 break;
22216 case 'DIRECTION':
22217 break;
22218 }//end of switch($k)
22219 }
22220 // FOR INLINE ONLY
22221 if ($type == 'INLINE') {
22222 switch($k){
22223 // BORDERS
22224 case 'BORDER-TOP':
22225 $this->spanborddet['T'] = $this->border_details($v);
22226 $this->spanborder = true;
22227 break;
22228 case 'BORDER-BOTTOM':
22229 $this->spanborddet['B'] = $this->border_details($v);
22230 $this->spanborder = true;
22231 break;
22232 case 'BORDER-LEFT':
22233 $this->spanborddet['L'] = $this->border_details($v);
22234 $this->spanborder = true;
22235 break;
22236 case 'BORDER-RIGHT':
22237 $this->spanborddet['R'] = $this->border_details($v);
22238 $this->spanborder = true;
22239 break;
22240 // mPDF 5.6.26
22241 case 'VISIBILITY': // block is set in OpenTag
22242 $v = strtolower($v);
22243 if ($v == 'visible' || $v == 'hidden' || $v == 'printonly' || $v == 'screenonly') {
22244 $this->textparam['visibility'] = $v;
22245 }
22246 break;
22247 }//end of switch($k)
22248 }
22249
22250
22251 // FOR INLINE and BLOCK
22252 switch($k){
22253 case 'TEXT-ALIGN': //left right center justify
22254 if (strtoupper($v) == 'NOJUSTIFY' && $this->blk[$this->blklvl]['align']=="J") {
22255 $this->blk[$this->blklvl]['align']="";
22256 }
22257 break;
22258 // bgcolor only - to stay consistent with original html2fpdf
22259 case 'BACKGROUND':
22260 case 'BACKGROUND-COLOR':
22261 $cor = $this->ConvertColor($v);
22262 if ($cor) {
22263 if ($tag == 'BODY') {
22264 $this->bodyBackgroundColor = $cor;
22265 }
22266 else if ($type == 'INLINE' || $type == 'LIST') {
22267 $this->spanbgcolorarray = $cor;
22268 $this->spanbgcolor = true;
22269 }
22270 else {
22271 $this->blk[$this->blklvl]['bgcolorarray'] = $cor;
22272 $this->blk[$this->blklvl]['bgcolor'] = true;
22273 }
22274 }
22275 else if ($type != 'INLINE' && $type != 'LIST') {
22276 if ($this->ColActive || $this->keep_block_together) {
22277 $this->blk[$this->blklvl]['bgcolorarray'] = $this->blk[$this->blklvl-1]['bgcolorarray'] ;
22278 $this->blk[$this->blklvl]['bgcolor'] = $this->blk[$this->blklvl-1]['bgcolor'] ;
22279 }
22280 }
22281 break;
22282
22283 // auto | normal | none
22284 case 'FONT-KERNING':
22285 if ((strtoupper($v) == 'NORMAL' || strtoupper($v) == 'AUTO') && $this->useKerning) { $this->kerning = true; }
22286 else if (strtoupper($v) == 'NONE') { $this->kerning = false; }
22287 break;
22288
22289
22290 // normal | <length>
22291 case 'LETTER-SPACING':
22292 $this->lSpacingCSS = $v;
22293 if (($this->lSpacingCSS || $this->lSpacingCSS==='0') && strtoupper($this->lSpacingCSS) != 'NORMAL') {
22294 $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize);
22295 }
22296 break;
22297
22298 // normal | <length>
22299 case 'WORD-SPACING':
22300 $this->wSpacingCSS = $v;
22301 if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') {
22302 $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize);
22303 }
22304 break;
22305
22306 case 'FONT-STYLE': // italic normal oblique
22307 switch (strtoupper($v)) {
22308 case 'ITALIC':
22309 case 'OBLIQUE':
22310 $this->SetStyle('I',true);
22311 break;
22312 case 'NORMAL':
22313 $this->SetStyle('I',false);
22314 break;
22315 }
22316 break;
22317
22318 case 'FONT-WEIGHT': // normal bold //Does not support: bolder, lighter, 100..900(step value=100)
22319 switch (strtoupper($v)) {
22320 case 'BOLD':
22321 $this->SetStyle('B',true);
22322 break;
22323 case 'NORMAL':
22324 $this->SetStyle('B',false);
22325 break;
22326 }
22327 break;
22328
22329 case 'VERTICAL-ALIGN': //super and sub only dealt with here e.g. <SUB> and <SUP>
22330 switch (strtoupper($v)) {
22331 case 'SUPER':
22332 $this->SUP=true;
22333 $this->SUB=false; // mPDF 5.6.07
22334 break;
22335 case 'SUB':
22336 $this->SUB=true;
22337 $this->SUP=false; // mPDF 5.6.07
22338 break;
22339 case 'BASELINE': // mPDF 5.6.07
22340 $this->SUB=false;
22341 $this->SUP=false;
22342 break;
22343 }
22344 break;
22345
22346 case 'TEXT-DECORATION': // none underline line-through (strikeout) //Does not support: overline, blink
22347 if (stristr($v,'LINE-THROUGH')) {
22348 $this->strike = true;
22349 }
22350 else if (stristr($v,'UNDERLINE')) {
22351 $this->SetStyle('U',true);
22352 }
22353 else if (stristr($v,'NONE')) {
22354 $this->SetStyle('U',false);
22355 $this->strike = false; // mPDF 5.6.07
22356 }
22357 break;
22358
22359 case 'FONT-VARIANT':
22360 switch (strtoupper($v)) {
22361 case 'SMALL-CAPS':
22362 $this->SetStyle('S',true);
22363 break;
22364 case 'NORMAL':
22365 $this->SetStyle('S',false);
22366 break;
22367 }
22368 break;
22369
22370 case 'TEXT-TRANSFORM': // none uppercase lowercase //Does support: capitalize
22371 switch (strtoupper($v)) { //Not working 100%
22372 case 'CAPITALIZE':
22373 $this->capitalize=true;
22374 break;
22375 case 'UPPERCASE':
22376 $this->toupper=true;
22377 break;
22378 case 'LOWERCASE':
22379 $this->tolower=true;
22380 break;
22381 case 'NONE': break;
22382 }
22383 break;
22384
22385 case 'TEXT-SHADOW':
22386 $ts = $this->cssmgr->setCSStextshadow($v);
22387 if ($ts) { $this->textshadow = $ts; }
22388 break;
22389
22390 case 'HYPHENS': // mPDF 5.6.08
22391 if (strtoupper($v)=='NONE') {
22392 $this->textparam['hyphens'] = 2;
22393 }
22394 else if (strtoupper($v)=='AUTO') {
22395 $this->textparam['hyphens'] = 1;
22396 }
22397 else if (strtoupper($v)=='MANUAL') {
22398 $this->textparam['hyphens'] = 0;
22399 }
22400 break;
22401
22402 case 'TEXT-OUTLINE': // mPDF 5.6.07
22403 if (strtoupper($v)=='NONE') {
22404 $this->textparam['outline-s'] = false;
22405 }
22406 break;
22407
22408 case 'TEXT-OUTLINE-WIDTH': // mPDF 5.6.07
22409 case 'OUTLINE-WIDTH':
22410 switch(strtoupper($v)) {
22411 case 'THIN': $v = '0.03em'; break;
22412 case 'MEDIUM': $v = '0.05em'; break;
22413 case 'THICK': $v = '0.07em'; break;
22414 }
22415 $w = $this->ConvertSize($v,$this->blk[$this->blklvl]['inner_width'],$this->FontSize);
22416 if ($w) {
22417 $this->textparam['outline-WIDTH'] = $w;
22418 $this->textparam['outline-s'] = true;
22419 }
22420 else { $this->textparam['outline-s'] = false; }
22421 break;
22422
22423 case 'TEXT-OUTLINE-COLOR': // mPDF 5.6.07
22424 case 'OUTLINE-COLOR':
22425 if (strtoupper($v) == 'INVERT') {
22426 if ($this->colorarray) {
22427 $cor = $this->colorarray;
22428 $this->textparam['outline-COLOR'] = $this->_invertColor($cor);
22429 }
22430 else {
22431 $this->textparam['outline-COLOR'] = $this->ConvertColor(255);
22432 }
22433 }
22434 else {
22435 $cor = $this->ConvertColor($v);
22436 if ($cor) { $this->textparam['outline-COLOR'] = $cor ; }
22437 }
22438 break;
22439
22440 case 'COLOR': // font color
22441 $cor = $this->ConvertColor($v);
22442 if ($cor) {
22443 $this->colorarray = $cor;
22444 $this->SetTColor($cor);
22445 }
22446 break;
22447
22448
22449 }//end of switch($k)
22450
22451
22452 }//end of foreach
22453 }
22454
22455 /*-- END HTML-CSS --*/
22456
22457
22458 function SetStyle($tag,$enable) {
22459 $this->$tag=$enable;
22460 $style='';
22461 foreach(array('B','I','U','S') as $s) {
22462 if($this->$s) {
22463 $style.=$s;
22464 }
22465 }
22466 if ($this->S && empty($this->upperCase)) { @include(_MPDF_PATH.'includes/upperCase.php'); }
22467 $this->currentfontstyle=$style;
22468 $this->SetFont('',$style,0,false);
22469 }
22470
22471 // Set multiple styles at one $str e.g. "BIS"
22472 function SetStylesArray($arr) {
22473 $style='';
22474 foreach(array('B','I','U','S') as $s) {
22475 if (isset($arr[$s])) {
22476 if ($arr[$s]) {
22477 $this->$s = true;
22478 $style.=$s;
22479 }
22480 else { $this->$s = false; }
22481 }
22482 else if ($this->$s) { $style.=$s; }
22483 }
22484 $this->currentfontstyle=$style;
22485 $this->SetFont('',$style,0,false);
22486 }
22487
22488 // Set multiple styles at one $str e.g. "BIS"
22489 function SetStyles($str) {
22490 $style='';
22491 foreach(array('B','I','U','S') as $s) {
22492 if (strpos($str,$s) !== false) {
22493 $this->$s = true;
22494 $style.=$s;
22495 }
22496 else { $this->$s = false; }
22497 }
22498 $this->currentfontstyle=$style;
22499 $this->SetFont('',$style,0,false);
22500 }
22501
22502 function ResetStyles() {
22503 foreach(array('B','I','U','S') as $s) {
22504 $this->$s = false;
22505 }
22506 $this->currentfontstyle='';
22507 $this->SetFont('','',0,false);
22508 }
22509
22510
22511 function DisableTags($str='')
22512 {
22513 if ($str == '') //enable all tags
22514 {
22515 //Insert new supported tags in the long string below.
22516 $this->enabledtags = "<span><s><strike><del><bdo><big><small><ins><cite><acronym><font><sup><sub><b><u><i><a><strong><em><code><samp><tt><kbd><var><q><table><thead><tfoot><tbody><tr><th><td><ol><ul><li><dl><dt><dd><form><input><select><textarea><option><div><p><h1><h2><h3><h4><h5><h6><pre><center><blockquote><address><hr><img><br><indexentry><indexinsert><bookmark><watermarktext><watermarkimage><tts><ttz><tta><column_break><columnbreak><newcolumn><newpage><page_break><pagebreak><formfeed><columns><toc><tocentry><tocpagebreak><pageheader><pagefooter><setpageheader><setpagefooter><sethtmlpageheader><sethtmlpagefooter><annotation><template><jpgraph><barcode><dottab><caption><textcircle><fieldset><legend><article><aside><figure><figcaption><footer><header><hgroup><nav><section><mark><details><summary><meter><progress><time>"; // mPDF 5.5.09
22517 }
22518 else
22519 {
22520 $str = explode(",",$str);
22521 foreach($str as $v) $this->enabledtags = str_replace(trim($v),'',$this->enabledtags);
22522 }
22523 }
22524
22525
22526 /*-- TABLES --*/
22527
22528 function finaliseCellLineHeight($lhxt, $maxfontsize, $maxlineHeight, $lhfixed, $forceExactLineheight) {
22529 $af = 0; // Above font
22530 $bf = 0; // Below font
22531 $mta = 0; // Maximum top-aligned
22532 $mba = 0; // Maximum bottom-aligned
22533 if ($lhxt['BS']) {
22534 $af = max($af, ($lhxt['BS'] - ($maxfontsize * (0.5 + $this->baselineC))));
22535 }
22536 if ($lhxt['M']) {
22537 $af = max($af, ($lhxt['M'] - $maxfontsize)/2);
22538 $bf = max($bf, ($lhxt['M'] - $maxfontsize)/2);
22539 }
22540 if ($lhxt['TT']) {
22541 $bf = max($bf, ($lhxt['TT'] - $maxfontsize));
22542 }
22543 if ($lhxt['TB']) {
22544 $af = max($af, ($lhxt['TB'] - $maxfontsize));
22545 }
22546 if ($lhxt['T']) {
22547 $mta = max($mta, $lhxt['T']);
22548 }
22549 if ($lhxt['B']) {
22550 $mba = max($mba, $lhxt['B']);
22551 }
22552 if ((!$lhfixed || !$forceExactLineheight) && ($af > (($maxlineHeight - $maxfontsize)/2) || $bf > (($maxlineHeight - $maxfontsize)/2))) {
22553 $maxlineHeight = $maxfontsize + $af + $bf;
22554 }
22555 else if (!$lhfixed) { $af = $bf = ($maxlineHeight - $maxfontsize)/2; }
22556 if ($mta > $maxlineHeight) {
22557 $bf += ($mta - $maxlineHeight);
22558 $maxlineHeight = $mta;
22559 }
22560 if ($mba > $maxlineHeight) {
22561 $af += ($mba - $maxlineHeight);
22562 $maxlineHeight = $mba;
22563 }
22564 return $maxlineHeight;
22565 }
22566
22567 function TableWordWrap($maxwidth, $forcewrap = 0, $textbuffer = '', $def_fontsize, $returnarray=false) { // NB ** returnarray used in flowchart
22568 $biggestword=0;
22569 $toonarrow=false;
22570
22571 $textbuffer[0][0] = preg_replace('/^[ ]*/','',$textbuffer[0][0]);
22572 if ((count($textbuffer) == 0) or ((count($textbuffer) == 1) && ($textbuffer[0][0] == ''))) { return 0; }
22573
22574 $text = '';
22575 $lhfixed = false;
22576 if (preg_match('/([0-9.,]+)mm/',$this->table_lineheight)) { $lhfixed = true; }
22577 if ($lhfixed) { $def_lineheight = $this->_computeLineheight($this->table_lineheight, $def_fontsize);}
22578 else { $def_lineheight = 0; }
22579 // START OF NEW LINE
22580 // Initialise lineheight variables
22581 $maxfontsize = 0;
22582 $forceExactLineheight = true;
22583 $lhxt = array('BS'=>0, 'M'=>0, 'TT'=>0, 'TB'=>0, 'T'=>0, 'B'=>0);
22584 $maxlineHeight = $def_lineheight ;
22585 $ch = 0;
22586 $width = 0;
22587 $ln = 1; // Counts line number
22588 $mxw = $this->GetCharWidth('W',false);
22589 for($cctr=0;$cctr<count($textbuffer);$cctr++) { // mPDF 5.6.22
22590 $chunk = $textbuffer[$cctr]; // mPDF 5.6.22
22591 $line = $chunk[0];
22592 //IMAGE
22593 if (substr($line,0,3) == "\xbb\xa4\xac") { //identifier has been identified!
22594 $objattr = $this->_getObjAttr($line);
22595 if ($objattr['type'] == 'nestedtable') {
22596 // END OF LINE
22597 // Finalise & add lineheight
22598 $ch += $this->finaliseCellLineHeight($lhxt, $maxfontsize, $maxlineHeight, $lhfixed, $forceExactLineheight);
22599 $level = $objattr['level'];
22600 $ih = $this->table[($level+1)][$objattr['nestedcontent']]['h']; // nested table width
22601 $ch += $ih;
22602 // START OF NEW LINE
22603 // Initialise lineheight variables
22604 $ln++;
22605 $maxfontsize = 0;
22606 $forceExactLineheight = true;
22607 $lhxt = array('BS'=>0, 'M'=>0, 'TT'=>0, 'TB'=>0, 'T'=>0, 'B'=>0);
22608 $maxlineHeight = $def_lineheight ;
22609 $width = 0;
22610 $text = "";
22611 continue;
22612 }
22613
22614 list($skipln,$iw,$ih) = $this->inlineObject((isset($specialcontent['type']) ? $specialcontent['type'] : null),0,0, $objattr, $this->lMargin,$width,$maxwidth,$maxlineHeight,false,true);
22615 if ($objattr['type'] == 'hr') {
22616 // END OF LINE
22617 // Finalise & add lineheight
22618 $ch += $this->finaliseCellLineHeight($lhxt, $maxfontsize, $maxlineHeight, $lhfixed, $forceExactLineheight);
22619 // Add HR height
22620 $ch += $ih;
22621 // START OF NEW LINE
22622 // Initialise lineheight variables
22623 $ln++;
22624 $maxfontsize = 0;
22625 $forceExactLineheight = true;
22626 $lhxt = array('BS'=>0, 'M'=>0, 'TT'=>0, 'TB'=>0, 'T'=>0, 'B'=>0);
22627 $maxlineHeight = $def_lineheight ;
22628 $width = 0;
22629 $text = "";
22630 continue;
22631 }
22632
22633 if ($skipln==1 || $skipln==-2) {
22634 // Finish last line
22635 // END OF LINE
22636 // Finalise & add lineheight
22637 $ch += $this->finaliseCellLineHeight($lhxt, $maxfontsize, $maxlineHeight, $lhfixed, $forceExactLineheight);
22638 // START OF NEW LINE
22639 // Initialise lineheight variables
22640 $maxfontsize = 0;
22641 $forceExactLineheight = true;
22642 $lhxt = array('BS'=>0, 'M'=>0, 'TT'=>0, 'TB'=>0, 'T'=>0, 'B'=>0);
22643 $maxlineHeight = $def_lineheight ;
22644 $ln++;
22645 $width = 0;
22646 $text = "";
22647 }
22648 $va = (isset($objattr['vertical-align']) ? $objattr['vertical-align'] : null);
22649 if ($va) {
22650 $lhxt[$va] = max($lhxt[$va], $ih);
22651 }
22652 if ($lhfixed && $ih > $def_fontsize) { $forceExactLineheight = false; }
22653 $maxlineHeight = max($maxlineHeight ,$ih);
22654 $width += $iw;
22655 continue;
22656 }
22657
22658 // SET FONT SIZE/STYLE from $chunk[n]
22659 // FONTSIZE
22660 if(isset($chunk[11]) and $chunk[11] != '') {
22661 if ($this->shrin_k) {
22662 $this->SetFontSize($chunk[11]/$this->shrin_k,false);
22663 }
22664 else {
22665 $this->SetFontSize($chunk[11],false);
22666 }
22667 }
22668 if ($line == "\n") {
22669 // END OF LINE
22670 $maxfontsize = max($maxfontsize,$this->FontSize);
22671 $fh = $this->_computeLineheight($this->table_lineheight);
22672 if ($lhfixed && $this->FontSize > $def_fontsize) {
22673 $fh = $this->FontSize;
22674 $forceExactLineheight = false;
22675 }
22676 $maxlineHeight = max($maxlineHeight,$fh);
22677
22678 // Finalise & add lineheight
22679 $ch += $this->finaliseCellLineHeight($lhxt, $maxfontsize, $maxlineHeight, $lhfixed, $forceExactLineheight);
22680 // START OF NEW LINE
22681 // Initialise lineheight variables
22682 $maxfontsize = 0;
22683 $forceExactLineheight = true;
22684 $lhxt = array('BS'=>0, 'M'=>0, 'TT'=>0, 'TB'=>0, 'T'=>0, 'B'=>0);
22685 $maxlineHeight = $this->_computeLineheight($this->table_lineheight);
22686 $ln++;
22687 $text = "";
22688 $width = 0;
22689 if(isset($chunk[11]) and $chunk[11] != '') {
22690 $this->SetFontSize($this->default_font_size,false);
22691 }
22692 continue;
22693 }
22694
22695 $lbw = $rbw = 0; // Border widths
22696 if(isset($chunk[16]) && !empty($chunk[16])) { //Border
22697 $this->spanborddet = $chunk[16];
22698 if (isset($this->spanborddet['L'])) $lbw = $this->spanborddet['L']['w'];
22699 if (isset($this->spanborddet['R'])) $rbw = $this->spanborddet['R']['w'];
22700 }
22701 if(isset($chunk[15])) { // Word spacing
22702 $this->wSpacingCSS = $chunk[15];
22703 if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') {
22704 $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize);
22705 }
22706 }
22707 if(isset($chunk[14])) { // Letter spacing
22708 $this->lSpacingCSS = $chunk[14];
22709 if (($this->lSpacingCSS || $this->lSpacingCSS==='0') && strtoupper($this->lSpacingCSS) != 'NORMAL') {
22710 $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize);
22711 }
22712 }
22713 if(isset($chunk[13])) { // Font Kerning
22714 $this->kerning = $chunk[13];
22715 }
22716 if(isset($chunk[9])) { // Text params - Outline, hyphens // mPDF 5.6.08
22717 $this->textparam = $chunk[9];
22718 }
22719 // FONTFAMILY
22720 if(isset($chunk[4]) and $chunk[4] != '') { $font = $this->SetFont($chunk[4],$this->FontStyle,0,false); }
22721
22722 // FONT STYLE B I U
22723 if(isset($chunk[2]) and $chunk[2] != '') {
22724 $this->SetStyles($chunk[2]);
22725 }
22726
22727 $space = $this->GetCharWidth(' ',false);
22728
22729 if (mb_substr($line,0,1,$this->mb_enc ) == ' ') { // line (chunk) starts with a space
22730 $width += $space;
22731 $text .= ' ';
22732 }
22733
22734 if (mb_substr($line,(mb_strlen($line,$this->mb_enc )-1),1,$this->mb_enc ) == ' ') { $lsend = true; } // line (chunk) ends with a space
22735 else { $lsend = false; }
22736 $line= trim($line);
22737 if ($line == '') { continue; }
22738
22739 // mPDF ITERATION
22740 if ($this->iterationCounter) $line = preg_replace('/{iteration ([a-zA-Z0-9_]+)}/','\\1', $line);
22741
22742 $words = explode(' ', $line);
22743
22744 foreach ($words as $k=>$word) {
22745 $word = trim($word);
22746 $wordwidth = $this->GetStringWidth($word);
22747 if ($k==0) { $wordwidth += $lbw; }
22748 if ($k==(count($words)-1)) { $wordwidth += $rbw; }
22749 //maxwidth is insufficient for one word
22750 if ($wordwidth > $maxwidth + 0.0001) {
22751 $firstchunk=true;
22752 while($wordwidth > $maxwidth + 0.0001) {
22753 $chw = 0; // check width
22754 $oneCJKorphan = false;
22755 $mlen = mb_strlen($word, $this->mb_enc );
22756 for ( $i = 0; $i < $mlen; $i++ ) {
22757 $chw = $this->GetStringWidth(mb_substr($word,0,$i+1,$this->mb_enc ));
22758 if ($k==0) { $chw += $lbw; }
22759 if ($k==(count($words)-1)) { $chw += $rbw; }
22760 if ($chw > $maxwidth) {
22761 if ($i==0 && $firstchunk) {
22762 // If first letter of line does not fit
22763 $wordwidth = $maxwidth - 0.0001;
22764 if ($this->debug) { $this->Error("Table cell width calculated less than that needed for one character!"); }
22765 break;
22766 }
22767 /*-- CJK-FONTS --*/
22768 // mPDF 5.6.40 mPDF 5.6.44
22769 if ($this->checkCJK && !$this->usingCoreFont && preg_match("/[".$this->pregCJKchars."]/u", $word)) { // mPDF 5.6.44
22770 if (!$oneCJKorphan && preg_match('/['.$this->CJKoverflow.']$/u',mb_substr($word,0,$i+1,$this->mb_enc )) && $this->allowCJKorphans) {
22771 $wordwidth = $maxwidth - 0.0001;
22772 $oneCJKorphan = true;
22773 continue;
22774 }
22775 $cjkfix = 0;
22776 // Last character that fits is not allowed to end a line - move lastchar(s) to start of next line
22777 if ($i>0 && preg_match("/[".$this->CJKleading."$]/u", mb_substr($word,0,$i,$this->mb_enc ))) {
22778 $cjkfix = 1;
22779 }
22780 // Next character is not allowed to start a new line
22781 else if (preg_match("/[".$this->CJKfollowing."]/u", mb_substr($word,$i,1,$this->mb_enc ))) {
22782 // try squeezing another character(s) onto this line = Oikomi
22783 if ($this->allowCJKorphans && !$oneCJKorphan) {
22784 //if lookahead is not another following char
22785 if ($i==($mlen-1) || ($i<($mlen-1) && !preg_match("/[".$this->CJKfollowing."]/u", mb_substr($word,$i+1,1,$this->mb_enc )))) {
22786 $wordwidth = $maxwidth - 0.0001;
22787 $oneCJKorphan = true;
22788 continue;
22789 }
22790 }
22791 // or move lastchar(s) to next line
22792 $cjkfix = 2;
22793 }
22794 // mPDF 5.6.42
22795 // CJK numerals kept together
22796 else if (preg_match("/([".$this->pregCJKchars."]+[0-9\x{ff10}-\x{ff19}]+$)/u", mb_substr($word,0,$i,$this->mb_enc )) && preg_match("/^([0-9\x{ff10}-\x{ff19}]+[".$this->pregCJKchars."]+)/u", mb_substr($word,$i,16,$this->mb_enc ))) {
22797 $cjkfix = 3;
22798 }
22799 if ($cjkfix) {
22800 //move lastchar(s) to next line
22801 $m0 = mb_substr($word,$i-1,1,$this->mb_enc ); // chars to move
22802 $m1 = mb_substr($word,0,$i-1,$this->mb_enc ); // str after stripped chars to move
22803 $mi = $i - 1;
22804 if ($cjkfix == 3) { $match = "0-9\x{ff10}-\x{ff19}"; }
22805 else { $match = $this->CJKleading; }
22806 while(preg_match("/[".$match."$]/u", $m1) && mb_strlen($m1, $this->mb_enc)>2) {
22807 $m0 = mb_substr($m1,$mi-1,1,$this->mb_enc ).$m0; // chars to move
22808 $m1 = mb_substr($m1,0,$mi-1,$this->mb_enc ); // str after stripped chars to move
22809 $mi--;
22810 }
22811 // Insert $m0 into $word at $i
22812 $word = mb_substr($word,0,$i,$this->mb_enc ) . $m0 . mb_substr($word,$i,mb_strlen($word, $this->mb_enc )-$i,$this->mb_enc );
22813 $mlen = mb_strlen($word, $this->mb_enc ); // increment max for loop counter
22814 }
22815
22816
22817
22818 }
22819 /*-- END CJK-FONTS --*/
22820
22821 if ($text && $firstchunk) {
22822 // END OF LINE
22823 // Finalise & add lineheight
22824 $maxfontsize = max($maxfontsize,$this->FontSize);
22825 $fh = $this->_computeLineheight($this->table_lineheight);
22826 if ($lhfixed && $this->FontSize > $def_fontsize) {
22827 $fh = $this->FontSize;
22828 $forceExactLineheight = false;
22829 }
22830 $maxlineHeight = max($maxlineHeight,$fh);
22831 $ch += $this->finaliseCellLineHeight($lhxt, $maxfontsize, $maxlineHeight, $lhfixed, $forceExactLineheight);
22832 // START OF NEW LINE
22833 // Initialise lineheight variables
22834 $maxfontsize = $this->FontSize;
22835 $forceExactLineheight = true;
22836 $lhxt = array('BS'=>0, 'M'=>0, 'TT'=>0, 'TB'=>0, 'T'=>0, 'B'=>0);
22837 $maxlineHeight = $this->_computeLineheight($this->table_lineheight);
22838 $ln++;
22839 }
22840 // END OF LINE
22841 // Finalise & add lineheight
22842 $maxfontsize = max($maxfontsize,$this->FontSize);
22843 $fh = $this->_computeLineheight($this->table_lineheight);
22844 if ($lhfixed && $this->FontSize > $def_fontsize) {
22845 $fh = $this->FontSize;
22846 $forceExactLineheight = false;
22847 }
22848 $maxlineHeight = max($maxlineHeight,$fh);
22849 $ch += $this->finaliseCellLineHeight($lhxt, $maxfontsize, $maxlineHeight, $lhfixed, $forceExactLineheight);
22850 // START OF NEW LINE
22851 // Initialise lineheight variables
22852 $maxfontsize = $this->FontSize;
22853 $forceExactLineheight = true;
22854 $lhxt = array('BS'=>0, 'M'=>0, 'TT'=>0, 'TB'=>0, 'T'=>0, 'B'=>0);
22855 $maxlineHeight = $this->_computeLineheight($this->table_lineheight);
22856 $ln++;
22857 $mxw = $maxwidth;
22858 $text = mb_substr($word,0,$i,$this->mb_enc );
22859 $word = mb_substr($word,$i,mb_strlen($word, $this->mb_enc )-$i,$this->mb_enc );
22860 $wordwidth = $this->GetStringWidth($word);
22861 $width = 0;
22862 $firstchunk=false;
22863 break;
22864 }
22865 }
22866 if (mb_strlen($word, $this->mb_enc )<2 && $wordwidth > $maxwidth + 0.0001) {
22867 $wordwidth = $maxwidth - 0.0001;
22868 if ($this->debug) { $this->Error("Table cell width calculated less than that needed for single character!"); }
22869 }
22870 $firstchunk=false;
22871 }
22872 }
22873 // Word fits on line...
22874 if ($width + $wordwidth < $maxwidth + 0.0001) {
22875 $mxw = max($mxw, ($width+$wordwidth));
22876 $width += $wordwidth + $space;
22877 $text .= $word.' ';
22878 }
22879 // Word does not fit on line...
22880 else {
22881 // mPDF 5.6.21 hard hyphens
22882 if ($this->textparam['hyphens'] != 2 && preg_match('/\-/',$word)) {
22883 list($hardsuccess,$pre,$post,$prelength) = $this->hardHyphenate($word, ($maxwidth - $width)-$this->GetCharWidth("-", false));
22884 if ($hardsuccess) {
22885 $text .= $pre.'-';
22886 $word = $post;
22887 $wordwidth = $this->GetStringWidth($word);
22888 if ($k==(count($words)-1)) { $wordwidth += $rbw; }
22889 }
22890 }
22891 /*-- HYPHENATION --*/
22892 // Soft Hyphens chr(173)
22893 else if ($this->textparam['hyphens'] != 2 && (!$this->usingCoreFont && preg_match("/\xc2\xad/",$word)) || ($this->usingCoreFont && preg_match("/".chr(173)."/",$word) && ($this->FontFamily!='csymbol' && $this->FontFamily!='czapfdingbats')) ) { // mPDF 5.6.06 5.6.08
22894 list($success,$pre,$post,$prelength) = $this->softHyphenate($word, ($maxwidth - $width));
22895 if ($success) {
22896 $text .= $pre.'-';
22897 $word = $post;
22898 $wordwidth = $this->GetStringWidth($word);
22899 if ($k==(count($words)-1)) { $wordwidth += $rbw; }
22900 }
22901 }
22902 else if ($this->textparam['hyphens'] == 1) { // mPDF 5.6.06 5.6.08
22903 list($success,$pre,$post,$prelength) = $this->hyphenateWord($word, ($maxwidth - $width));
22904 if ($success) {
22905 $text .= $pre.'-';
22906 $word = $post;
22907 $wordwidth = $this->GetStringWidth($word);
22908 if ($k==(count($words)-1)) { $wordwidth += $rbw; }
22909 }
22910 }
22911 /*-- END HYPHENATION --*/
22912
22913
22914 // mPDF 5.6.22
22915 if ( count($textbuffer)>1 && $cctr > 0 && $k==0
22916 && (substr($textbuffer[$cctr][0],0,3) != "\xbb\xa4\xac")
22917 && (substr($textbuffer[$cctr-1][0],0,3) != "\xbb\xa4\xac")
22918 && substr($textbuffer[$cctr-1][0],-1,1) != ' '
22919 && substr($textbuffer[$cctr][0],0,1) != ' '
22920 ) {
22921 // Go back to find a space in a previous chunk of content
22922 $found = false;
22923 for ($ix=$cctr-1;$ix>=0;$ix--) {
22924 if (preg_match('/[ ]/',$textbuffer[$ix][0])) { $found = $ix; break; }
22925 }
22926 if ($found !== false) {
22927 $charpos = strrpos($textbuffer[$found][0],' ');
22928 // mPDF 5.6.24
22929 $a1 = $a2 = $textbuffer[$found];
22930 $a1[0] = "\n";
22931 $a2[0] = substr($textbuffer[$found][0], $charpos+1, strlen($textbuffer[$found][0])-$charpos);
22932 $textbuffer[$found][0] = substr($textbuffer[$found][0], 0, $charpos);
22933 array_insert($textbuffer, $a1, $found+1);
22934 array_insert($textbuffer, $a2, $found+2);
22935 // Initialise all variables
22936 $biggestword=0;
22937 $toonarrow=false;
22938 $lhfixed = false;
22939 if (preg_match('/([0-9.,]+)mm/',$this->table_lineheight)) { $lhfixed = true; }
22940 if ($lhfixed) { $def_lineheight = $this->_computeLineheight($this->table_lineheight, $def_fontsize);}
22941 else { $def_lineheight = 0; }
22942 $maxfontsize = 0;
22943 $forceExactLineheight = true;
22944 $lhxt = array('BS'=>0, 'M'=>0, 'TT'=>0, 'TB'=>0, 'T'=>0, 'B'=>0);
22945 $maxlineHeight = $def_lineheight ;
22946 $ch = 0;
22947 $width = 0;
22948 $ln = 1; // Counts line number
22949 $mxw = $this->GetCharWidth('W',false);
22950 $text = '';
22951
22952 $cctr = -1;
22953 break;
22954 }
22955 }
22956
22957 // END OF LINE
22958 // Finalise & add lineheight
22959 $maxfontsize = max($maxfontsize,$this->FontSize);
22960 $fh = $this->_computeLineheight($this->table_lineheight);
22961 if ($lhfixed && $this->FontSize > $def_fontsize) {
22962 $fh = $this->FontSize;
22963 $forceExactLineheight = false;
22964 }
22965 $maxlineHeight = max($maxlineHeight,$fh);
22966 $ch += $this->finaliseCellLineHeight($lhxt, $maxfontsize, $maxlineHeight, $lhfixed, $forceExactLineheight);
22967 $mxw = $maxwidth;
22968 // START OF NEW LINE
22969 // Initialise lineheight variables
22970 $maxfontsize = $this->FontSize;
22971 $forceExactLineheight = true;
22972 $lhxt = array('BS'=>0, 'M'=>0, 'TT'=>0, 'TB'=>0, 'T'=>0, 'B'=>0);
22973 $maxlineHeight = $this->_computeLineheight($this->table_lineheight);
22974 $ln++;
22975 $width = $wordwidth + $space;
22976 $text = $word.' ';
22977 }
22978 $maxfontsize = max($maxfontsize,$this->FontSize);
22979 $fh = $this->_computeLineheight($this->table_lineheight);
22980 if ($lhfixed && $this->FontSize > $def_fontsize) {
22981 $fh = $this->FontSize;
22982 $forceExactLineheight = false;
22983 }
22984 $maxlineHeight = max($maxlineHeight,$fh);
22985 }
22986
22987 // End of textbuffer chunk
22988 if (!$lsend) {
22989 $width -= $space;
22990 $text = rtrim($text);
22991 }
22992
22993 // RESET FONT SIZE/STYLE
22994 // RESETTING VALUES
22995 //Now we must deactivate what we have used
22996 if(isset($chunk[2]) and $chunk[2] != '') {
22997 $this->ResetStyles();
22998 }
22999 if(isset($chunk[4]) and $chunk[4] != '') {
23000 $this->SetFont($this->default_font,$this->FontStyle,0,false);
23001 }
23002 if(isset($chunk[11]) and $chunk[11] != '') {
23003 $this->SetFontSize($this->default_font_size,false);
23004 }
23005 $this->spanborddet = array();
23006 $this->kerning = false;
23007 $this->lSpacingCSS = '';
23008 $this->wSpacingCSS = '';
23009 $this->fixedlSpacing = false;
23010 $this->minwSpacing = 0;
23011 }
23012 // Finalise lineheight if something output on line and add
23013 if ($width) {
23014 $ch += $this->finaliseCellLineHeight($lhxt, $maxfontsize, $maxlineHeight, $lhfixed, $forceExactLineheight);
23015 }
23016 if ($returnarray) { return array($ch,$ln,$mxw); }
23017 else { return $ch; }
23018
23019 }
23020
23021
23022 function TableCheckMinWidth($maxwidth, $forcewrap = 0, $textbuffer) {
23023 $biggestword=0;
23024 $toonarrow=false;
23025 if ((count($textbuffer) == 0) or ((count($textbuffer) == 1) && ($textbuffer[0][0] == ''))) { return 0; }
23026
23027 foreach ($textbuffer as $chunk) {
23028
23029 $line = $chunk[0];
23030 // mPDF ITERATION
23031 if ($this->iterationCounter) $line = preg_replace('/{iteration ([a-zA-Z0-9_]+)}/','\\1', $line);
23032
23033 // IMAGES & FORM ELEMENTS
23034 if (substr($line,0,3) == "\xbb\xa4\xac") { //inline object - FORM element or IMAGE!
23035 $objattr = $this->_getObjAttr($line);
23036 if ($objattr['type']!='hr' && isset($objattr['width']) && ($objattr['width']/$this->shrin_k) > ($maxwidth + 0.0001) ) {
23037 if (($objattr['width']/$this->shrin_k) > $biggestword) { $biggestword = ($objattr['width']/$this->shrin_k); }
23038 $toonarrow=true;
23039 }
23040 continue;
23041 }
23042
23043 if ($line == "\n") {
23044 continue;
23045 }
23046 $line = trim($line );
23047 // SET FONT SIZE/STYLE from $chunk[n]
23048
23049 // FONTSIZE
23050 if(isset($chunk[11]) and $chunk[11] != '') {
23051 if ($this->shrin_k) {
23052 $this->SetFontSize($chunk[11]/$this->shrin_k,false);
23053 }
23054 else {
23055 $this->SetFontSize($chunk[11],false);
23056 }
23057 }
23058 // FONTFAMILY
23059 if(isset($chunk[4]) and $chunk[4] != '') { $font = $this->SetFont($chunk[4],$this->FontStyle,0,false); }
23060 // B I U
23061 if(isset($chunk[2]) and $chunk[2] != '') {
23062 $this->SetStyles($chunk[2]);
23063 }
23064
23065 $lbw = $rbw = 0; // Border widths
23066 if(isset($chunk[16]) && !empty($chunk[16])) { //Border
23067 $this->spanborddet = $chunk[16];
23068 $lbw = $this->spanborddet['L']['w'];
23069 $rbw = $this->spanborddet['R']['w'];
23070 }
23071 if(isset($chunk[15])) { // Word spacing
23072 $this->wSpacingCSS = $chunk[15];
23073 if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') {
23074 $this->minwSpacing = $this->ConvertSize($this->wSpacingCSS,$this->FontSize);
23075 }
23076 }
23077 if(isset($chunk[14])) { // Letter spacing
23078 $this->lSpacingCSS = $chunk[14];
23079 if (($this->lSpacingCSS || $this->lSpacingCSS==='0') && strtoupper($this->lSpacingCSS) != 'NORMAL') {
23080 $this->fixedlSpacing = $this->ConvertSize($this->lSpacingCSS,$this->FontSize);
23081 }
23082 }
23083 if(isset($chunk[13])) { // Font Kerning
23084 $this->kerning = $chunk[13];
23085 }
23086
23087 $words = explode(' ', $line);
23088 foreach ($words as $k=>$word) {
23089 $word = trim($word);
23090 $wordwidth = $this->GetStringWidth($word);
23091 if ($k==0) { $wordwidth += $lbw; }
23092 if ($k==(count($words)-1)) { $wordwidth += $rbw; }
23093
23094 //Warn user that maxwidth is insufficient
23095 if ($wordwidth > $maxwidth + 0.0001) {
23096 if ($wordwidth > $biggestword) { $biggestword = $wordwidth; }
23097 $toonarrow=true;
23098 }
23099 }
23100
23101 // RESET FONT SIZE/STYLE
23102 // RESETTING VALUES
23103 //Now we must deactivate what we have used
23104 if(isset($chunk[2]) and $chunk[2] != '') {
23105 $this->ResetStyles();
23106 }
23107 if(isset($chunk[4]) and $chunk[4] != '') {
23108 $this->SetFont($this->default_font,$this->FontStyle,0,false);
23109 }
23110 if(isset($chunk[11]) and $chunk[11] != '') {
23111 $this->SetFontSize($this->default_font_size,false);
23112 }
23113 $this->spanborddet = array();
23114 $this->kerning = false;
23115 $this->lSpacingCSS = '';
23116 $this->wSpacingCSS = '';
23117 $this->fixedlSpacing = false;
23118 $this->minwSpacing = 0;
23119 }
23120
23121 //Return -(wordsize) if word is bigger than maxwidth
23122 // ADDED
23123 if (($toonarrow) && ($this->table_error_report)) {
23124 $this->Error("Word is too long to fit in table - ".$this->table_error_report_param);
23125 }
23126 if ($toonarrow) return -$biggestword;
23127 else return 1;
23128 }
23129
23130 function shrinkTable(&$table,$k) {
23131 $table['border_spacing_H'] /= $k;
23132 $table['border_spacing_V'] /= $k;
23133
23134 $table['padding']['T'] /= $k;
23135 $table['padding']['R'] /= $k;
23136 $table['padding']['B'] /= $k;
23137 $table['padding']['L'] /= $k;
23138
23139 $table['margin']['T'] /= $k;
23140 $table['margin']['R'] /= $k;
23141 $table['margin']['B'] /= $k;
23142 $table['margin']['L'] /= $k;
23143
23144 $table['border_details']['T']['w'] /= $k;
23145 $table['border_details']['R']['w'] /= $k;
23146 $table['border_details']['B']['w'] /= $k;
23147 $table['border_details']['L']['w'] /= $k;
23148
23149 if (isset($table['max_cell_border_width']['T'])) $table['max_cell_border_width']['T'] /= $k;
23150 if (isset($table['max_cell_border_width']['R'])) $table['max_cell_border_width']['R'] /= $k;
23151 if (isset($table['max_cell_border_width']['B'])) $table['max_cell_border_width']['B'] /= $k;
23152 if (isset($table['max_cell_border_width']['L'])) $table['max_cell_border_width']['L'] /= $k;
23153
23154 if ($this->simpleTables){
23155 $table['simple']['border_details']['T']['w'] /= $k;
23156 $table['simple']['border_details']['R']['w'] /= $k;
23157 $table['simple']['border_details']['B']['w'] /= $k;
23158 $table['simple']['border_details']['L']['w'] /= $k;
23159 }
23160
23161 $table['miw'] /= $k;
23162 $table['maw'] /= $k;
23163
23164 if ($this->cacheTables) { $fh = fopen($table['cache'], "r+b"); }
23165
23166 for($j = 0 ; $j < $table['nc'] ; $j++ ) { //columns
23167
23168 $table['wc'][$j]['miw'] /= $k;
23169 $table['wc'][$j]['maw'] /= $k;
23170
23171 // mPDF 5.6.13
23172 if (isset($table['decimal_align'][$j]['maxs0']) && $table['decimal_align'][$j]['maxs0']) { $table['decimal_align'][$j]['maxs0'] /= $k; }
23173 if (isset($table['decimal_align'][$j]['maxs1']) && $table['decimal_align'][$j]['maxs1']) { $table['decimal_align'][$j]['maxs1'] /= $k; }
23174
23175 if (isset($table['wc'][$j]['absmiw']) && $table['wc'][$j]['absmiw'] ) $table['wc'][$j]['absmiw'] /= $k;
23176
23177 for($i = 0 ; $i < $table['nr']; $i++ ) { //rows
23178 if ($this->cacheTables) {
23179 $c = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
23180 }
23181 else
23182 $c = &$table['cells'][$i][$j];
23183 if (isset($c) && $c) {
23184 if (!$this->simpleTables){
23185 if ($this->packTableData) {
23186 $cell = $this->_unpackCellBorder($c['borderbin'] );
23187 $cell['border_details']['T']['w'] /= $k;
23188 $cell['border_details']['R']['w'] /= $k;
23189 $cell['border_details']['B']['w'] /= $k;
23190 $cell['border_details']['L']['w'] /= $k;
23191 $cell['border_details']['mbw']['TL'] /= $k;
23192 $cell['border_details']['mbw']['TR'] /= $k;
23193 $cell['border_details']['mbw']['BL'] /= $k;
23194 $cell['border_details']['mbw']['BR'] /= $k;
23195 $cell['border_details']['mbw']['LT'] /= $k;
23196 $cell['border_details']['mbw']['LB'] /= $k;
23197 $cell['border_details']['mbw']['RT'] /= $k;
23198 $cell['border_details']['mbw']['RB'] /= $k;
23199 $c['borderbin'] = $this->_packCellBorder($cell);
23200 }
23201 else {
23202 $c['border_details']['T']['w'] /= $k;
23203 $c['border_details']['R']['w'] /= $k;
23204 $c['border_details']['B']['w'] /= $k;
23205 $c['border_details']['L']['w'] /= $k;
23206 $c['border_details']['mbw']['TL'] /= $k;
23207 $c['border_details']['mbw']['TR'] /= $k;
23208 $c['border_details']['mbw']['BL'] /= $k;
23209 $c['border_details']['mbw']['BR'] /= $k;
23210 $c['border_details']['mbw']['LT'] /= $k;
23211 $c['border_details']['mbw']['LB'] /= $k;
23212 $c['border_details']['mbw']['RT'] /= $k;
23213 $c['border_details']['mbw']['RB'] /= $k;
23214 }
23215 }
23216 $c['padding']['T'] /= $k;
23217 $c['padding']['R'] /= $k;
23218 $c['padding']['B'] /= $k;
23219 $c['padding']['L'] /= $k;
23220 $c['maxs'] /= $k;
23221 if (isset($c['w'])) { $c['w'] /= $k; }
23222 $c['s'] /= $k;
23223 $c['maw'] /= $k;
23224 $c['miw'] /= $k;
23225 if (isset($c['absmiw'])) $c['absmiw'] /= $k;
23226 if (isset($c['nestedmaw'])) $c['nestedmaw'] /= $k;
23227 if (isset($c['nestedmiw'])) $c['nestedmiw'] /= $k;
23228 if (isset($c['textbuffer'])) {
23229 foreach($c['textbuffer'] AS $n=>$tb) {
23230 if (!empty($tb[16])) {
23231 $c['textbuffer'][$n][16]['T']['w'] /= $k;
23232 $c['textbuffer'][$n][16]['B']['w'] /= $k;
23233 $c['textbuffer'][$n][16]['L']['w'] /= $k;
23234 $c['textbuffer'][$n][16]['R']['w'] /= $k;
23235 }
23236 }
23237 }
23238 if ($this->cacheTables) {
23239 $this->_cacheCell($c, '', "W", $fh, $table['cells'][$i][$j]);
23240 }
23241 unset($c);
23242 }
23243 }//rows
23244 }//columns
23245 if ($this->cacheTables) { fclose($fh); }
23246 }
23247
23248 function _cacheCell($c, $file, $mode="A", $fh=null, $offset=0) { // mode = Append or (over)Write (needs offset and fh)
23249 // Requires either $file OR $fh (file_handle)
23250 if (!is_array($c) || !isset($c)) { return ''; }
23251
23252 if(isset($c['w'])) { $cw = $c['w']; } else { $cw = -1; }
23253 if(isset($c['w0'])) { $cw0 = $c['w0']; } else { $cw0 = -1; }
23254 if(isset($c['h0'])) { $ch0 = $c['h0']; } else { $ch0 = -1; }
23255
23256 $data = pack("n2d19A1A1n2sA32A128",
23257 $c['colspan'], /* n (16 bit; 2 bytes) [pos 0] */
23258 $c['rowspan'], /* n (16 bit; 2 bytes) [pos 2] */
23259 $c['s'], /* d NB machine-dependent size (64 bit; 8 bytes on test winOS) [pos 4] */
23260 $c['maxs'], /* d NB machine-dependent size [pos 4 + 1*D] */
23261 $c['nestedmaw'], /* d NB machine-dependent size [pos 4 + 2*D] */
23262 $c['nestedmiw'], /* d NB machine-dependent size [pos 4 + 3*D] */
23263 $c['padding']['L'], /* d NB machine-dependent size [pos 4 + 4*D] */
23264 $c['padding']['R'], /* d NB machine-dependent size [pos 4 + 5*D] */
23265 $c['padding']['T'], /* d NB machine-dependent size [pos 4 + 6*D] */
23266 $c['padding']['B'], /* d NB machine-dependent size [pos 4 + 7*D] */
23267 $c['dfs'], /* d NB machine-dependent size [pos 4 + 8*D] */
23268 $cw, /* d NB machine-dependent size [pos 4 + 9*D] */
23269 $c['h'], /* d NB machine-dependent size [pos 4 + 10*D] */
23270 $c['absmiw'], /* d NB machine-dependent size [pos 4 + 11*D] */
23271 $c['maw'], /* d NB machine-dependent size [pos 4 + 12*D] */
23272 $c['miw'], /* d NB machine-dependent size [pos 4 + 13*D] */
23273 $c['mih'], /* d NB machine-dependent size [pos 4 + 14*D] */
23274 $c['x0'], /* d NB machine-dependent size [pos 4 + 15*D] */
23275 $cw0, /* d NB machine-dependent size [pos 4 + 16*D] */
23276 $c['y0'], /* d NB machine-dependent size [pos 4 + 17*D] */
23277 $ch0, /* d NB machine-dependent size [pos 4 + 18*D] */
23278 $c['a'], /* A1 (1 byte) [pos 4 + 19*D] */
23279 $c['va'], /* A1 (1 byte) [pos 5 + 19*D] */
23280 $c['nowrap'], /* 1 or blank n (16 bit; 2 bytes) [pos 6 + 19*D] */
23281 $c['wpercent'], /* 0 - 100 n (16 bit; 2 bytes) [pos 8 + 19*D] */
23282 $c['R'], /* 90 or -90 s (16 bit; 2 bytes) [pos 10 + 19*D] */
23283 $c['bgcolor'], /* A32 (32 bytes) [pos 12 + 19*D] */
23284 $c['gradient'] /* A128 (128 bytes) [pos 44 + 19*D] */
23285 );
23286
23287 if ($c['background-image']) {
23288 $data .= pack("n2d2A6A6n3dA4A128",
23289 strlen($data), /* offset in main data to start of bgimage data */
23290 $c['background-image']['image_id'], /* n */
23291 $c['background-image']['orig_w'], /* d NB machine-dependent size */
23292 $c['background-image']['orig_h'], /* d NB machine-dependent size */
23293 $c['background-image']['x_pos'], /* A6 calc size or "50%" */
23294 $c['background-image']['y_pos'], /* A6 calc size or "50%" */
23295 $c['background-image']['x_repeat'], /* n true or false*/
23296 $c['background-image']['y_repeat'], /* n true or false */
23297 $c['background-image']['resize'], /* n 0 - 6 */
23298 $c['background-image']['opacity'], /* d 0-1 */
23299 $c['background-image']['itype'], /* A4 jpg etc */
23300 $c['background-image']['gradient'] /* A128 CSS string */
23301 );
23302 }
23303 else $data .= pack("n",0);
23304 $tb_offset = 2 + 186 + 2 + strlen($data);
23305 $stb = serialize($c['textbuffer']).' '; // buffer to allow updating in reverseTableDir
23306 $lentb = strlen($stb);
23307 $data2 = pack("nA".$lentb, $lentb, $stb);
23308
23309 $tempfh = true;
23310 if ($mode=="W" && $offset) {
23311 if (!$fh) { $fh = fopen($file, "r+b"); } // Overwrite (but not truncate)
23312 else $tempfh = false;
23313 fseek($fh, $offset);
23314 }
23315 else {
23316 $fh = fopen($file, "ab"); // APPEND
23317 }
23318 fwrite($fh, pack("n",$tb_offset)); // Offset to Text buffer 2 bytes
23319 fwrite($fh, $c['borderbin']); // border details 186 bytes
23320 fwrite($fh, pack("n",strlen($data))); // Length of Main data
23321 fwrite($fh, $data); // Main data
23322 fwrite($fh, $data2); // Text buffer (starts with "n" length of text buffer)
23323 if ($tempfh) fclose($fh);
23324 return ($tb_offset + 2 + $lentb);
23325 }
23326
23327 function _cacheUpdateTxB($c, $fh, $offset) {
23328 fseek($fh, $offset);
23329 $tb_offset = $this->read_short($fh); // First entry = Offset to Text buffer 2 bytes
23330 fseek($fh, ($tb_offset-2), SEEK_CUR);
23331 $lentb = $this->read_short($fh); // First entry in textbuffer = Length of serialized textbuffer - do not update
23332 $stb = serialize($c['textbuffer']);
23333 fwrite($fh, pack("A".$lentb, $stb));
23334 }
23335
23336 function _cacheUpdateBorder($c, $fh, $offset) {
23337 $offset += 2;
23338 fseek($fh, $offset);
23339 fwrite($fh, $c['borderbin']);
23340 }
23341
23342 function _cacheUpdateMtx($c, $fh, $offset, $var) {
23343 if ($var=='mih') { $offset += (2 + 186 + 2 + 4 + 14*_DSIZE); }
23344 else if ($var=='x0') { $offset += (2 + 186 + 2 + 4 + 15*_DSIZE); } // x0 and w0
23345 else if ($var=='y0') { $offset += (2 + 186 + 2 + 4 + 17*_DSIZE); } // y0 and h0
23346 fseek($fh, $offset);
23347 if ($var=='mih') { fwrite($fh, pack("d",$c['mih'])); }
23348 else if ($var=='x0') { fwrite($fh, pack("d2",$c['x0'],$c['w0'])); }
23349 else if ($var=='y0') { fwrite($fh, pack("d2",$c['y0'],$c['h0'])); }
23350 }
23351
23352 function _uncacheCell($ptr, $file, $fh) {
23353 // Requires either $file or $fh (file_handle)
23354 if ($ptr==0) { return null; }
23355 if (is_array($ptr)) { $this->Error("Probable cause - missing end tag &lt;/td&gt;. You may be able to change the configurable variable: allow_html_optional_endtags "); }
23356 $tempfh = true;
23357 if (!$fh) { $fh = fopen($file, "rb"); }
23358 else $tempfh = false;
23359 fseek($fh, $ptr);
23360 $c = array();
23361 $tb_offset = $this->read_short($fh); // First entry = Offset to Text buffer 2 bytes
23362 $c['borderbin'] = fread($fh,186); // border details 186 bytes
23363 $maindatalen = $this->read_short($fh); // Length of Main data (2 bytes)
23364 $str = fread($fh,$maindatalen ); // Main data
23365 $data = unpack("ncolspan/nrowspan/ds/dmaxs/dnmaw/dnmiw/dpl/dpr/dpt/dpb/ddfs/dw/dh/dabsmiw/dmaw/dmiw/dmih/dx0/dw0/dy0/dh0/A1a/A1va/nnowrap/nwpercent/sR/A32bgcol/A128grad/nbgimage", $str);
23366
23367 if ($data['colspan']>0) $c['colspan'] = $data['colspan']; /* n */
23368 if ($data['rowspan']>0) $c['rowspan'] = $data['rowspan']; /* n */
23369 $c['s'] = $data['s']; /* d NB machine-dependent size */
23370 $c['maxs'] = $data['maxs']; /* d NB machine-dependent size */
23371 if ($data['nmaw']>0) $c['nestedmaw'] = $data['nmaw']; /* d NB machine-dependent size */
23372 if ($data['nmiw']>0) $c['nestedmiw'] = $data['nmiw']; /* d NB machine-dependent size */
23373 $c['padding']['L'] = $data['pl']; /* d NB machine-dependent size */
23374 $c['padding']['R'] = $data['pr']; /* d NB machine-dependent size */
23375 $c['padding']['T'] = $data['pt']; /* d NB machine-dependent size */
23376 $c['padding']['B'] = $data['pb']; /* d NB machine-dependent size */
23377 $c['dfs'] = $data['dfs']; /* d NB machine-dependent size */
23378 if ($data['w']>=0) $c['w'] = $data['w']; /* d NB machine-dependent size */
23379 if ($data['h']>0) $c['h'] = $data['h']; /* d NB machine-dependent size */
23380 if ($data['absmiw']>0) $c['absmiw'] = $data['absmiw']; /* d NB machine-dependent size */
23381 if ($data['maw']>0) $c['maw'] = $data['maw']; /* d NB machine-dependent size */
23382 if ($data['miw']>0) $c['miw'] = $data['miw']; /* d NB machine-dependent size */
23383 if ($data['mih']>0) $c['mih'] = $data['mih']; /* d NB machine-dependent size */
23384 if ($data['w0']>=0) { $c['w0'] = $data['w0']; /* d NB machine-dependent size */
23385 $c['x0'] = $data['x0']; } /* d NB machine-dependent size */
23386 if ($data['h0']>=0) { $c['h0'] = $data['h0']; /* d NB machine-dependent size */
23387 $c['y0'] = $data['y0']; } /* d NB machine-dependent size */
23388 $c['a'] = trim($data['a']); /* A1 */
23389 $c['va'] = trim($data['va']); /* A1 */
23390 if ($data['nowrap']) $c['nowrap'] = $data['nowrap']; /* 1 or blank n */
23391 else $c['nowrap'] = false;
23392 if ($data['wpercent']>0) $c['wpercent'] = $data['wpercent']; /* 0 - 100 n */
23393 if ($data['R']<>0) $c['R'] = $data['R']; /* 90 or -90 s */
23394 else $c['R'] = false;
23395 $c['bgcolor'] = trim($data['bgcol']); /* A32 */
23396 if (trim($data['grad']))
23397 $c['gradient'] = trim($data['grad']); /* A128 */
23398 else $c['gradient'] = false;
23399 if ($data['bgimage']>0) {
23400 $bgidata = substr($str, ($data['bgimage']+2));
23401 $c['background-image'] = unpack("nimage_id/dorig_w/dorig_h/A6x_pos/A6y_pos/nx_repeat/ny_repeat/nresize/dopacity/A4itype/A128gradient", $bgidata);
23402 }
23403
23404 $tblen = $this->read_short($fh); // Length of Textbuffer
23405 $tbsp = fread($fh,$tblen); // Textbuffer (serialised and packed)
23406 $tbs = unpack("A".$tblen."textbuffer",$tbsp); // Textbuffer unpacked
23407 $c['textbuffer'] = unserialize(trim($tbs['textbuffer'])); // Textbuffer unserialized
23408
23409 if ($tempfh) { fclose($fh); }
23410 return ($c);
23411 }
23412 function read_short(&$fh) {
23413 $s = fread($fh,2);
23414 $a = (ord($s[0])<<8) + ord($s[1]);
23415 if ($a & (1 << 15) ) {
23416 $a = ($a - (1 << 16));
23417 }
23418 return $a;
23419 }
23420 function _backupCacheFiles() {
23421 foreach($this->table AS $lvl=>$t) {
23422 foreach($this->table[$lvl] AS $c=>$t2) {
23423 ///////////////////////////if (!file_exists($t2['cache'])) { echo $lvl; echo $c; print_r($this->table); exit; }
23424 copy( $t2['cache'], $t2['cache'].'.bak');
23425 }
23426 }
23427 }
23428 function _restoreCacheFiles() {
23429 foreach($this->table AS $lvl=>$t) {
23430 foreach($this->table[$lvl] AS $c=>$t2) {
23431 copy( $t2['cache'].'.bak', $t2['cache']);
23432 }
23433 }
23434 }
23435
23436
23437 function _packCellBorder($cell) {
23438 if (!is_array($cell) || !isset($cell)) { return ''; }
23439
23440 if (!$this->packTableData) { return $cell; }
23441 // = 186 bytes
23442 $bindata = pack("nnda6A10nnda6A10nnda6A10nnda6A10nd9",
23443 $cell['border'],
23444 $cell['border_details']['R']['s'],
23445 $cell['border_details']['R']['w'],
23446 $cell['border_details']['R']['c'],
23447 $cell['border_details']['R']['style'],
23448 $cell['border_details']['R']['dom'],
23449
23450 $cell['border_details']['L']['s'],
23451 $cell['border_details']['L']['w'],
23452 $cell['border_details']['L']['c'],
23453 $cell['border_details']['L']['style'],
23454 $cell['border_details']['L']['dom'],
23455
23456 $cell['border_details']['T']['s'],
23457 $cell['border_details']['T']['w'],
23458 $cell['border_details']['T']['c'],
23459 $cell['border_details']['T']['style'],
23460 $cell['border_details']['T']['dom'],
23461
23462 $cell['border_details']['B']['s'],
23463 $cell['border_details']['B']['w'],
23464 $cell['border_details']['B']['c'],
23465 $cell['border_details']['B']['style'],
23466 $cell['border_details']['B']['dom'],
23467
23468 $cell['border_details']['mbw']['BL'],
23469 $cell['border_details']['mbw']['BR'],
23470 $cell['border_details']['mbw']['RT'],
23471 $cell['border_details']['mbw']['RB'],
23472 $cell['border_details']['mbw']['TL'],
23473 $cell['border_details']['mbw']['TR'],
23474 $cell['border_details']['mbw']['LT'],
23475 $cell['border_details']['mbw']['LB'],
23476
23477 $cell['border_details']['cellposdom']
23478 );
23479 return $bindata;
23480 }
23481
23482
23483
23484 function _getBorderWidths($bindata) {
23485 if (!$bindata) { return array(0,0,0,0); }
23486 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']); }
23487
23488 $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);
23489 $cell['border_details']['R']['w'] = $bd['rw'];
23490 $cell['border_details']['L']['w'] = $bd['lw'];
23491 $cell['border_details']['T']['w'] = $bd['tw'];
23492 $cell['border_details']['B']['w'] = $bd['bw'];
23493 return array($bd['tw'], $bd['rw'], $bd['bw'], $bd['lw']);
23494 }
23495
23496
23497 function _unpackCellBorder($bindata) {
23498 if (!$bindata) { return array(); }
23499 if (!$this->packTableData) { return $bindata; }
23500
23501 $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);
23502
23503 $cell['border'] = $bd['bord'];
23504 $cell['border_details']['R']['s'] = $bd['rs'];
23505 $cell['border_details']['R']['w'] = $bd['rw'];
23506 $cell['border_details']['R']['c'] = $bd['rca'];
23507 $cell['border_details']['R']['style'] = trim($bd['rst']);
23508 $cell['border_details']['R']['dom'] = $bd['rd'];
23509
23510 $cell['border_details']['L']['s'] = $bd['ls'];
23511 $cell['border_details']['L']['w'] = $bd['lw'];
23512 $cell['border_details']['L']['c'] = $bd['lca'];
23513 $cell['border_details']['L']['style'] = trim($bd['lst']);
23514 $cell['border_details']['L']['dom'] = $bd['ld'];
23515
23516 $cell['border_details']['T']['s'] = $bd['ts'];
23517 $cell['border_details']['T']['w'] = $bd['tw'];
23518 $cell['border_details']['T']['c'] = $bd['tca'];
23519 $cell['border_details']['T']['style'] = trim($bd['tst']);
23520 $cell['border_details']['T']['dom'] = $bd['td'];
23521
23522 $cell['border_details']['B']['s'] = $bd['bs'];
23523 $cell['border_details']['B']['w'] = $bd['bw'];
23524 $cell['border_details']['B']['c'] = $bd['bca'];
23525 $cell['border_details']['B']['style'] = trim($bd['bst']);
23526 $cell['border_details']['B']['dom'] = $bd['bd'];
23527
23528 $cell['border_details']['mbw']['BL'] = $bd['mbl'];
23529 $cell['border_details']['mbw']['BR'] = $bd['mbr'];
23530 $cell['border_details']['mbw']['RT'] = $bd['mrt'];
23531 $cell['border_details']['mbw']['RB'] = $bd['mrb'];
23532 $cell['border_details']['mbw']['TL'] = $bd['mtl'];
23533 $cell['border_details']['mbw']['TR'] = $bd['mtr'];
23534 $cell['border_details']['mbw']['LT'] = $bd['mlt'];
23535 $cell['border_details']['mbw']['LB'] = $bd['mlb'];
23536 $cell['border_details']['cellposdom'] = $bd['cpd'];
23537
23538 return($cell);
23539 }
23540
23541
23542 ////////////////////////TABLE CODE (from PDFTable)/////////////////////////////////////
23543 ////////////////////////TABLE CODE (from PDFTable)/////////////////////////////////////
23544 ////////////////////////TABLE CODE (from PDFTable)/////////////////////////////////////
23545 //table Array of (w, h, bc, nr, wc, hr, cells)
23546 //w Width of table
23547 //h Height of table
23548 //nc Number column
23549 //nr Number row
23550 //hr List of height of each row
23551 //wc List of width of each column
23552 //cells List of cells of each rows, cells[i][j] is a cell in the table
23553 function _tableColumnWidth(&$table,$firstpass=false){
23554 $cs = &$table['cells'];
23555
23556 $nc = $table['nc'];
23557 $nr = $table['nr'];
23558 $listspan = array();
23559
23560 if ($table['borders_separate']) {
23561 $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'];
23562 }
23563 else { $tblbw = $table['max_cell_border_width']['L']/2 + $table['max_cell_border_width']['R']/2 + $table['margin']['L'] + $table['margin']['R']; }
23564
23565 if ($this->cacheTables) { $fh = fopen($table['cache'], "r+b"); }
23566 else { $fh = null; }
23567
23568 // ADDED table['l'][colno]
23569 // = total length of text approx (using $c['s']) in that column - used to approximately distribute col widths in _tableWidth
23570 //
23571 for($j = 0 ; $j < $nc ; $j++ ) { //columns
23572 $wc = &$table['wc'][$j];
23573 for($i = 0 ; $i < $nr ; $i++ ) { //rows
23574 if (isset($cs[$i][$j]) && $cs[$i][$j]) {
23575 if ($this->cacheTables) {
23576 $c = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
23577 }
23578 else
23579 $c = &$cs[$i][$j];
23580
23581 if ($this->simpleTables){
23582 if ($table['borders_separate']) { // NB twice border width
23583 $extrcw = $table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w'] + $c['padding']['L'] + $c['padding']['R'] + $table['border_spacing_H'];
23584 }
23585 else {
23586 $extrcw = $table['simple']['border_details']['L']['w']/2 + $table['simple']['border_details']['R']['w']/2 + $c['padding']['L'] + $c['padding']['R'];
23587 }
23588 }
23589 else {
23590 if ($this->packTableData) {
23591 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
23592 }
23593 else {
23594 $br = $c['border_details']['R']['w'];
23595 $bl = $c['border_details']['L']['w'];
23596 }
23597 if ($table['borders_separate']) { // NB twice border width
23598 $extrcw = $bl + $br + $c['padding']['L'] + $c['padding']['R'] + $table['border_spacing_H'];
23599 }
23600 else {
23601 $extrcw = $bl/2 + $br/2 + $c['padding']['L'] + $c['padding']['R'];
23602 }
23603 }
23604
23605 //$mw = $this->GetStringWidth('W') + $extrcw ;
23606 $mw = 0;
23607 // mPDF 5.6.13 Decimal point alignment
23608 if(substr($c['a'],0,1) == 'D') {
23609 $mw = $table['decimal_align'][$j]['maxs0'] + $table['decimal_align'][$j]['maxs1'] + $extrcw ;
23610 }
23611
23612 $c['absmiw'] = $mw;
23613
23614 if (isset($c['R']) && $c['R']) {
23615 $c['maw'] = $c['miw'] = $this->FontSize + $extrcw ;
23616 if (isset($c['w'])) { // If cell width is specified
23617 if ($c['miw'] <$c['w']) { $c['miw'] = $c['w']; }
23618 }
23619 if (!isset($c['colspan'])) {
23620 if ($wc['miw'] < $c['miw']) { $wc['miw'] = $c['miw']; }
23621 if ($wc['maw'] < $c['maw']) { $wc['maw'] = $c['maw']; }
23622
23623 if ($firstpass) {
23624 if (isset($table['l'][$j]) ) {
23625 $table['l'][$j] += $c['miw'] ;
23626 }
23627 else {
23628 $table['l'][$j] = $c['miw'] ;
23629 }
23630 }
23631 }
23632 if ($c['miw'] > $wc['miw']) { $wc['miw'] = $c['miw']; }
23633 if ($wc['miw'] > $wc['maw']) { $wc['maw'] = $wc['miw']; }
23634 continue;
23635 }
23636
23637 if ($firstpass) {
23638 if (isset($c['s'])) { $c['s'] += $extrcw; }
23639 if (isset($c['maxs'])) { $c['maxs'] += $extrcw; }
23640 if (isset($c['nestedmiw'])) { $c['nestedmiw'] += $extrcw; }
23641 if (isset($c['nestedmaw'])) { $c['nestedmaw'] += $extrcw; }
23642 }
23643
23644
23645 // If minimum width has already been set by a nested table or inline object (image/form), use it
23646 if (isset($c['nestedmiw']) && $this->table[1][1]['overflow']!='visible') { $miw = $c['nestedmiw']; }
23647 else { $miw = $mw; }
23648
23649 if (isset($c['maxs']) && $c['maxs'] != '') { $c['s'] = $c['maxs']; }
23650
23651 // If maximum width has already been set by a nested table, use it
23652 if (isset($c['nestedmaw'])) { $c['maw'] = $c['nestedmaw']; }
23653 else $c['maw'] = $c['s'];
23654
23655 if (isset($table['overflow']) && $table['overflow']=='visible' && $table['level']==1) {
23656 if (($c['maw'] + $tblbw) > $this->blk[$this->blklvl]['inner_width']) {
23657 $c['maw'] = $this->blk[$this->blklvl]['inner_width'] - $tblbw;
23658 }
23659 }
23660
23661 if (isset($c['nowrap']) && $c['nowrap']) { $miw = $c['maw']; }
23662
23663 if (isset($c['wpercent']) && $firstpass) {
23664 if (isset($c['colspan'])) { // Not perfect - but % set on colspan is shared equally on cols.
23665 for($k=0;$k<$c['colspan'];$k++) {
23666 $table['wc'][($j+$k)]['wpercent'] = $c['wpercent'] / $c['colspan'];
23667 }
23668 }
23669 else {
23670 if (isset($table['w']) && $table['w']) { $c['w'] = $c['wpercent']/100 * ($table['w'] - $tblbw ); }
23671 $wc['wpercent'] = $c['wpercent'];
23672 }
23673 }
23674
23675 if (isset($table['overflow']) && $table['overflow']=='visible' && $table['level']==1) {
23676 if (($c['w'] + $tblbw) > $this->blk[$this->blklvl]['inner_width']) {
23677 $c['w'] = $this->blk[$this->blklvl]['inner_width'] - $tblbw;
23678 }
23679 }
23680
23681
23682 if (isset($c['w'])) { // If cell width is specified
23683 if ($miw<$c['w']) { $c['miw'] = $c['w']; } // Cell min width = that specified
23684 if ($miw>$c['w']) { $c['miw'] = $c['w'] = $miw; } // If width specified is less than minimum allowed (W) increase it
23685 if (!isset($wc['w'])) { $wc['w'] = 1; } // If the Col width is not specified = set it to 1
23686
23687 }
23688 else { $c['miw'] = $miw; } // If cell width not specified -> set Cell min width it to minimum allowed (W)
23689
23690 if ($c['maw'] < $c['miw']) { $c['maw'] = $c['miw']; } // If Cell max width < Minwidth - increase it to =
23691 if (!isset($c['colspan'])) {
23692 if ($wc['miw'] < $c['miw']) { $wc['miw'] = $c['miw']; } // Update Col Minimum and maximum widths
23693 if ($wc['maw'] < $c['maw']) { $wc['maw'] = $c['maw']; }
23694 if ((isset($wc['absmiw']) && $wc['absmiw'] < $c['absmiw']) || !isset($wc['absmiw'])) { $wc['absmiw'] = $c['absmiw']; } // Update Col Minimum and maximum widths
23695
23696 if (isset($table['l'][$j]) ) {
23697 $table['l'][$j] += $c['s'];
23698 }
23699 else {
23700 $table['l'][$j] = $c['s'];
23701 }
23702
23703 }
23704 else {
23705 $listspan[] = array($i,$j);
23706 }
23707
23708 //Check if minimum width of the whole column is big enough for largest word to fit
23709 if (isset($c['textbuffer']) && (!isset($table['overflow']) || $table['overflow']!='wrap')) { // mPDF 5.5.11
23710 $minwidth = $this->TableCheckMinWidth($wc['miw']- $extrcw ,0,$c['textbuffer']);
23711 }
23712 else { $minwidth = 0; }
23713 if ($minwidth < 0) {
23714 //increase minimum width
23715 if (!isset($c['colspan'])) {
23716 $wc['miw'] = max($wc['miw'],((-$minwidth) + $extrcw) );
23717 }
23718 else {
23719 $c['miw'] = max($c['miw'],((-$minwidth) + $extrcw) );
23720 }
23721 }
23722 if (!isset($c['colspan'])) {
23723 if ($wc['miw'] > $wc['maw']) { $wc['maw'] = $wc['miw']; } //update maximum width, if needed
23724 }
23725 if ($this->cacheTables) {
23726 $this->_cacheCell($c, '', "W", $fh, $table['cells'][$i][$j]);
23727 }
23728 }
23729 unset($c);
23730 }//rows
23731 }//columns
23732
23733
23734 // COLUMN SPANS
23735 $wc = &$table['wc'];
23736 foreach ($listspan as $span) {
23737 list($i,$j) = $span;
23738 if ($this->cacheTables) {
23739 $c = $this->_uncacheCell($cs[$i][$j], '', $fh);
23740 }
23741 else
23742 $c = &$cs[$i][$j];
23743 $lc = $j + $c['colspan'];
23744 if ($lc > $nc) { $lc = $nc; }
23745 $wis = $wisa = 0;
23746 $was = $wasa = 0;
23747 $list = array();
23748 for($k=$j;$k<$lc;$k++) {
23749 if (isset($table['l'][$k]) ) {
23750 if ($c['R']) { $table['l'][$k] += $c['miw']/$c['colspan'] ; }
23751 else { $table['l'][$k] += $c['s']/$c['colspan']; }
23752 }
23753 else {
23754 if ($c['R']) { $table['l'][$k] = $c['miw']/$c['colspan'] ; }
23755 else { $table['l'][$k] = $c['s']/$c['colspan']; }
23756 }
23757 $wis += $wc[$k]['miw'];
23758 $was += $wc[$k]['maw'];
23759 if (!isset($c['w'])) {
23760 $list[] = $k;
23761 $wisa += $wc[$k]['miw'];
23762 $wasa += $wc[$k]['maw'];
23763 }
23764 }
23765 if ($c['miw'] > $wis) {
23766 if (!$wis) {
23767 for($k=$j;$k<$lc;$k++) { $wc[$k]['miw'] = $c['miw']/$c['colspan']; }
23768 }
23769 else if (!count($list)) {
23770 $wi = $c['miw'] - $wis;
23771 for($k=$j;$k<$lc;$k++) { $wc[$k]['miw'] += ($wc[$k]['miw']/$wis)*$wi; }
23772 }
23773 else {
23774 $wi = $c['miw'] - $wis;
23775 foreach ($list as $k) { $wc[$k]['miw'] += ($wc[$k]['miw']/$wisa)*$wi; }
23776 }
23777 }
23778 if ($c['maw'] > $was) {
23779 if (!$wis) {
23780 for($k=$j;$k<$lc;$k++) { $wc[$k]['maw'] = $c['maw']/$c['colspan']; }
23781 }
23782 else if (!count($list)) {
23783 $wi = $c['maw'] - $was;
23784 for($k=$j;$k<$lc;$k++) { $wc[$k]['maw'] += ($wc[$k]['maw']/$was)*$wi; }
23785 }
23786 else {
23787 $wi = $c['maw'] - $was;
23788 foreach ($list as $k) { $wc[$k]['maw'] += ($wc[$k]['maw']/$wasa)*$wi; }
23789 }
23790 }
23791 unset($c);
23792 }
23793
23794 if ($this->cacheTables) { fclose($fh); }
23795
23796 $checkminwidth = 0;
23797 $checkmaxwidth = 0;
23798 $totallength = 0;
23799
23800 for( $i = 0 ; $i < $nc ; $i++ ) {
23801 $checkminwidth += $table['wc'][$i]['miw'];
23802 $checkmaxwidth += $table['wc'][$i]['maw'];
23803 $totallength += $table['l'][$i];
23804 }
23805
23806 if (!isset($table['w']) && $firstpass) {
23807 $sumpc = 0;
23808 $notset = 0;
23809 for( $i = 0 ; $i < $nc ; $i++ ) {
23810 if (isset($table['wc'][$i]['wpercent']) && $table['wc'][$i]['wpercent']) {
23811 $sumpc += $table['wc'][$i]['wpercent'];
23812 }
23813 else { $notset++; }
23814 }
23815
23816 // If sum of widths as % >= 100% and not all columns are set
23817 // Set a nominal width of 1% for unset columns
23818 if ($sumpc >= 100 && $notset) {
23819 for( $i = 0 ; $i < $nc ; $i++ ) {
23820 if ((!isset($table['wc'][$i]['wpercent']) || !$table['wc'][$i]['wpercent']) &&
23821 (!isset($table['wc'][$i]['w']) || !$table['wc'][$i]['w'])) {
23822 $table['wc'][$i]['wpercent'] = 1;
23823 }
23824 }
23825 }
23826
23827
23828 if ($sumpc) { // if any percents are set
23829 $sumnonpc = (100 - $sumpc);
23830 $sumpc = max($sumpc,100);
23831 $miwleft = 0;
23832 $miwleftcount = 0;
23833 $miwsurplusnonpc = 0;
23834 $maxcalcmiw = 0;
23835 $mawleft = 0;
23836 $mawleftcount = 0;
23837 $mawsurplusnonpc = 0;
23838 $maxcalcmaw = 0;
23839 for( $i = 0 ; $i < $nc ; $i++ ) {
23840 if (isset($table['wc'][$i]['wpercent'])) {
23841 $maxcalcmiw = max($maxcalcmiw, ($table['wc'][$i]['miw'] * $sumpc /$table['wc'][$i]['wpercent']) );
23842 $maxcalcmaw = max($maxcalcmaw, ($table['wc'][$i]['maw'] * $sumpc /$table['wc'][$i]['wpercent']) );
23843 }
23844 else {
23845 $miwleft += $table['wc'][$i]['miw'];
23846 $mawleft += $table['wc'][$i]['maw'];
23847 if (!isset($table['wc'][$i]['w'])) { $miwleftcount++; $mawleftcount++; }
23848 }
23849 }
23850 if ($miwleft && $sumnonpc > 0) { $miwnon = $miwleft * 100 / $sumnonpc; }
23851 if ($mawleft && $sumnonpc > 0) { $mawnon = $mawleft * 100 / $sumnonpc; }
23852 if (($miwnon > $checkminwidth || $maxcalcmiw > $checkminwidth) && $this->keep_table_proportions) {
23853 if ($miwnon > $maxcalcmiw) {
23854 $miwsurplusnonpc = round((($miwnon * $sumnonpc / 100) - $miwleft),3);
23855 $checkminwidth = $miwnon;
23856 }
23857 else { $checkminwidth = $maxcalcmiw; }
23858 for( $i = 0 ; $i < $nc ; $i++ ) {
23859 if (isset($table['wc'][$i]['wpercent'])) {
23860 $newmiw = $checkminwidth * $table['wc'][$i]['wpercent']/100;
23861 if ($table['wc'][$i]['miw'] < $newmiw) {
23862 $table['wc'][$i]['miw'] = $newmiw;
23863 }
23864 $table['wc'][$i]['w'] = 1;
23865 }
23866 else if ($miwsurplusnonpc && !$table['wc'][$i]['w']) {
23867 $table['wc'][$i]['miw'] += $miwsurplusnonpc / $miwleftcount;
23868 }
23869 }
23870 }
23871 if (($mawnon > $checkmaxwidth || $maxcalcmaw > $checkmaxwidth )) {
23872 if ($mawnon > $maxcalcmaw) {
23873 $mawsurplusnonpc = round((($mawnon * $sumnonpc / 100) - $mawleft),3);
23874 $checkmaxwidth = $mawnon;
23875 }
23876 else { $checkmaxwidth = $maxcalcmaw; }
23877 for( $i = 0 ; $i < $nc ; $i++ ) {
23878 if (isset($table['wc'][$i]['wpercent'])) {
23879 $newmaw = $checkmaxwidth * $table['wc'][$i]['wpercent']/100;
23880 if ($table['wc'][$i]['maw'] < $newmaw) {
23881 $table['wc'][$i]['maw'] = $newmaw;
23882 }
23883 $table['wc'][$i]['w'] = 1;
23884 }
23885 else if ($mawsurplusnonpc && !$table['wc'][$i]['w']) {
23886 $table['wc'][$i]['maw'] += $mawsurplusnonpc / $mawleftcount;
23887 }
23888 if ($table['wc'][$i]['maw'] < $table['wc'][$i]['miw']) { $table['wc'][$i]['maw'] = $table['wc'][$i]['miw']; }
23889 }
23890 }
23891 if ($checkminwidth > $checkmaxwidth) { $checkmaxwidth = $checkminwidth; }
23892 }
23893 }
23894
23895 if (isset($table['wpercent']) && $table['wpercent']) {
23896 $checkminwidth *= (100 / $table['wpercent']);
23897 $checkmaxwidth *= (100 / $table['wpercent']);
23898 }
23899
23900
23901 $checkminwidth += $tblbw ;
23902 $checkmaxwidth += $tblbw ;
23903
23904 // Table['miw'] set by percent in first pass may be larger than sum of column miw
23905 if ((isset($table['miw']) && $checkminwidth > $table['miw']) || !isset($table['miw'])) { $table['miw'] = $checkminwidth; }
23906 if ((isset($table['maw']) && $checkmaxwidth > $table['maw']) || !isset($table['maw'])) { $table['maw'] = $checkmaxwidth; }
23907 $table['tl'] = $totallength ;
23908
23909
23910 if (!$this->tableCJK) {
23911 if ($this->table_rotate) {
23912 $mxw = $this->tbrot_maxw;
23913 }
23914 else {
23915 $mxw = $this->blk[$this->blklvl]['inner_width'];
23916 }
23917 if(!isset($table['overflow'])) { $table['overflow'] = null; }
23918 if ($table['overflow']=='visible') {
23919 return array(0,0);
23920 }
23921 else if ($table['overflow']=='hidden' && !$this->table_rotate && !$this->ColActive && $checkminwidth > $mxw) {
23922 $table['w'] = $table['miw'];
23923 return array(0,0);
23924 }
23925 else if ($table['overflow']=='wrap') { return array(0,0); }
23926
23927 if (isset($table['w']) && $table['w'] ) {
23928 if ($table['w'] >= $checkminwidth && $table['w'] <= $mxw) { $table['maw'] = $mxw = $table['w']; }
23929 else if ($table['w'] >= $checkminwidth && $table['w'] > $mxw && $this->keep_table_proportions) { $checkminwidth = $table['w']; }
23930 else {
23931 unset($table['w']);
23932 }
23933 }
23934 $ratio = $checkminwidth/$mxw;
23935 if ($checkminwidth > $mxw) { return array(($ratio +0.001),$checkminwidth); } // 0.001 to allow for rounded numbers when resizing
23936 }
23937 unset($cs);
23938 return array(0,0);
23939 }
23940
23941
23942
23943 function _tableWidth(&$table){
23944 $widthcols = &$table['wc'];
23945 $numcols = $table['nc'];
23946 $tablewidth = 0;
23947 if ($table['borders_separate']) {
23948 $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'];
23949 }
23950 else { $tblbw = $table['max_cell_border_width']['L']/2 + $table['max_cell_border_width']['R']/2 + $table['margin']['L'] + $table['margin']['R']; }
23951
23952 if ($table['level']>1 && isset($table['w'])) {
23953 if (isset($table['wpercent']) && $table['wpercent']) {
23954 $table['w'] = $temppgwidth = (($table['w']-$tblbw) * $table['wpercent'] / 100) + $tblbw ;
23955 }
23956 else {
23957 $temppgwidth = $table['w'] ;
23958 }
23959 }
23960 else if ($this->table_rotate) {
23961 $temppgwidth = $this->tbrot_maxw;
23962 // If it is less than 1/20th of the remaining page height to finish the DIV (i.e. DIV padding + table bottom margin)
23963 // then allow for this
23964 $enddiv = $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'];
23965 if ($enddiv/$temppgwidth <0.05) { $temppgwidth -= $enddiv; }
23966 }
23967 else {
23968 if (isset($table['w']) && $table['w']< $this->blk[$this->blklvl]['inner_width']) {
23969 $notfullwidth = 1;
23970 $temppgwidth = $table['w'] ;
23971 }
23972 else if ($table['overflow']=='visible' && $table['level'] ==1) {
23973 $temppgwidth = null;
23974 }
23975 else if ($table['overflow']=='hidden' && !$this->ColActive && isset($table['w']) && $table['w'] > $this->blk[$this->blklvl]['inner_width'] && $table['w']==$table['miw']) {
23976 //$temppgwidth = $this->blk[$this->blklvl]['inner_width'];
23977 $temppgwidth = $table['w'] ;
23978 }
23979 else { $temppgwidth = $this->blk[$this->blklvl]['inner_width']; }
23980 }
23981
23982
23983 $totaltextlength = 0; // Added - to sum $table['l'][colno]
23984 $totalatextlength = 0; // Added - to sum $table['l'][colno] for those columns where width not set
23985 $percentages_set = 0;
23986 for ( $i = 0 ; $i < $numcols ; $i++ ) {
23987 if (isset($widthcols[$i]['wpercent'])) { $tablewidth += $widthcols[$i]['maw']; $percentages_set = 1; }
23988 else if (isset($widthcols[$i]['w'])) { $tablewidth += $widthcols[$i]['miw']; }
23989 else { $tablewidth += $widthcols[$i]['maw']; }
23990 $totaltextlength += $table['l'][$i];
23991 }
23992 if (!$totaltextlength) { $totaltextlength =1; }
23993 $tablewidth += $tblbw; // Outer half of table borders
23994
23995 if ($tablewidth > $temppgwidth) {
23996 $table['w'] = $temppgwidth;
23997 }
23998 // if any widths set as percentages and max width fits < page width
23999 else if ($tablewidth < $temppgwidth && !isset($table['w']) && $percentages_set) {
24000 $table['w'] = $table['maw'];
24001 }
24002 // if table width is set and is > allowed width
24003 if (isset($table['w']) && $table['w'] > $temppgwidth) { $table['w'] = $temppgwidth; }
24004 // IF the table width is now set - Need to distribute columns widths
24005 if (isset($table['w'])) {
24006 $wis = $wisa = 0;
24007 $list = array();
24008 $notsetlist = array();
24009 for( $i = 0 ; $i < $numcols ; $i++ ) {
24010 $wis += $widthcols[$i]['miw'];
24011 if (!isset($widthcols[$i]['w']) || ($widthcols[$i]['w'] && $table['w'] > $temppgwidth && !$this->keep_table_proportions && !$notfullwidth )){
24012 $list[] = $i;
24013 $wisa += $widthcols[$i]['miw'];
24014 $totalatextlength += $table['l'][$i];
24015 }
24016 }
24017 if (!$totalatextlength) { $totalatextlength =1; }
24018
24019 // Allocate spare (more than col's minimum width) across the cols according to their approx total text length
24020 // Do it by setting minimum width here
24021 if ($table['w'] > $wis + $tblbw) {
24022 // First set any cell widths set as percentages
24023 if ($table['w'] < $temppgwidth || $this->keep_table_proportions) {
24024 for($k=0;$k<$numcols;$k++) {
24025 if (isset($widthcols[$k]['wpercent'])) {
24026 $curr = $widthcols[$k]['miw'];
24027 $widthcols[$k]['miw'] = ($table['w']-$tblbw) * $widthcols[$k]['wpercent']/100;
24028 $wis += $widthcols[$k]['miw'] - $curr;
24029 $wisa += $widthcols[$k]['miw'] - $curr;
24030 }
24031 }
24032 }
24033 // Now allocate surplus up to maximum width of each column
24034 $surplus = 0; $ttl = 0; // number of surplus columns
24035 if (!count($list)) {
24036 $wi = ($table['w']-($wis + $tblbw)); // i.e. extra space to distribute
24037 for($k=0;$k<$numcols;$k++) {
24038 $spareratio = ($table['l'][$k] / $totaltextlength); // gives ratio to divide up free space
24039 // Don't allocate more than Maximum required width - save rest in surplus
24040 if ($widthcols[$k]['miw'] + ($wi * $spareratio) > $widthcols[$k]['maw']) {
24041 $surplus += ($wi * $spareratio) - ($widthcols[$k]['maw']-$widthcols[$k]['miw']);
24042 $widthcols[$k]['miw'] = $widthcols[$k]['maw'];
24043 }
24044 else {
24045 $notsetlist[] = $k;
24046 $ttl += $table['l'][$k];
24047 $widthcols[$k]['miw'] += ($wi * $spareratio);
24048 }
24049
24050 }
24051 }
24052 else {
24053 $wi = ($table['w'] - ($wis + $tblbw)); // i.e. extra space to distribute
24054 foreach ($list as $k) {
24055 $spareratio = ($table['l'][$k] / $totalatextlength); // gives ratio to divide up free space
24056 // Don't allocate more than Maximum required width - save rest in surplus
24057 if ($widthcols[$k]['miw'] + ($wi * $spareratio) > $widthcols[$k]['maw']) {
24058 $surplus += ($wi * $spareratio) - ($widthcols[$k]['maw']-$widthcols[$k]['miw']);
24059 $widthcols[$k]['miw'] = $widthcols[$k]['maw'];
24060 }
24061 else {
24062 $notsetlist[] = $k;
24063 $ttl += $table['l'][$k];
24064 $widthcols[$k]['miw'] += ($wi * $spareratio);
24065 }
24066 }
24067 }
24068 // If surplus still left over apportion it across columns
24069 if ($surplus) {
24070 // if some are set only add to remaining - otherwise add to all of them
24071 if (count($notsetlist) && count($notsetlist) < $numcols) {
24072 foreach ($notsetlist AS $i) {
24073 if ($ttl) $widthcols[$i]['miw'] += $surplus * $table['l'][$i] / $ttl ;
24074 }
24075 }
24076 // If some widths are defined, and others have been added up to their maxmum
24077 else if (count($list) && count($list) < $numcols) {
24078 foreach ($list AS $i) {
24079 $widthcols[$i]['miw'] += $surplus / count($list) ;
24080 }
24081 }
24082 else if ($numcols) { // If all columns
24083 $ttl = array_sum($table['l']);
24084 for ($i=0;$i<$numcols;$i++) {
24085 $widthcols[$i]['miw'] += $surplus * $table['l'][$i] / $ttl;
24086 }
24087 }
24088 }
24089
24090 }
24091
24092 // This sets the columns all to minimum width (which has been increased above if appropriate)
24093 for ($i=0;$i<$numcols;$i++) {
24094 $widthcols[$i] = $widthcols[$i]['miw'];
24095 }
24096
24097 // TABLE NOT WIDE ENOUGH EVEN FOR MINIMUM CONTENT WIDTH
24098 // If sum of column widths set are too wide for table
24099 $checktablewidth = 0;
24100 for ( $i = 0 ; $i < $numcols ; $i++ ) {
24101 $checktablewidth += $widthcols[$i];
24102 }
24103 if ($checktablewidth > ($temppgwidth + 0.001 - $tblbw)) {
24104 $usedup = 0; $numleft = 0;
24105 for ($i=0;$i<$numcols;$i++) {
24106 if ((isset($widthcols[$i]) && $widthcols[$i] > (($temppgwidth - $tblbw) / $numcols)) && (!isset($widthcols[$i]['w']))) {
24107 $numleft++;
24108 unset($widthcols[$i]);
24109 }
24110 else { $usedup += $widthcols[$i]; }
24111 }
24112 for ($i=0;$i<$numcols;$i++) {
24113 if (!isset($widthcols[$i]) || !$widthcols[$i]) {
24114 $widthcols[$i] = ((($temppgwidth - $tblbw) - $usedup)/ ($numleft));
24115 }
24116 }
24117 }
24118
24119 }
24120 else { //table has no width defined
24121 $table['w'] = $tablewidth;
24122 for ( $i = 0 ; $i < $numcols ; $i++) {
24123 if (isset($widthcols[$i]['wpercent']) && $this->keep_table_proportions) { $colwidth = $widthcols[$i]['maw']; }
24124 else if (isset($widthcols[$i]['w'])) { $colwidth = $widthcols[$i]['miw']; }
24125 else { $colwidth = $widthcols[$i]['maw']; }
24126 unset($widthcols[$i]);
24127 $widthcols[$i] = $colwidth;
24128 }
24129 }
24130
24131 if ($table['overflow']=='visible' && $table['level'] ==1) {
24132 if ($tablewidth > $this->blk[$this->blklvl]['inner_width']) {
24133 if ($this->cacheTables) { $fh = fopen($table['cache'], "r+b"); }
24134 else { $fh = null; }
24135 for ($j = 0 ; $j < $numcols; $j++) { //columns
24136 for ($i = 0 ; $i < $table['nr']; $i++) { //rows
24137 if (isset($table['cells'][$i][$j]) && $table['cells'][$i][$j]) {
24138 if ($this->cacheTables) {
24139 $cc = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
24140 $colspan = $cc['colspan'];
24141 }
24142 else
24143 $colspan = $table['cells'][$i][$j]['colspan'];
24144 if ($colspan > 1) {
24145 $w = 0;
24146 for ($c = $j; $c < ($j + $colspan); $c++) {
24147 $w += $widthcols[$c];
24148 }
24149 if ($w > $this->blk[$this->blklvl]['inner_width']) {
24150 $diff = $w - ($this->blk[$this->blklvl]['inner_width'] - $tblbw);
24151 for ($c = $j; $c < ($j + $colspan); $c++) {
24152 $widthcols[$c] -= $diff * ($widthcols[$c]/$w);
24153 }
24154 $table['w'] -= $diff;
24155 $table['csp'][$j] = $w - $diff;
24156 }
24157 }
24158 }
24159
24160 }
24161 }
24162 if ($this->cacheTables) { fclose($fh); }
24163 }
24164 $pgNo = 0;
24165 $currWc = 0;
24166 for ($i = 0 ; $i < $numcols; $i++) { //columns
24167 if (isset($table['csp'][$i])) {
24168 $w = $table['csp'][$i];
24169 unset($table['csp'][$i]);
24170 }
24171 else { $w = $widthcols[$i]; }
24172 if (($currWc + $w + $tblbw) > $this->blk[$this->blklvl]['inner_width']) {
24173 $pgNo++;
24174 $currWc = $widthcols[$i] ;
24175 }
24176 else { $currWc += $widthcols[$i] ; }
24177 $table['colPg'][$i] = $pgNo;
24178 }
24179 }
24180 }
24181
24182
24183
24184 function _tableHeight(&$table){
24185 $level = $table['level'];
24186 $levelid = $table['levelid'];
24187 $cells = &$table['cells'];
24188 $numcols = $table['nc'];
24189 $numrows = $table['nr'];
24190 $listspan = array();
24191 $checkmaxheight = 0;
24192 $headerrowheight = 0;
24193 $checkmaxheightplus = 0;
24194 $headerrowheightplus = 0;
24195 $firstrowheight = 0;
24196
24197 $footerrowheight = 0;
24198 $footerrowheightplus = 0;
24199 if ($this->table_rotate) {
24200 $temppgheight = $this->tbrot_maxh;
24201 $remainingpage = $this->tbrot_maxh;
24202 }
24203 else {
24204 $temppgheight = ($this->h - $this->bMargin - $this->tMargin) - $this->kwt_height;
24205 $remainingpage = ($this->h - $this->bMargin - $this->y) - $this->kwt_height;
24206
24207 // If it is less than 1/20th of the remaining page height to finish the DIV (i.e. DIV padding + table bottom margin)
24208 // then allow for this
24209 $enddiv = $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'] + $table['margin']['B'];
24210 if ($remainingpage > $enddiv && $enddiv/$remainingpage <0.05) { $remainingpage -= $enddiv; }
24211 else if ($remainingpage == 0) { $remainingpage = 0.001; }
24212 if ($temppgheight > $enddiv && $enddiv/$temppgheight <0.05) { $temppgheight -= $enddiv; }
24213 else if ($temppgheight == 0) { $temppgheight = 0.001; }
24214 }
24215 if ($remainingpage < 0) { $remainingpage = 0.001; } // mPDF 5.6.64
24216 if ($temppgheight < 0) { $temppgheight = 0.001; } // mPDF 5.6.64
24217
24218 if ($this->cacheTables) { $fh = fopen($table['cache'], "r+b"); }
24219 else { $fh = null; }
24220
24221 for( $i = 0 ; $i < $numrows ; $i++ ) { //rows
24222 $heightrow = &$table['hr'][$i];
24223 for( $j = 0 ; $j < $numcols ; $j++ ) { //columns
24224 if (isset($cells[$i][$j]) && $cells[$i][$j]) {
24225 if ($this->cacheTables) {
24226 $c = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
24227 }
24228 else
24229 $c = &$cells[$i][$j];
24230
24231 if ($this->simpleTables){
24232 if ($table['borders_separate']) { // NB twice border width
24233 $extraWLR = ($table['simple']['border_details']['L']['w']+$table['simple']['border_details']['R']['w']) + ($c['padding']['L']+$c['padding']['R'])+$table['border_spacing_H'];
24234 $extrh = ($table['simple']['border_details']['T']['w']+$table['simple']['border_details']['B']['w']) + ($c['padding']['T']+$c['padding']['B'])+$table['border_spacing_V'];
24235 }
24236 else {
24237 $extraWLR = ($table['simple']['border_details']['L']['w']+$table['simple']['border_details']['R']['w'])/2 + ($c['padding']['L']+$c['padding']['R']);
24238 $extrh = ($table['simple']['border_details']['T']['w']+$table['simple']['border_details']['B']['w'])/2 + ($c['padding']['T']+$c['padding']['B']);
24239 }
24240 }
24241 else {
24242 if ($this->packTableData) {
24243 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
24244 }
24245 else {
24246 $bt = $c['border_details']['T']['w'];
24247 $bb = $c['border_details']['B']['w'];
24248 $br = $c['border_details']['R']['w'];
24249 $bl = $c['border_details']['L']['w'];
24250 }
24251 if ($table['borders_separate']) { // NB twice border width
24252 $extraWLR = $bl + $br + $c['padding']['L'] + $c['padding']['R'] + $table['border_spacing_H'];
24253 $extrh = $bt + $bb + $c['padding']['T'] + $c['padding']['B'] + $table['border_spacing_V'];
24254 }
24255 else {
24256 $extraWLR = $bl/2 + $br/2 + $c['padding']['L'] + $c['padding']['R'];
24257 $extrh = $bt/2 + $bb/2 + $c['padding']['T']+$c['padding']['B'];
24258 }
24259 }
24260
24261 if ($table['overflow']=='visible' && $level==1)
24262 list($x,$cw) = $this->_splitTableGetWidth($table, $i,$j, $fh);
24263 else
24264 list($x,$cw) = $this->_tableGetWidth($table, $i,$j, $fh);
24265
24266 // Get CELL HEIGHT
24267 // ++ extra parameter forces wrap to break word
24268 if ($c['R'] && isset($c['textbuffer'])) { // mPDF 5.4.01
24269 $str = '';
24270 foreach($c['textbuffer'] AS $t) { $str .= $t[0].' '; }
24271 $str = trim($str);
24272 $s_fs = $this->FontSizePt;
24273 $s_f = $this->FontFamily;
24274 $s_st = $this->FontStyle;
24275 $this->SetFont($c['textbuffer'][0][4],$c['textbuffer'][0][2],$c['textbuffer'][0][11] / $this->shrin_k,true,true);
24276 $tempch = $this->GetStringWidth($str);
24277 if ($c['R'] >= 45 && $c['R'] < 90) {
24278 $tempch = ((sin(deg2rad($c['R']))) * $tempch ) + ((sin(deg2rad($c['R']))) * (($c['textbuffer'][0][11]/_MPDFK) / $this->shrin_k));
24279 }
24280 $this->SetFont($s_f,$s_st,$s_fs,true,true);
24281 $ch = ($tempch ) + $extrh ;
24282 }
24283 else {
24284 if (isset($c['textbuffer'])) {
24285 $tempch = $this->TableWordWrap(($cw-$extraWLR),1,$c['textbuffer'], $c['dfs']);
24286 }
24287 else { $tempch = 0; }
24288
24289 // Added cellpadding top and bottom. (Lineheight already adjusted to table_lineheight)
24290 $ch = $tempch + $extrh ;
24291 }
24292 //If height is defined and it is bigger than calculated $ch then update values
24293 if (isset($c['h']) && $c['h'] > $ch) {
24294 $c['mih'] = $ch; //in order to keep valign working
24295 $ch = $c['h'];
24296 }
24297 else $c['mih'] = $ch;
24298 if ($this->cacheTables) {
24299 $this->_cacheUpdateMtx($c, $fh, $table['cells'][$i][$j], 'mih');
24300 }
24301 if (isset($c['rowspan'])) $listspan[] = array($i,$j);
24302 elseif ($heightrow < $ch) $heightrow = $ch;
24303
24304 // this is the extra used in _tableWrite to determine whether to trigger a page change
24305 if ($table['borders_separate']) {
24306 if ($i == ($numrows-1) || (isset($c['rowspan']) && ($i+$c['rowspan']) == ($numrows)) ) {
24307 $extra = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2;
24308 }
24309 else {
24310 $extra = $table['border_spacing_V']/2;
24311 }
24312 }
24313 else {
24314 if (!$this->simpleTables){
24315 $extra = $bb/2;
24316 }
24317 else if ($this->simpleTables){
24318 $extra = $table['simple']['border_details']['B']['w'] /2;
24319 }
24320 }
24321 if (isset($table['is_thead'][$i]) && $table['is_thead'][$i]) {
24322 if ($j==0) {
24323 $headerrowheight += $ch;
24324 $headerrowheightplus += $ch+$extra;
24325 }
24326 }
24327 else if (isset($table['is_tfoot'][$i]) && $table['is_tfoot'][$i]) {
24328 if ($j==0) {
24329 $footerrowheight += $ch;
24330 $footerrowheightplus += $ch+$extra;
24331 }
24332 }
24333 else {
24334 $checkmaxheight = max($checkmaxheight,$ch);
24335 $checkmaxheightplus = max($checkmaxheightplus,$ch+$extra);
24336 }
24337 if ($this->tableLevel==1 && $i == $table['headernrows']) { $firstrowheight = max($ch,$firstrowheight); }
24338 unset($c);
24339 }
24340 }//end of columns
24341 }//end of rows
24342
24343 $heightrow = &$table['hr'];
24344 foreach ($listspan as $span) {
24345 list($i,$j) = $span;
24346 if ($this->cacheTables) {
24347 $c = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
24348 }
24349 else
24350 $c = &$cells[$i][$j];
24351 $lr = $i + $c['rowspan'];
24352 if ($lr > $numrows) $lr = $numrows;
24353 $hs = $hsa = 0;
24354 $list = array();
24355 for($k=$i;$k<$lr;$k++) {
24356 $hs += $heightrow[$k];
24357 if (!isset($c['h'])) {
24358 $list[] = $k;
24359 $hsa += $heightrow[$k];
24360 }
24361 }
24362
24363 if ($table['borders_separate']) {
24364 if ($i == ($numrows-1) || ($i+$c['rowspan']) == ($numrows) ) {
24365 $extra = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2;
24366 }
24367 else {
24368 $extra = $table['border_spacing_V']/2;
24369 }
24370 }
24371 else {
24372 if (!$this->simpleTables){
24373 if ($this->packTableData) {
24374 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($c['borderbin']);
24375 }
24376 else {
24377 $bb = $c['border_details']['B']['w'];
24378 }
24379 $extra = $bb/2;
24380 }
24381 else if ($this->simpleTables){
24382 $extra = $table['simple']['border_details']['B']['w'] /2;
24383 }
24384 }
24385 if (!empty($table['is_thead'][$i])) {
24386 $headerrowheight = max($headerrowheight,$hs);
24387 $headerrowheightplus = max($headerrowheightplus,$hs+$extra);
24388 }
24389 else if (!empty($table['is_tfoot'][$i])) {
24390 $footerrowheight = max($footerrowheight,$hs);
24391 $footerrowheightplus = max($footerrowheightplus,$hs+$extra);
24392 }
24393 else {
24394 $checkmaxheight = max($checkmaxheight,$hs);
24395 $checkmaxheightplus = max($checkmaxheightplus,$hs+$extra);
24396 }
24397 if ($this->tableLevel==1 && $i == $table['headernrows']) { $firstrowheight = max($hs,$firstrowheight); }
24398
24399 if ($c['mih'] > $hs) {
24400 if (!$hs) {
24401 for($k=$i;$k<$lr;$k++) $heightrow[$k] = $c['mih']/$c['rowspan'];
24402 }
24403 elseif (!count($list)) {
24404 $hi = $c['mih'] - $hs;
24405 for($k=$i;$k<$lr;$k++) $heightrow[$k] += ($heightrow[$k]/$hs)*$hi;
24406 }
24407 else {
24408 $hi = $c['mih'] - $hsa;
24409 foreach ($list as $k) $heightrow[$k] += ($heightrow[$k]/$hsa)*$hi;
24410 }
24411 }
24412 unset($c);
24413
24414 // If rowspans overlap so that one or more rows do not have a height set...
24415 // i.e. for one or more rows, the only cells (explicit) in that row have rowspan>1
24416 // so heightrow is still == 0
24417 if ($heightrow[$i]==0) {
24418 // Get row extent to analyse above and below
24419 $top = $i;
24420 foreach ($listspan as $checkspan) {
24421 list($cki,$ckj) = $checkspan;
24422 if ($this->cacheTables) {
24423 $c = $this->_uncacheCell($table['cells'][$cki][$ckj], '', $fh);
24424 }
24425 else
24426 $c = &$cells[$cki][$ckj];
24427 if (isset($c['rowspan']) && $c['rowspan']>1) {
24428 if (($cki + $c['rowspan']-1) >= $i) { $top = min($top, $cki); }
24429 }
24430 }
24431 $bottom = $i + $c['rowspan']-1;
24432 // Check for overconstrained conditions
24433 for ($k=$top; $k<=$bottom; $k++) {
24434 // if ['hr'] for any of the others is also 0, then abort (too complicated)
24435 if ($k != $i && $heightrow[$k]==0) { break(1); }
24436 // check again that top and bottom are not crossed by rowspans - or abort (too complicated)
24437 if ($k==$top) {
24438 // ???? take account of colspan as well???
24439 for( $m = 0 ; $m < $numcols ; $m++ ) { //columns
24440 if (!isset($cells[$k][$m]) || $cells[$k][$m]==0) {
24441 break(2);
24442 }
24443 }
24444 }
24445 else if ($k==$bottom) {
24446 // ???? take account of colspan as well???
24447 for( $m = 0 ; $m < $numcols ; $m++ ) { //columns
24448 if ($this->cacheTables) {
24449 $c = $this->_uncacheCell($table['cells'][$k][$m], '', $fh);
24450 }
24451 else
24452 $c = &$cells[$k][$m];
24453 if (isset($c['rowspan']) && $c['rowspan']>1) {
24454 break(2);
24455 }
24456 }
24457 }
24458 }
24459 // By columns add up col height using ['h'] if set or ['mih'] if not
24460 // Intentionally do not substract border-spacing
24461 $colH = array();
24462 $extH = 0;
24463 $newhr = array();
24464 for( $m = 0 ; $m < $numcols ; $m++ ) { //columns
24465 for ($k=$top; $k<=$bottom; $k++) {
24466 if (isset($cells[$k][$m]) && $cells[$k][$m]!=0) {
24467 if ($this->cacheTables) {
24468 $c = $this->_uncacheCell($table['cells'][$k][$m], '', $fh);
24469 }
24470 else
24471 $c = &$cells[$k][$m];
24472 if (isset($c['h']) && $c['h']) {
24473 $useh = $c['h'];
24474 }
24475 // ???? take account of colspan as well???
24476 else {
24477 $useh = $c['mih'];
24478 }
24479 $colH[$m] += $useh;
24480 if (!isset($c['rowspan']) || $c['rowspan']<2) { $newhr[$k] = max($newhr[$k], $useh); }
24481 }
24482 }
24483 $extH = max($tabH, $colH[$m]);
24484 }
24485 $newhr[$i] = $extH - array_sum($newhr);
24486 for ($k=$top; $k<=$bottom; $k++) { $heightrow[$k] = $newhr[$k]; }
24487 }
24488
24489
24490 unset($c);
24491 }
24492
24493 $table['h'] = array_sum($heightrow);
24494 unset($heightrow);
24495
24496 if ($this->cacheTables) { fclose($fh); }
24497
24498 if ($table['borders_separate']) {
24499 $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'];
24500 }
24501 else {
24502 $table['h'] += $table['margin']['T'] + $table['margin']['B'] + $table['max_cell_border_width']['T']/2 + $table['max_cell_border_width']['B']/2;
24503 }
24504
24505 $maxrowheight = $checkmaxheightplus + $headerrowheightplus + $footerrowheightplus;
24506 $maxfirstrowheight = $firstrowheight + $headerrowheightplus + $footerrowheightplus; // includes thead, 1st row and tfoot
24507 return array($table['h'],$maxrowheight,$temppgheight,$remainingpage,$maxfirstrowheight);
24508 }
24509
24510 function _tableGetWidth(&$table, $i,$j, $fh){
24511 if ($this->cacheTables) {
24512 $cell = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
24513 }
24514 else
24515 $cell = &$table['cells'][$i][$j];
24516 if ($cell) {
24517 if (isset($cell['x0'])) { return array($cell['x0'], $cell['w0']); }
24518 $x = 0;
24519 $widthcols = &$table['wc'];
24520 for( $k = 0 ; $k < $j ; $k++ ) $x += $widthcols[$k];
24521 $w = $widthcols[$j];
24522 if (isset($cell['colspan'])) {
24523 for ( $k = $j+$cell['colspan']-1 ; $k > $j ; $k-- ) $w += $widthcols[$k];
24524 }
24525 $cell['x0'] = $x;
24526 $cell['w0'] = $w;
24527 if ($this->cacheTables) {
24528 $this->_cacheUpdateMtx($cell, $fh, $table['cells'][$i][$j], 'x0');
24529 }
24530 return array($x, $w);
24531 }
24532 return array(0,0);
24533 }
24534
24535 function _splitTableGetWidth(&$table, $i,$j, $fh){
24536 if ($this->cacheTables) {
24537 $cell = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
24538 }
24539 else
24540 $cell = &$table['cells'][$i][$j];
24541 if ($cell) {
24542 if (isset($cell['x0'])) return array($cell['x0'], $cell['w0']);
24543 $x = 0;
24544 $widthcols = &$table['wc'];
24545 $pg = $table['colPg'][$j];
24546 for( $k = 0 ; $k < $j ; $k++ ) {
24547 if ($table['colPg'][$k]==$pg) $x += $widthcols[$k];
24548 }
24549 $w = $widthcols[$j];
24550 if (isset($cell['colspan'])) {
24551 for ( $k = $j+$cell['colspan']-1 ; $k > $j ; $k-- ) if ($table['colPg'][$k]==$pg) $w += $widthcols[$k];
24552 }
24553 $cell['x0'] = $x;
24554 $cell['w0'] = $w;
24555 if ($this->cacheTables) {
24556 $this->_cacheUpdateMtx($cell, $fh, $table['cells'][$i][$j], 'x0');
24557 }
24558 return array($x, $w);
24559 }
24560 return array(0,0);
24561 }
24562
24563
24564 function _tableGetHeight(&$table, $i,$j, $fh){
24565 if ($this->cacheTables) {
24566 $cell = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
24567 }
24568 else
24569 $cell = &$table['cells'][$i][$j];
24570 if ($cell){
24571 if (isset($cell['y0'])) return array($cell['y0'], $cell['h0']);
24572 $y = 0;
24573 $heightrow = &$table['hr'];
24574 for ($k=0;$k<$i;$k++) $y += $heightrow[$k];
24575 $h = $heightrow[$i];
24576 if (isset($cell['rowspan'])){
24577 for ($k=$i+$cell['rowspan']-1;$k>$i;$k--)
24578 $h += $heightrow[$k];
24579 }
24580 $cell['y0'] = $y;
24581 $cell['h0'] = $h;
24582 if ($this->cacheTables) {
24583 $this->_cacheUpdateMtx($cell, $fh, $table['cells'][$i][$j], 'y0');
24584 }
24585 return array($y, $h);
24586 }
24587 return array(0,0);
24588 }
24589
24590 function _tableGetMaxRowHeight($table, $row, $fh) {
24591 if ($row==$table['nc']-1) { return $table['hr'][$row]; }
24592 $maxrowheight = $table['hr'][$row];
24593 for ($i=$row+1;$i<$table['nr'];$i++) {
24594 $cellsset = 0;
24595 for ($j=0;$j<$table['nc'];$j++) {
24596 if ($this->cacheTables) {
24597 $cell = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
24598 if ($cell) {
24599 if (isset($cell['colspan'])) { $cellsset += $cell['colspan']; }
24600 else $cellsset += 1;
24601 }
24602 }
24603 else {
24604 if ($table['cells'][$i][$j]) {
24605 if (isset($table['cells'][$i][$j]['colspan'])) { $cellsset += $table['cells'][$i][$j]['colspan']; }
24606 else $cellsset += 1;
24607 }
24608 }
24609 }
24610 if ($cellsset == $table['nc']) { return $maxrowheight; }
24611 else { $maxrowheight += $table['hr'][$i]; }
24612 }
24613 return $maxrowheight;
24614 }
24615
24616
24617 // CHANGED TO ALLOW TABLE BORDER TO BE SPECIFIED CORRECTLY - added border_details
24618 function _tableRect($x, $y, $w, $h, $bord=-1, $details=array(), $buffer=false, $bSeparate=false, $cort='cell', $tablecorner='', $bsv=0, $bsh=0) {
24619 $cellBorderOverlay = array();
24620
24621 if ($bord==-1) { $this->Rect($x, $y, $w, $h); }
24622 else if ($this->simpleTables && ($cort=='cell')) {
24623 $this->SetLineWidth($details['L']['w']);
24624 if ($details['L']['c']) {
24625 $this->SetDColor($details['L']['c']);
24626 }
24627 else { $this->SetDColor($this->ConvertColor(0)); }
24628 $this->SetLineJoin(0);
24629 $this->Rect($x, $y, $w, $h);
24630 }
24631 else if ($bord){
24632 if (!$bSeparate && $buffer) {
24633 $priority = 'LRTB';
24634 for($p=0;$p<strlen($priority);$p++) {
24635 $side = $priority[$p];
24636 $details['p'] = $side ;
24637
24638 $dom = 0;
24639 if (isset($details[$side]['w'])) { $dom += ($details[$side]['w'] * 100000); }
24640 if (isset($details[$side]['style'])) { $dom += (array_search($details[$side]['style'],$this->borderstyles)*100) ; }
24641 if (isset($details[$side]['dom'])) { $dom += ($details[$side]['dom']*10); }
24642
24643 // Precedence to darker colours at joins
24644 $coldom = 0;
24645 if (isset($details[$side]['c']) && is_array($details[$side]['c'])) {
24646 if ($details[$side]['c']{0}==3) { // RGB
24647 $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);
24648 }
24649 } // 10 black - 0 white
24650 if ($coldom) { $dom += $coldom; }
24651 // Lastly precedence to RIGHT and BOTTOM cells at joins
24652 if (isset($details['cellposdom'])) { $dom += $details['cellposdom']; }
24653
24654 $save = false;
24655 if ($side == 'T' && $this->issetBorder($bord, _BORDER_TOP)) { $cbord = _BORDER_TOP; $save = true; }
24656 else if ($side == 'L' && $this->issetBorder($bord, _BORDER_LEFT)) { $cbord = _BORDER_LEFT; $save = true; }
24657 else if ($side == 'R' && $this->issetBorder($bord, _BORDER_RIGHT)) { $cbord = _BORDER_RIGHT; $save = true; }
24658 else if ($side == 'B' && $this->issetBorder($bord, _BORDER_BOTTOM)) { $cbord = _BORDER_BOTTOM; $save = true; }
24659
24660 if ($save) {
24661 $this->cellBorderBuffer[] = pack("A16nCnda6A10d14",
24662 str_pad(sprintf("%08.7f", $dom),16,"0",STR_PAD_LEFT),
24663 $cbord,
24664 ord($side),
24665 $details[$side]['s'],
24666 $details[$side]['w'],
24667 $details[$side]['c'],
24668 $details[$side]['style'],
24669 $x, $y, $w, $h,
24670 $details['mbw']['BL'],
24671 $details['mbw']['BR'],
24672 $details['mbw']['RT'],
24673 $details['mbw']['RB'],
24674 $details['mbw']['TL'],
24675 $details['mbw']['TR'],
24676 $details['mbw']['LT'],
24677 $details['mbw']['LB'],
24678 $details['cellposdom'],
24679 0
24680 );
24681 if ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'groove' || $details[$side]['style'] == 'inset' || $details[$side]['style'] == 'outset' || $details[$side]['style'] == 'double' ) {
24682 $details[$side]['overlay'] = true;
24683 $this->cellBorderBuffer[] = pack("A16nCnda6A10d14",
24684 str_pad(sprintf("%08.7f", ($dom+4)),16,"0",STR_PAD_LEFT),
24685 $cbord,
24686 ord($side),
24687 $details[$side]['s'],
24688 $details[$side]['w'],
24689 $details[$side]['c'],
24690 $details[$side]['style'],
24691 $x, $y, $w, $h,
24692 $details['mbw']['BL'],
24693 $details['mbw']['BR'],
24694 $details['mbw']['RT'],
24695 $details['mbw']['RB'],
24696 $details['mbw']['TL'],
24697 $details['mbw']['TR'],
24698 $details['mbw']['LT'],
24699 $details['mbw']['LB'],
24700 $details['cellposdom'],
24701 1
24702 );
24703 }
24704 }
24705 }
24706 return;
24707 }
24708
24709 if (isset($details['p']) && strlen($details['p'])>1) { $priority = $details['p']; }
24710 else { $priority='LTRB'; }
24711 $Tw = 0;
24712 $Rw = 0;
24713 $Bw = 0;
24714 $Lw = 0;
24715 if (isset($details['T']['w'])) { $Tw = $details['T']['w']; }
24716 if (isset($details['R']['w'])) { $Rw = $details['R']['w']; }
24717 if (isset($details['B']['w'])) { $Bw = $details['B']['w']; }
24718 if (isset($details['L']['w'])) { $Lw = $details['L']['w']; }
24719
24720 $x2 = $x + $w; $y2 = $y + $h;
24721 $oldlinewidth = $this->LineWidth;
24722
24723 for($p=0;$p<strlen($priority);$p++) {
24724 $side = $priority[$p];
24725 $xadj = 0;
24726 $xadj2 = 0;
24727 $yadj = 0;
24728 $yadj2 = 0;
24729 $print = false;
24730 if ($Tw && $side=='T' && $this->issetBorder($bord, _BORDER_TOP)) { // TOP
24731 $ly1 = $y;
24732 $ly2 = $y;
24733 $lx1 = $x;
24734 $lx2 = $x2;
24735 $this->SetLineWidth($Tw);
24736 if ($cort == 'cell' || strpos($tablecorner,'L')!==false) {
24737 if ($Tw > $Lw) $xadj = ($Tw - $Lw)/2;
24738 if ($Tw < $Lw) $xadj = ($Tw + $Lw)/2;
24739 }
24740 else { $xadj = $Tw/2 - $bsh/2; }
24741 if ($cort == 'cell' || strpos($tablecorner,'R')!==false) {
24742 if ($Tw > $Rw) $xadj2 = ($Tw - $Rw)/2;
24743 if ($Tw < $Rw) $xadj2 = ($Tw + $Rw)/2;
24744 }
24745 else { $xadj2 = $Tw/2 - $bsh/2; }
24746 if (!$bSeparate && $details['mbw']['TL']) {
24747 $xadj = ($Tw - $details['mbw']['TL'])/2 ;
24748 }
24749 if (!$bSeparate && $details['mbw']['TR']) {
24750 $xadj2 = ($Tw - $details['mbw']['TR'])/2;
24751 }
24752 $print = true;
24753 }
24754 if ($Lw && $side=='L' && $this->issetBorder($bord, _BORDER_LEFT)) { // LEFT
24755 $ly1 = $y;
24756 $ly2 = $y2;
24757 $lx1 = $x;
24758 $lx2 = $x;
24759 $this->SetLineWidth($Lw);
24760 if ($cort == 'cell' || strpos($tablecorner,'T')!==false) {
24761 if ($Lw > $Tw) $yadj = ($Lw - $Tw)/2;
24762 if ($Lw < $Tw) $yadj = ($Lw + $Tw)/2;
24763 }
24764 else { $yadj = $Lw/2 - $bsv/2; }
24765 if ($cort == 'cell' || strpos($tablecorner,'B')!==false) {
24766 if ($Lw > $Bw) $yadj2 = ($Lw - $Bw)/2;
24767 if ($Lw < $Bw) $yadj2 = ($Lw + $Bw)/2;
24768 }
24769 else { $yadj2 = $Lw/2 - $bsv/2; }
24770 if (!$bSeparate && $details['mbw']['LT']) {
24771 $yadj = ($Lw - $details['mbw']['LT'])/2;
24772 }
24773 if (!$bSeparate && $details['mbw']['LB']) {
24774 $yadj2 = ($Lw - $details['mbw']['LB'])/2;
24775 }
24776 $print = true;
24777 }
24778 if ($Rw && $side=='R' && $this->issetBorder($bord, _BORDER_RIGHT)) { // RIGHT
24779 $ly1 = $y;
24780 $ly2 = $y2;
24781 $lx1 = $x2;
24782 $lx2 = $x2;
24783 $this->SetLineWidth($Rw);
24784 if ($cort == 'cell' || strpos($tablecorner,'T')!==false) {
24785 if ($Rw < $Tw) $yadj = ($Rw + $Tw)/2;
24786 if ($Rw > $Tw) $yadj = ($Rw - $Tw)/2;
24787 }
24788 else { $yadj = $Rw/2 - $bsv/2; }
24789
24790 if ($cort == 'cell' || strpos($tablecorner,'B')!==false) {
24791 if ($Rw > $Bw) $yadj2 = ($Rw - $Bw)/2;
24792 if ($Rw < $Bw) $yadj2 = ($Rw + $Bw)/2;
24793 }
24794 else { $yadj2 = $Rw/2 - $bsv/2; }
24795
24796 if (!$bSeparate && $details['mbw']['RT']) {
24797 $yadj = ($Rw - $details['mbw']['RT'])/2;
24798 }
24799 if (!$bSeparate && $details['mbw']['RB']) {
24800 $yadj2 = ($Rw - $details['mbw']['RB'])/2;
24801 }
24802 $print = true;
24803 }
24804 if ($Bw && $side=='B' && $this->issetBorder($bord, _BORDER_BOTTOM)) { // BOTTOM
24805 $ly1 = $y2;
24806 $ly2 = $y2;
24807 $lx1 = $x;
24808 $lx2 = $x2;
24809 $this->SetLineWidth($Bw);
24810 if ($cort == 'cell' || strpos($tablecorner,'L')!==false) {
24811 if ($Bw > $Lw) $xadj = ($Bw - $Lw)/2;
24812 if ($Bw < $Lw) $xadj = ($Bw + $Lw)/2;
24813 }
24814 else { $xadj = $Bw/2 - $bsh/2; }
24815 if ($cort == 'cell' || strpos($tablecorner,'R')!==false) {
24816 if ($Bw > $Rw) $xadj2 = ($Bw - $Rw)/2;
24817 if ($Bw < $Rw) $xadj2 = ($Bw + $Rw)/2;
24818 }
24819 else { $xadj2 = $Bw/2 - $bsh/2; }
24820 if (!$bSeparate && $details['mbw']['BL']) {
24821 $xadj = ($Bw - $details['mbw']['BL'])/2;
24822 }
24823 if (!$bSeparate && $details['mbw']['BR']) {
24824 $xadj2 = ($Bw - $details['mbw']['BR'])/2;
24825 }
24826 $print = true;
24827 }
24828
24829 // Now draw line
24830 if ($print) {
24831 /*-- TABLES-ADVANCED-BORDERS --*/
24832 if ($details[$side]['style'] == 'double') {
24833 if (!isset($details[$side]['overlay']) || !$details[$side]['overlay'] || $bSeparate) {
24834 if ($details[$side]['c']) {
24835 $this->SetDColor($details[$side]['c']);
24836 }
24837 else { $this->SetDColor($this->ConvertColor(0)); }
24838 $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2);
24839 }
24840 if ((isset($details[$side]['overlay']) && $details[$side]['overlay']) || $bSeparate) {
24841 if ($bSeparate && $cort=='table') {
24842 if ($side=='T') {
24843 $xadj -= $this->LineWidth/2;
24844 $xadj2 -= $this->LineWidth;
24845 if ($this->issetBorder($bord, _BORDER_LEFT)) {
24846 $xadj += $this->LineWidth/2;
24847 }
24848 if ($this->issetBorder($bord, _BORDER_RIGHT)) {
24849 $xadj2 += $this->LineWidth;
24850 }
24851 }
24852 if ($side=='L') {
24853 $yadj -= $this->LineWidth/2;
24854 $yadj2 -= $this->LineWidth;
24855 if ($this->issetBorder($bord, _BORDER_TOP)) {
24856 $yadj += $this->LineWidth/2;
24857 }
24858 if ($this->issetBorder($bord, _BORDER_BOTTOM)) {
24859 $yadj2 += $this->LineWidth;
24860 }
24861 }
24862 if ($side=='B') {
24863 $xadj -= $this->LineWidth/2;
24864 $xadj2 -= $this->LineWidth;
24865 if ($this->issetBorder($bord, _BORDER_LEFT)) {
24866 $xadj += $this->LineWidth/2;
24867 }
24868 if ($this->issetBorder($bord, _BORDER_RIGHT)) {
24869 $xadj2 += $this->LineWidth;
24870 }
24871 }
24872 if ($side=='R') {
24873 $yadj -= $this->LineWidth/2;
24874 $yadj2 -= $this->LineWidth;
24875 if ($this->issetBorder($bord, _BORDER_TOP)) {
24876 $yadj += $this->LineWidth/2;
24877 }
24878 if ($this->issetBorder($bord, _BORDER_BOTTOM)) {
24879 $yadj2 += $this->LineWidth;
24880 }
24881 }
24882 }
24883
24884 $this->SetLineWidth($this->LineWidth/3);
24885
24886 $tbcol = $this->ConvertColor(255);
24887 for($l=0; $l <= $this->blklvl; $l++) {
24888 if ($this->blk[$l]['bgcolor']) {
24889 $tbcol = ($this->blk[$l]['bgcolorarray']); // mPDF 5.6.53
24890 }
24891 }
24892
24893 if ($bSeparate) {
24894 $cellBorderOverlay[] = array(
24895 'x' => $lx1 + $xadj,
24896 'y' => $ly1 + $yadj,
24897 'x2' => $lx2 - $xadj2,
24898 'y2' => $ly2 - $yadj2,
24899 'col' => $tbcol,
24900 'lw' => $this->LineWidth,
24901 );
24902 }
24903 else {
24904 $this->SetDColor($tbcol);
24905 $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2);
24906 }
24907 }
24908 }
24909
24910
24911 else if (isset($details[$side]['style']) && ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'groove' || $details[$side]['style'] == 'inset' || $details[$side]['style'] == 'outset')) {
24912 if (!isset($details[$side]['overlay']) || !$details[$side]['overlay'] || $bSeparate) {
24913 if ($details[$side]['c']) {
24914 $this->SetDColor($details[$side]['c']);
24915 }
24916 else { $this->SetDColor($this->ConvertColor(0)); }
24917 if ($details[$side]['style'] == 'outset' || $details[$side]['style'] == 'groove') {
24918 $nc = $this->_darkenColor($details[$side]['c']);
24919 $this->SetDColor($nc);
24920 }
24921 else if ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'inset') {
24922 $nc = $this->_lightenColor($details[$side]['c']);
24923 $this->SetDColor($nc);
24924 }
24925 $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2);
24926 }
24927 if ((isset($details[$side]['overlay']) && $details[$side]['overlay']) || $bSeparate) {
24928 if ($details[$side]['c']) {
24929 $this->SetDColor($details[$side]['c']);
24930 }
24931 else { $this->SetDColor($this->ConvertColor(0)); }
24932 $doubleadj = ($this->LineWidth)/3;
24933 $this->SetLineWidth($this->LineWidth/2);
24934 $xadj3 = $yadj3 = $wadj3 = $hadj3 = 0;
24935
24936 if ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'inset') {
24937 $nc = $this->_darkenColor($details[$side]['c']);
24938
24939 if ($bSeparate && $cort=='table') {
24940 if ($side=='T') {
24941 $yadj3 = $this->LineWidth/2;
24942 $xadj3 = -$this->LineWidth/2;
24943 $wadj3 = $this->LineWidth;
24944 if ($this->issetBorder($bord, _BORDER_LEFT)) {
24945 $xadj3 += $this->LineWidth; $wadj3 -= $this->LineWidth;
24946 }
24947 if ($this->issetBorder($bord, _BORDER_RIGHT)) {
24948 $wadj3 -= $this->LineWidth*2;
24949 }
24950 }
24951 if ($side=='L') {
24952 $xadj3 = $this->LineWidth/2;
24953 $yadj3 = -$this->LineWidth/2;
24954 $hadj3 = $this->LineWidth;
24955 if ($this->issetBorder($bord, _BORDER_TOP)) {
24956 $yadj3 += $this->LineWidth; $hadj3 -= $this->LineWidth;
24957 }
24958 if ($this->issetBorder($bord, _BORDER_BOTTOM)) {
24959 $hadj3 -= $this->LineWidth*2;
24960 }
24961 }
24962 if ($side=='B') {
24963 $yadj3 = $this->LineWidth/2;
24964 $xadj3 = -$this->LineWidth/2;
24965 $wadj3 = $this->LineWidth;
24966 }
24967 if ($side=='R') {
24968 $xadj3 = $this->LineWidth/2;
24969 $yadj3 = -$this->LineWidth/2;
24970 $hadj3 = $this->LineWidth;
24971 }
24972 }
24973
24974 else if ($side=='T') { $yadj3 = $this->LineWidth/2; $xadj3 = $this->LineWidth/2; $wadj3 = -$this->LineWidth*2; }
24975 else if ($side=='L') { $xadj3 = $this->LineWidth/2; $yadj3 = $this->LineWidth/2; $hadj3 = -$this->LineWidth*2; }
24976
24977 else if ($side=='B' && $bSeparate) { $yadj3 = $this->LineWidth/2; $wadj3 = $this->LineWidth/2; }
24978 else if ($side=='R' && $bSeparate) { $xadj3 = $this->LineWidth/2; $hadj3 = $this->LineWidth/2; }
24979
24980 else if ($side=='B') { $yadj3 = $this->LineWidth/2; $xadj3 = $this->LineWidth/2; }
24981 else if ($side=='R') { $xadj3 = $this->LineWidth/2; $yadj3 = $this->LineWidth/2; }
24982 }
24983 else {
24984 $nc = $this->_lightenColor($details[$side]['c']);
24985
24986 if ($bSeparate && $cort=='table') {
24987 if ($side=='T') {
24988 $yadj3 = $this->LineWidth/2;
24989 $xadj3 = -$this->LineWidth/2;
24990 $wadj3 = $this->LineWidth;
24991 if ($this->issetBorder($bord, _BORDER_LEFT)) {
24992 $xadj3 += $this->LineWidth; $wadj3 -= $this->LineWidth;
24993 }
24994 }
24995 if ($side=='L') {
24996 $xadj3 = $this->LineWidth/2;
24997 $yadj3 = -$this->LineWidth/2;
24998 $hadj3 = $this->LineWidth;
24999 if ($this->issetBorder($bord, _BORDER_TOP)) {
25000 $yadj3 += $this->LineWidth; $hadj3 -= $this->LineWidth;
25001 }
25002 }
25003 if ($side=='B') {
25004 $yadj3 = $this->LineWidth/2;
25005 $xadj3 = -$this->LineWidth/2;
25006 $wadj3 = $this->LineWidth;
25007 if ($this->issetBorder($bord, _BORDER_LEFT)) {
25008 $xadj3 += $this->LineWidth; $wadj3 -= $this->LineWidth;
25009 }
25010 }
25011 if ($side=='R') {
25012 $xadj3 = $this->LineWidth/2;
25013 $yadj3 = -$this->LineWidth/2;
25014 $hadj3 = $this->LineWidth;
25015 if ($this->issetBorder($bord, _BORDER_TOP)) {
25016 $yadj3 += $this->LineWidth; $hadj3 -= $this->LineWidth;
25017 }
25018 }
25019 }
25020
25021 else if ($side=='T') { $yadj3 = $this->LineWidth/2; $xadj3 = $this->LineWidth/2; }
25022 else if ($side=='L') { $xadj3 = $this->LineWidth/2; $yadj3 = $this->LineWidth/2; }
25023
25024 else if ($side=='B' && $bSeparate) { $yadj3 = $this->LineWidth/2; $xadj3 = $this->LineWidth/2; }
25025 else if ($side=='R' && $bSeparate) { $xadj3 = $this->LineWidth/2; $yadj3 = $this->LineWidth/2; }
25026
25027 else if ($side=='B') { $yadj3 = $this->LineWidth/2; $xadj3 = -$this->LineWidth/2; $wadj3 = $this->LineWidth; }
25028 else if ($side=='R') { $xadj3 = $this->LineWidth/2; $yadj3 = -$this->LineWidth/2; $hadj3 = $this->LineWidth; }
25029
25030 }
25031
25032 if ($bSeparate) {
25033 $cellBorderOverlay[] = array(
25034 'x' => $lx1 + $xadj + $xadj3,
25035 'y' => $ly1 + $yadj + $yadj3,
25036 'x2' => $lx2 - $xadj2 + $xadj3 + $wadj3,
25037 'y2' => $ly2 - $yadj2 + $yadj3 + $hadj3,
25038 'col' => $nc,
25039 'lw' => $this->LineWidth,
25040 );
25041 }
25042 else {
25043 $this->SetDColor($nc);
25044 $this->Line($lx1 + $xadj + $xadj3, $ly1 + $yadj + $yadj3, $lx2 - $xadj2 + $xadj3 + $wadj3, $ly2 - $yadj2 + $yadj3 + $hadj3);
25045 }
25046 }
25047 }
25048
25049
25050 else {
25051 /*-- END TABLES-ADVANCED-BORDERS --*/
25052 if ($details[$side]['style'] == 'dashed') {
25053 $dashsize = 2; // final dash will be this + 1*linewidth
25054 $dashsizek = 1.5; // ratio of Dash/Blank
25055 $this->SetDash($dashsize,($dashsize/$dashsizek)+($this->LineWidth*2));
25056 }
25057 else if ($details[$side]['style'] == 'dotted') {
25058 $this->SetLineJoin(1);
25059 $this->SetLineCap(1);
25060 $this->SetDash(0.001,($this->LineWidth*2));
25061 }
25062 if ($details[$side]['c']) {
25063 $this->SetDColor($details[$side]['c']);
25064 }
25065 else { $this->SetDColor($this->ConvertColor(0)); }
25066 $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2);
25067 /*-- TABLES-ADVANCED-BORDERS --*/
25068 }
25069 /*-- END TABLES-ADVANCED-BORDERS --*/
25070
25071 // Reset Corners
25072 $this->SetDash();
25073 //BUTT style line cap
25074 $this->SetLineCap(2);
25075 }
25076 }
25077
25078 if ($bSeparate && count($cellBorderOverlay)) {
25079 foreach($cellBorderOverlay AS $cbo) {
25080 $this->SetLineWidth($cbo['lw']);
25081 $this->SetDColor($cbo['col']);
25082 $this->Line($cbo['x'], $cbo['y'], $cbo['x2'], $cbo['y2']);
25083 }
25084 }
25085
25086 // $this->SetLineWidth($oldlinewidth);
25087 // $this->SetDColor($this->ConvertColor(0));
25088 }
25089 }
25090
25091
25092 /*-- TABLES --*/
25093 /*-- TABLES-ADVANCED-BORDERS --*/
25094 function _lightenColor($c) {
25095 if (is_array($c)) { die('Color error in _lightencolor'); }
25096 if ($c{0}==3 || $c{0}==5) { // RGB
25097 list($h,$s,$l) = $this->rgb2hsl(ord($c{1})/255,ord($c{2})/255,ord($c{3})/255);
25098 $l += ((1 - $l)*0.8);
25099 list($r,$g,$b) = $this->hsl2rgb($h,$s,$l);
25100 $ret = array(3,$r,$g,$b);
25101 }
25102 else if ($c{0}==4 || $c{0}==6) { // CMYK
25103 $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)) );
25104 }
25105 else if ($c{0}==1) { // Grayscale
25106 $ret = array(1,min(255,(ord($c{1})+32)));
25107 }
25108 $c = array_pad($ret, 6, 0);
25109 $cstr = pack("a1ccccc", $c[0], ($c[1] & 0xFF), ($c[2] & 0xFF), ($c[3] & 0xFF), ($c[4] & 0xFF), ($c[5] & 0xFF) );
25110 return $cstr;
25111 }
25112
25113
25114 function _darkenColor($c) {
25115 if (is_array($c)) { die('Color error in _darkenColor'); }
25116 if ($c{0}==3 || $c{0}==5) { // RGB
25117 list($h,$s,$l) = $this->rgb2hsl(ord($c{1})/255,ord($c{2})/255,ord($c{3})/255);
25118 $s *= 0.25;
25119 $l *= 0.75;
25120 list($r,$g,$b) = $this->hsl2rgb($h,$s,$l);
25121 $ret = array(3,$r,$g,$b);
25122 }
25123 else if ($c{0}==4 || $c{0}==6) { // CMYK
25124 $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)) );
25125 }
25126 else if ($c{0}==1) { // Grayscale
25127 $ret = array(1,max(0,(ord($c{1})-32)));
25128 }
25129 $c = array_pad($ret, 6, 0);
25130 $cstr = pack("a1ccccc", $c[0], ($c[1] & 0xFF), ($c[2] & 0xFF), ($c[3] & 0xFF), ($c[4] & 0xFF), ($c[5] & 0xFF) );
25131 return $cstr;
25132 }
25133
25134 /*-- END TABLES-ADVANCED-BORDERS --*/
25135
25136
25137
25138 function setBorder(&$var, $flag, $set = true) {
25139 $flag = intval($flag);
25140 if ($set) { $set = true; }
25141 $var = intval($var);
25142 $var = $set ? ($var | $flag) : ($var & ~$flag);
25143 }
25144 function issetBorder($var, $flag) {
25145 $flag = intval($flag);
25146 $var = intval($var);
25147 return (($var & $flag) == $flag);
25148 }
25149
25150
25151 function _table2cellBorder(&$tableb, &$cbdb, &$cellb, $bval) {
25152 if ($tableb && $tableb['w'] > $cbdb['w']) {
25153 $cbdb = $tableb;
25154 $this->setBorder($cellb, $bval);
25155 }
25156 else if ($tableb && $tableb['w'] == $cbdb['w']
25157 && array_search($tableb['style'],$this->borderstyles) > array_search($cbdb['style'],$this->borderstyles)) {
25158 $cbdb = $tableb;
25159 $this->setBorder($cellb, $bval);
25160 }
25161 }
25162
25163 // FIX BORDERS ********************************************
25164 function _fixTableBorders(&$table){
25165 if ($this->cacheTables) { $fh = fopen($table['cache'], "r+b"); }
25166 else { $fh = null; }
25167
25168 if (!$table['borders_separate'] && $table['border_details']['L']['w']) {
25169 $table['max_cell_border_width']['L'] = $table['border_details']['L']['w'];
25170 }
25171 if (!$table['borders_separate'] && $table['border_details']['R']['w']) {
25172 $table['max_cell_border_width']['R'] = $table['border_details']['R']['w'];
25173 }
25174 if (!$table['borders_separate'] && $table['border_details']['T']['w']) {
25175 $table['max_cell_border_width']['T'] = $table['border_details']['T']['w'];
25176 }
25177 if (!$table['borders_separate'] && $table['border_details']['B']['w']) {
25178 $table['max_cell_border_width']['B'] = $table['border_details']['B']['w'];
25179 }
25180 if ($this->simpleTables) { return; }
25181 $cells = &$table['cells'];
25182 $numcols = $table['nc'];
25183 $numrows = $table['nr'];
25184 /*-- TABLES-ADVANCED-BORDERS --*/
25185 if (isset($table['topntail']) && $table['topntail']) { $tntborddet = $this->border_details($table['topntail']); }
25186 if (isset($table['thead-underline']) && $table['thead-underline']) { $thuborddet = $this->border_details($table['thead-underline']); }
25187 /*-- END TABLES-ADVANCED-BORDERS --*/
25188
25189 for( $i = 0 ; $i < $numrows ; $i++ ) { //Rows
25190 for( $j = 0 ; $j < $numcols ; $j++ ) { //Columns
25191 if (isset($cells[$i][$j]) && $cells[$i][$j]) {
25192 if ($this->cacheTables) {
25193 $cell = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
25194 }
25195 else
25196 $cell = &$cells[$i][$j];
25197 if ($this->packTableData) { // includes $this->cacheTables
25198 $cbord = $this->_unpackCellBorder($cell['borderbin']);
25199 }
25200 else {
25201 $cbord = &$cells[$i][$j];
25202 }
25203
25204 if (!$cbord['border'] && isset($table['border']) && $table['border'] && $this->table_border_attr_set) {
25205 $cbord['border'] = $table['border'];
25206 $cbord['border_details'] = $table['border_details'];
25207 }
25208
25209 if (isset($cell['colspan']) && $cell['colspan']>1) { $ccolsp = $cell['colspan']; }
25210 else { $ccolsp = 1; }
25211 if (isset($cell['rowspan']) && $cell['rowspan']>1) { $crowsp = $cell['rowspan']; }
25212 else { $crowsp = 1; }
25213
25214 $cbord['border_details']['cellposdom'] = ((($i+1)/$numrows) / 10000 ) + ((($j+1)/$numcols) / 10 );
25215 // Inherit Cell border from Table border
25216 if ($this->table_border_css_set && !$table['borders_separate']) {
25217 if ($i == 0) {
25218 $this->_table2cellBorder($table['border_details']['T'], $cbord['border_details']['T'], $cbord['border'], _BORDER_TOP);
25219 }
25220 if ($i == ($numrows-1) || ($i+$crowsp) == ($numrows) ) {
25221 $this->_table2cellBorder($table['border_details']['B'], $cbord['border_details']['B'], $cbord['border'], _BORDER_BOTTOM);
25222 }
25223 if ($j == 0) {
25224 $this->_table2cellBorder($table['border_details']['L'], $cbord['border_details']['L'], $cbord['border'], _BORDER_LEFT);
25225 }
25226 if ($j == ($numcols-1) || ($j+$ccolsp) == ($numcols) ) {
25227 $this->_table2cellBorder($table['border_details']['R'], $cbord['border_details']['R'], $cbord['border'], _BORDER_RIGHT);
25228 }
25229 }
25230
25231 /*-- TABLES-ADVANCED-BORDERS --*/
25232 $fixbottom = true;
25233 if (isset($table['topntail']) && $table['topntail']) {
25234 if ($i == 0) {
25235 $cbord['border_details']['T'] = $tntborddet;
25236 $this->setBorder($cbord['border'], _BORDER_TOP);
25237 }
25238 if ($this->tableLevel==1 && $table['headernrows']>0 && $i == $table['headernrows']-1) {
25239 $cbord['border_details']['B'] = $tntborddet;
25240 $this->setBorder($cbord['border'], _BORDER_BOTTOM);
25241 $fixbottom = false;
25242 }
25243 else if ($this->tableLevel==1 && $table['headernrows']>0 && $i == $table['headernrows']) {
25244 if (!$table['borders_separate']) {
25245 $cbord['border_details']['T'] = $tntborddet;
25246 $this->setBorder($cbord['border'], _BORDER_TOP);
25247 }
25248 }
25249 if ($this->tableLevel==1 && $table['footernrows']>0 && $i == ($numrows-$table['footernrows']-1)) {
25250 if (!$table['borders_separate']) {
25251 $cbord['border_details']['B'] = $tntborddet;
25252 $this->setBorder($cbord['border'], _BORDER_BOTTOM);
25253 $fixbottom = false;
25254 }
25255 }
25256 else if ($this->tableLevel==1 && $table['footernrows']>0 && $i == ($numrows-$table['footernrows'])) {
25257 $cbord['border_details']['T'] = $tntborddet;
25258 $this->setBorder($cbord['border'], _BORDER_TOP);
25259 }
25260 if ($this->tabletheadjustfinished) { // $this->tabletheadjustfinished called from tableheader
25261 if (!$table['borders_separate']) {
25262 $cbord['border_details']['T'] = $tntborddet;
25263 $this->setBorder($cbord['border'], _BORDER_TOP);
25264 }
25265 }
25266 if ($i == ($numrows-1) || ($i+$crowsp) == ($numrows) ) {
25267 $cbord['border_details']['B'] = $tntborddet;
25268 $this->setBorder($cbord['border'], _BORDER_BOTTOM);
25269 }
25270 }
25271 if (isset($table['thead-underline']) && $table['thead-underline']) {
25272 if ($table['borders_separate']) {
25273 if ($i == 0) {
25274 $cbord['border_details']['B'] = $thuborddet;
25275 $this->setBorder($cbord['border'], _BORDER_BOTTOM);
25276 $fixbottom = false;
25277 }
25278 }
25279 else {
25280 if ($this->tableLevel==1 && $table['headernrows']>0 && $i == $table['headernrows']-1) {
25281 $cbord['border_details']['T'] = $thuborddet;
25282 $this->setBorder($cbord['border'], _BORDER_TOP);
25283 }
25284 else if ($this->tabletheadjustfinished) { // $this->tabletheadjustfinished called from tableheader
25285 $cbord['border_details']['T'] = $thuborddet;
25286 $this->setBorder($cbord['border'], _BORDER_TOP);
25287 }
25288 }
25289 }
25290
25291 // Collapse Border - Algorithm for conflicting borders
25292 // Hidden >> Width >> double>solid>dashed>dotted... >> style set on cell>table >> top/left>bottom/right
25293 // Do not turn off border which is overridden
25294 // Needed for page break for TOP/BOTTOM both to be defined in Collapsed borders
25295 // Means it is painted twice. (Left/Right can still disable overridden border)
25296 if (!$table['borders_separate']) {
25297 if (($i < ($numrows-1) || ($i+$crowsp) < $numrows ) && $fixbottom ) { // Bottom
25298 for ($cspi = 0; $cspi<$ccolsp; $cspi++) {
25299 // already defined Top for adjacent cell below
25300 if (isset($cells[($i+$crowsp)][$j+$cspi])) {
25301 if ($this->packTableData) {
25302 if ($this->cacheTables) {
25303 $adjc = $this->_uncacheCell($table['cells'][$i+$crowsp][$j+$cspi], '', $fh);
25304 }
25305 else { $adjc = $cells[($i+$crowsp)][$j+$cspi]; }
25306 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
25307 }
25308 else { $celladj =& $cells[($i+$crowsp)][$j+$cspi]; }
25309 }
25310 else { $celladj = false; }
25311 if ($celladj && $celladj['border_details']['T']['s'] == 1) {
25312 $csadj = $celladj['border_details']['T']['w'];
25313 $csthis = $cbord['border_details']['B']['w'];
25314 // Hidden
25315 if ($cbord['border_details']['B']['style']=='hidden') {
25316 $celladj['border_details']['T'] = $cbord['border_details']['B'];
25317 $this->setBorder($celladj['border'] , _BORDER_TOP, false);
25318 $this->setBorder($cbord['border'] , _BORDER_BOTTOM , false);
25319 }
25320 else if ($celladj['border_details']['T']['style']=='hidden') {
25321 $cbord['border_details']['B'] = $celladj['border_details']['T'];
25322 $this->setBorder($cbord['border'] , _BORDER_BOTTOM , false);
25323 $this->setBorder($celladj['border'] , _BORDER_TOP, false);
25324 }
25325 // Width
25326 else if ($csthis > $csadj) {
25327 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
25328 $celladj['border_details']['T'] = $cbord['border_details']['B'];
25329 $this->setBorder($cbord['border'] , _BORDER_BOTTOM);
25330 }
25331 }
25332 else if ($csadj > $csthis) {
25333 if ($ccolsp < 2) { // don't overwrite this cell if it spans
25334 $cbord['border_details']['B'] = $celladj['border_details']['T'];
25335 $this->setBorder($celladj['border'] , _BORDER_TOP);
25336 }
25337 }
25338
25339 // double>solid>dashed>dotted...
25340 else if (array_search($cbord['border_details']['B']['style'],$this->borderstyles) > array_search($celladj['border_details']['T']['style'],$this->borderstyles)) {
25341 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
25342 $celladj['border_details']['T'] = $cbord['border_details']['B'];
25343 $this->setBorder($cbord['border'] , _BORDER_BOTTOM );
25344 }
25345 }
25346 else if (array_search($celladj['border_details']['T']['style'],$this->borderstyles) > array_search($cbord['border_details']['B']['style'],$this->borderstyles)) {
25347 if ($ccolsp < 2) { // don't overwrite this cell if it spans
25348 $cbord['border_details']['B'] = $celladj['border_details']['T'];
25349 $this->setBorder($celladj['border'] , _BORDER_TOP);
25350 }
25351 }
25352
25353
25354
25355 // Style set on cell vs. table
25356 else if ($celladj['border_details']['T']['dom'] > $cbord['border_details']['B']['dom']) {
25357 if ($ccolsp < 2) { // don't overwrite this cell if it spans
25358 $cbord['border_details']['B'] = $celladj['border_details']['T'];
25359 $this->setBorder($celladj['border'] , _BORDER_TOP);
25360 }
25361 }
25362 // Style set on cell vs. table - OR - LEFT/TOP (cell) in preference to BOTTOM/RIGHT
25363 else {
25364 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
25365 $celladj['border_details']['T'] = $cbord['border_details']['B'];
25366 $this->setBorder($cbord['border'] , _BORDER_BOTTOM );
25367 }
25368 }
25369 }
25370 else if ($celladj) {
25371 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
25372 $celladj['border_details']['T'] = $cbord['border_details']['B'];
25373 }
25374 }
25375 if ($celladj && $this->packTableData) {
25376 $celladj['borderbin'] = $this->_packCellBorder($celladj);
25377 unset($celladj['border']);
25378 unset($celladj['border_details']);
25379 }
25380 if ($this->cacheTables) {
25381 $this->_cacheUpdateBorder($celladj, $fh, $table['cells'][$i+$crowsp][$j+$cspi]);
25382 }
25383 unset($celladj);
25384 }
25385 }
25386
25387 if ($j < ($numcols-1) || ($j+$ccolsp) < $numcols ) { // Right-Left
25388 for ($cspi = 0; $cspi<$crowsp; $cspi++) {
25389 // already defined Left for adjacent cell to R
25390 if (isset($cells[($i+$cspi)][$j+$ccolsp])) {
25391 if ($this->packTableData) {
25392 if ($this->cacheTables) {
25393 $adjc = $this->_uncacheCell($table['cells'][$i+$cspi][$j+$ccolsp], '', $fh);
25394 }
25395 else { $adjc = $cells[($i+$cspi)][$j+$ccolsp]; }
25396 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
25397 }
25398 else { $celladj =& $cells[$i+$cspi][$j+$ccolsp]; }
25399 }
25400 else { $celladj = false; }
25401 if ($celladj && $celladj['border_details']['L']['s'] == 1) {
25402 $csadj = $celladj['border_details']['L']['w'];
25403 $csthis = $cbord['border_details']['R']['w'];
25404 // Hidden
25405 if ($cbord['border_details']['R']['style']=='hidden') {
25406 $celladj['border_details']['L'] = $cbord['border_details']['R'];
25407 $this->setBorder($celladj['border'] , _BORDER_LEFT, false);
25408 $this->setBorder($cbord['border'] , _BORDER_RIGHT , false);
25409 }
25410 else if ($celladj['border_details']['L']['style']=='hidden') {
25411 $cbord['border_details']['R'] = $celladj['border_details']['L'];
25412 $this->setBorder($cbord['border'] , _BORDER_RIGHT , false);
25413 $this->setBorder($celladj['border'] , _BORDER_LEFT, false);
25414 }
25415 // Width
25416 else if ($csthis > $csadj) {
25417 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
25418 $celladj['border_details']['L'] = $cbord['border_details']['R'];
25419 $this->setBorder($cbord['border'] , _BORDER_RIGHT);
25420 $this->setBorder($celladj['border'] , _BORDER_LEFT, false);
25421 }
25422 }
25423 else if ($csadj > $csthis) {
25424 if ($crowsp < 2) { // don't overwrite this cell if it spans
25425 $cbord['border_details']['R'] = $celladj['border_details']['L'];
25426 $this->setBorder($cbord['border'] , _BORDER_RIGHT, false);
25427 $this->setBorder($celladj['border'] , _BORDER_LEFT);
25428 }
25429 }
25430
25431 // double>solid>dashed>dotted...
25432 else if (array_search($cbord['border_details']['R']['style'],$this->borderstyles) > array_search($celladj['border_details']['L']['style'],$this->borderstyles)) {
25433 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
25434 $celladj['border_details']['L'] = $cbord['border_details']['R'];
25435 $this->setBorder($celladj['border'] , _BORDER_LEFT, false);
25436 $this->setBorder($cbord['border'] , _BORDER_RIGHT);
25437 }
25438 }
25439 else if (array_search($celladj['border_details']['L']['style'],$this->borderstyles) > array_search($cbord['border_details']['R']['style'],$this->borderstyles)) {
25440 if ($crowsp < 2) { // don't overwrite this cell if it spans
25441 $cbord['border_details']['R'] = $celladj['border_details']['L'];
25442 $this->setBorder($cbord['border'] , _BORDER_RIGHT , false);
25443 $this->setBorder($celladj['border'] , _BORDER_LEFT);
25444 }
25445 }
25446
25447
25448 // Style set on cell vs. table
25449 else if ($celladj['border_details']['L']['dom'] > $cbord['border_details']['R']['dom']) {
25450 if ($crowsp < 2) { // don't overwrite this cell if it spans
25451 $cbord['border_details']['R'] = $celladj['border_details']['L'];
25452 $this->setBorder($celladj['border'] , _BORDER_LEFT);
25453 }
25454 }
25455 // Style set on cell vs. table - OR - LEFT/TOP (cell) in preference to BOTTOM/RIGHT
25456 else {
25457 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
25458 $celladj['border_details']['L'] = $cbord['border_details']['R'];
25459 $this->setBorder($cbord['border'] , _BORDER_RIGHT);
25460 }
25461 }
25462 }
25463 else if ($celladj) {
25464 // if right-cell border is not set
25465 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
25466 $celladj['border_details']['L'] = $cbord['border_details']['R'];
25467 }
25468 }
25469 if ($celladj && $this->packTableData) {
25470 $celladj['borderbin'] = $this->_packCellBorder($celladj);
25471 unset($celladj['border']);
25472 unset($celladj['border_details']);
25473 }
25474 if ($this->cacheTables) {
25475 $this->_cacheUpdateBorder($celladj, $fh, $table['cells'][$i+$cspi][$j+$ccolsp]);
25476 }
25477 unset($celladj);
25478 }
25479 }
25480 }
25481
25482
25483 // Set maximum cell border width meeting at LRTB edges of cell - used for extended cell border
25484 // ['border_details']['mbw']['LT'] = meeting border width - Left border - Top end
25485 if (!$table['borders_separate']) {
25486 $cbord['border_details']['mbw']['BL'] = max($cbord['border_details']['mbw']['BL'], $cbord['border_details']['L']['w']);
25487 $cbord['border_details']['mbw']['BR'] = max($cbord['border_details']['mbw']['BR'], $cbord['border_details']['R']['w']);
25488 $cbord['border_details']['mbw']['RT'] = max($cbord['border_details']['mbw']['RT'], $cbord['border_details']['T']['w']);
25489 $cbord['border_details']['mbw']['RB'] = max($cbord['border_details']['mbw']['RB'], $cbord['border_details']['B']['w']);
25490 $cbord['border_details']['mbw']['TL'] = max($cbord['border_details']['mbw']['TL'], $cbord['border_details']['L']['w']);
25491 $cbord['border_details']['mbw']['TR'] = max($cbord['border_details']['mbw']['TR'], $cbord['border_details']['R']['w']);
25492 $cbord['border_details']['mbw']['LT'] = max($cbord['border_details']['mbw']['LT'], $cbord['border_details']['T']['w']);
25493 $cbord['border_details']['mbw']['LB'] = max($cbord['border_details']['mbw']['LB'], $cbord['border_details']['B']['w']);
25494 if (($i+$crowsp) < $numrows && isset($cells[$i+$crowsp][$j])) { // Has Bottom adjoining cell
25495 if ($this->packTableData) {
25496 if ($this->cacheTables) {
25497 $adjc = $this->_uncacheCell($table['cells'][$i+$crowsp][$j], '', $fh);
25498 }
25499 else { $adjc = $cells[$i+$crowsp][$j]; }
25500 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
25501 }
25502 else { $celladj =& $cells[$i+$crowsp][$j]; }
25503 $cbord['border_details']['mbw']['BL'] = max($cbord['border_details']['mbw']['BL'], $celladj['border_details']['L']['w'], $celladj['border_details']['mbw']['TL']);
25504 $cbord['border_details']['mbw']['BR'] = max($cbord['border_details']['mbw']['BR'], $celladj['border_details']['R']['w'], $celladj['border_details']['mbw']['TR']);
25505 $cbord['border_details']['mbw']['LB'] = max($cbord['border_details']['mbw']['LB'], $celladj['border_details']['mbw']['LT']);
25506 $cbord['border_details']['mbw']['RB'] = max($cbord['border_details']['mbw']['RB'], $celladj['border_details']['mbw']['RT']);
25507 unset($celladj);
25508 }
25509 if (($j+$ccolsp) < $numcols && isset($cells[$i][$j+$ccolsp])) { // Has Right adjoining cell
25510 if ($this->packTableData) {
25511 if ($this->cacheTables) {
25512 $adjc = $this->_uncacheCell($table['cells'][$i][$j+$ccolsp], '', $fh);
25513 }
25514 else { $adjc = $cells[$i][$j+$ccolsp]; }
25515 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
25516 }
25517 else { $celladj =& $cells[$i][$j+$ccolsp]; }
25518 $cbord['border_details']['mbw']['RT'] = max($cbord['border_details']['mbw']['RT'], $celladj['border_details']['T']['w'], $celladj['border_details']['mbw']['LT']);
25519 $cbord['border_details']['mbw']['RB'] = max($cbord['border_details']['mbw']['RB'], $celladj['border_details']['B']['w'], $celladj['border_details']['mbw']['LB']);
25520 $cbord['border_details']['mbw']['TR'] = max($cbord['border_details']['mbw']['TR'], $celladj['border_details']['mbw']['TL']);
25521 $cbord['border_details']['mbw']['BR'] = max($cbord['border_details']['mbw']['BR'], $celladj['border_details']['mbw']['BL']);
25522 unset($celladj);
25523 }
25524
25525 if ($i > 0 && isset($cells[$i-1][$j]) && (($this->packTableData && $cells[$i-1][$j]['borderbin']) || $cells[$i-1][$j]['border'])) { // Has Top adjoining cell
25526 if ($this->packTableData) {
25527 if ($this->cacheTables) {
25528 $adjc = $this->_uncacheCell($table['cells'][$i-1][$j], '', $fh);
25529 }
25530 else { $adjc = $cells[$i-1][$j]; }
25531 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
25532 }
25533 else { $celladj =& $cells[$i-1][$j]; }
25534 $cbord['border_details']['mbw']['TL'] = max($cbord['border_details']['mbw']['TL'], $celladj['border_details']['L']['w'], $celladj['border_details']['mbw']['BL']);
25535 $cbord['border_details']['mbw']['TR'] = max($cbord['border_details']['mbw']['TR'], $celladj['border_details']['R']['w'], $celladj['border_details']['mbw']['BR']);
25536 $cbord['border_details']['mbw']['LT'] = max($cbord['border_details']['mbw']['LT'], $celladj['border_details']['mbw']['LB']);
25537 $cbord['border_details']['mbw']['RT'] = max($cbord['border_details']['mbw']['RT'], $celladj['border_details']['mbw']['RB']);
25538
25539 if ($celladj['border_details']['mbw']['BL']) {
25540 $celladj['border_details']['mbw']['BL'] = max($cbord['border_details']['mbw']['TL'], $celladj['border_details']['mbw']['BL']);
25541 }
25542 if ($celladj['border_details']['mbw']['BR'] ) {
25543 $celladj['border_details']['mbw']['BR'] = max($celladj['border_details']['mbw']['BR'], $cbord['border_details']['mbw']['TR']);
25544 }
25545 if ($this->packTableData) { $cells[$i-1][$j]['borderbin'] = $this->_packCellBorder($celladj); }
25546 unset($celladj);
25547 }
25548 if ($j > 0 && isset($cells[$i][$j-1]) && (($this->packTableData && $cells[$i][$j-1]['borderbin']) || $cells[$i][$j-1]['border'])) { // Has Left adjoining cell
25549 if ($this->packTableData) {
25550 if ($this->cacheTables) {
25551 $adjc = $this->_uncacheCell($table['cells'][$i][$j-1], '', $fh);
25552 }
25553 else { $adjc = $cells[$i][$j-1]; }
25554 $celladj = $this->_unpackCellBorder($adjc['borderbin']);
25555 }
25556 else { $celladj =& $cells[$i][$j-1]; }
25557 $cbord['border_details']['mbw']['LT'] = max($cbord['border_details']['mbw']['LT'], $celladj['border_details']['T']['w'], $celladj['border_details']['mbw']['RT']);
25558 $cbord['border_details']['mbw']['LB'] = max($cbord['border_details']['mbw']['LB'], $celladj['border_details']['B']['w'], $celladj['border_details']['mbw']['RB']);
25559 $cbord['border_details']['mbw']['BL'] = max($cbord['border_details']['mbw']['BL'], $celladj['border_details']['mbw']['BR']);
25560 $cbord['border_details']['mbw']['TL'] = max($cbord['border_details']['mbw']['TL'], $celladj['border_details']['mbw']['TR']);
25561
25562 if ($celladj['border_details']['mbw']['RT']) {
25563 $celladj['border_details']['mbw']['RT'] = max($celladj['border_details']['mbw']['RT'], $cbord['border_details']['mbw']['LT']);
25564 }
25565 if ($celladj['border_details']['mbw']['RB']) {
25566 $celladj['border_details']['mbw']['RB'] = max($celladj['border_details']['mbw']['RB'], $cbord['border_details']['mbw']['LB']);
25567 }
25568 if ($this->packTableData) { $cells[$i][$j-1]['borderbin'] = $this->_packCellBorder($celladj); }
25569 unset($celladj);
25570 }
25571
25572
25573 // Update maximum cell border width at LRTB edges of table - used for overall table width
25574 if ($j == 0 && $cbord['border_details']['L']['w']) {
25575 $table['max_cell_border_width']['L'] = max($table['max_cell_border_width']['L'],$cbord['border_details']['L']['w']);
25576 }
25577 if (($j == ($numcols-1) || ($j+$ccolsp) == $numcols ) && $cbord['border_details']['R']['w']) {
25578 $table['max_cell_border_width']['R'] = max($table['max_cell_border_width']['R'],$cbord['border_details']['R']['w']);
25579 }
25580 if ($i == 0 && $cbord['border_details']['T']['w']) {
25581 $table['max_cell_border_width']['T'] = max($table['max_cell_border_width']['T'],$cbord['border_details']['T']['w']);
25582 }
25583 if (($i == ($numrows-1) || ($i+$crowsp) == $numrows ) && $cbord['border_details']['B']['w']) {
25584 $table['max_cell_border_width']['B'] = max($table['max_cell_border_width']['B'],$cbord['border_details']['B']['w']);
25585 }
25586 }
25587 /*-- END TABLES-ADVANCED-BORDERS --*/
25588
25589 if ($this->packTableData) { $cell['borderbin'] = $this->_packCellBorder($cbord); }
25590
25591 if ($this->cacheTables) {
25592 $this->_cacheUpdateBorder($cell, $fh, $table['cells'][$i][$j]);
25593 }
25594 unset($cbord );
25595 unset($cell );
25596 }
25597 }
25598 }
25599 if ($this->cacheTables) { fclose($fh); }
25600 unset($cell );
25601 }
25602 // END FIX BORDERS ************************************************************************************
25603
25604
25605 function _reverseTableDir(&$table) {
25606 if ($this->cacheTables) { $fh = fopen($table['cache'], "r+b"); }
25607 $cells = &$table['cells'];
25608 $numcols = $table['nc'];
25609 $numrows = $table['nr'];
25610 for( $i = 0 ; $i < $numrows ; $i++ ) { //Rows
25611 $row = array();
25612 for( $j = ($numcols-1) ; $j >= 0 ; $j-- ) { //Columns
25613 if (isset($cells[$i][$j]) && $cells[$i][$j]) {
25614 if ($this->cacheTables) {
25615 $cell = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
25616 }
25617 else
25618 $cell = &$cells[$i][$j];
25619 $col = $numcols - $j - 1;
25620 if (isset($cell['colspan']) && $cell['colspan'] > 1) { $col -= ($cell['colspan']-1); }
25621 // Nested content
25622 for ($n=0; $n < count($cell['textbuffer']); $n++) {
25623 $t = $cell['textbuffer'][$n][0];
25624 if (substr($t,0,19) == "\xbb\xa4\xactype=nestedtable") {
25625 $objattr = $this->_getObjAttr($t);
25626 $objattr['col'] = $col;
25627 $cell['textbuffer'][$n][0] = "\xbb\xa4\xactype=nestedtable,objattr=".serialize($objattr)."\xbb\xa4\xac";
25628 $this->table[($this->tableLevel+1)][$objattr['nestedcontent']]['nestedpos'][1] = $col;
25629 if ($this->cacheTables) {
25630 $this->_cacheUpdateTxB($cell, $fh, $table['cells'][$i][$j]);
25631 }
25632 }
25633 }
25634 $row[$col] = $cells[$i][$j];
25635 unset($cell);
25636 }
25637 }
25638 for($f=0; $f < $numcols; $f++) {
25639 if (!isset($row[$f])) { $row[$f] = 0; }
25640 }
25641 $table['cells'][$i] = $row;
25642 }
25643 if ($this->cacheTables) { fclose($fh); }
25644 }
25645
25646
25647 function _tableWrite(&$table, $split=false, $startrow=0, $startcol=0, $splitpg=0, $rety = 0){
25648 $level = $table['level'];
25649 $levelid = $table['levelid'];
25650
25651 $cells = &$table['cells'];
25652 $numcols = $table['nc'];
25653 $numrows = $table['nr'];
25654
25655 if ($this->ColActive && $level==1) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
25656
25657 if (!$split || ($startrow==0 && $splitpg==0) || $startrow>0){
25658 // TABLE TOP MARGIN
25659 if ($table['margin']['T']) {
25660 if (!$this->table_rotate && $level==1) {
25661 $this->DivLn($table['margin']['T'],$this->blklvl,true,1); // collapsible
25662 }
25663 else {
25664 $this->y += ($table['margin']['T']);
25665 }
25666 }
25667 // Advance down page by half width of top border
25668 if ($table['borders_separate']) {
25669 if ($startrow>0 && (!isset($table['is_thead']) || count($table['is_thead'])==0))
25670 $adv = $table['border_spacing_V']/2;
25671 else
25672 $adv = $table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V']/2;
25673 }
25674 else {
25675 $adv = $table['max_cell_border_width']['T']/2;
25676 }
25677 if (!$this->table_rotate && $level==1) { $this->DivLn($adv); }
25678 else { $this->y += $adv; }
25679 }
25680
25681 if ($level==1) {
25682 $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['padding_left'] + $this->blk[$this->blklvl]['border_left']['w'];
25683 $x0 = $this->x;
25684 $y0 = $this->y;
25685 $right = $x0 + $this->blk[$this->blklvl]['inner_width'];
25686 $outerfilled = $this->y; // Keep track of how far down the outer DIV bgcolor is painted (NB rowspans)
25687 $this->outerfilled = $this->y;
25688 $this->colsums = array();
25689 }
25690 else {
25691 $x0 = $this->x;
25692 $y0 = $this->y;
25693 $right = $x0 + $table['w'];
25694 }
25695
25696 if ($this->table_rotate) {
25697 $temppgwidth = $this->tbrot_maxw;
25698 $this->PageBreakTrigger = $pagetrigger = $y0 + ($this->blk[$this->blklvl]['inner_width']);
25699 if ($level==1) {
25700 $this->tbrot_y0 = $this->y - $adv - $table['margin']['T'] ;
25701 $this->tbrot_x0 = $this->x;
25702 $this->tbrot_w = $table['w'];
25703 if ($table['borders_separate']) { $this->tbrot_h = $table['margin']['T'] + $table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V']/2; }
25704 else { $this->tbrot_h = $table['margin']['T'] + $table['padding']['T'] + $table['max_cell_border_width']['T']; }
25705 }
25706 }
25707 else {
25708 $this->PageBreakTrigger = $pagetrigger = ($this->h - $this->bMargin);
25709 if ($level==1) {
25710 $temppgwidth = $this->blk[$this->blklvl]['inner_width'];
25711 if (isset($table['a']) and ($table['w'] < $this->blk[$this->blklvl]['inner_width'])) {
25712 if ($table['a']=='C') { $x0 += ((($right-$x0) - $table['w'])/2); }
25713 else if ($table['a']=='R') { $x0 = $right - $table['w']; }
25714 }
25715 }
25716 else {
25717 $temppgwidth = $table['w'];
25718 }
25719 }
25720 if(!isset($table['overflow'])) { $table['overflow'] = null; }
25721 if ($table['overflow']=='hidden' && $level==1 && !$this->table_rotate && !$this->ColActive) {
25722 //Bounding rectangle to clip
25723 $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);
25724 $this->_out($this->tableClipPath);
25725 }
25726 else { $this->tableClipPath = ''; }
25727
25728
25729 if ($table['borders_separate']) { $indent = $table['margin']['L'] + $table['border_details']['L']['w'] + $table['padding']['L'] + $table['border_spacing_H']/2; }
25730 else { $indent = $table['margin']['L'] + $table['max_cell_border_width']['L']/2; }
25731 $x0 += $indent;
25732
25733 $returny = 0;
25734 $lastCol = 0;
25735 $tableheader = array();
25736 $tablefooter = array();
25737 $tableheaderrowheight = 0;
25738 $tablefooterrowheight = 0;
25739 $footery = 0;
25740
25741 // mPD 3.0 Set the Page & Column where table starts
25742 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
25743 $tablestartpage = 'EVEN';
25744 }
25745 else if (($this->mirrorMargins) && (($this->page)%2==1)) { // ODD
25746 $tablestartpage = 'ODD';
25747 }
25748 else { $tablestartpage = ''; }
25749 if ($this->ColActive) { $tablestartcolumn = $this->CurrCol; }
25750 else { $tablestartcolumn = ''; }
25751
25752 if ($this->cacheTables) { $fh = fopen($table['cache'], "r+b"); }
25753 else { $fh = null; }
25754
25755 $y = $h = 0;
25756 for( $i = 0; $i < $numrows ; $i++ ) { //Rows
25757 if ($this->progressBar) { $this->UpdateProgressBar(7,intval(30 + ($i*40/$numrows)),' '); } // *PROGRESS-BAR*
25758 if (isset($table['is_tfoot'][$i]) && $table['is_tfoot'][$i] && $level==1) {
25759 $tablefooterrowheight += $table['hr'][$i];
25760 $tablefooter[$i][0]['trbackground-images'] = $table['trbackground-images'][$i];
25761 $tablefooter[$i][0]['trgradients'] = $table['trgradients'][$i];
25762 $tablefooter[$i][0]['trbgcolor'] = $table['bgcolor'][$i];
25763 for( $j = $startcol ; $j < $numcols ; $j++ ) { //Columns
25764 if (isset($cells[$i][$j]) && $cells[$i][$j]) {
25765 if ($this->cacheTables) {
25766 $cell = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
25767 }
25768 else
25769 $cell = &$cells[$i][$j];
25770 if ($split) {
25771 if ($table['colPg'][$j] != $splitpg) { continue; }
25772 list($x,$w) = $this->_splitTableGetWidth($table, $i, $j, $fh);
25773 $js = $j - $startcol;
25774 }
25775 else {
25776 list($x,$w) = $this->_tableGetWidth($table, $i, $j, $fh);
25777 $js = $j;
25778 }
25779
25780 list($y,$h) = $this->_tableGetHeight($table, $i, $j, $fh);
25781 $x += $x0;
25782 $y += $y0;
25783 //Get info of tfoot ==>> table footer
25784 $tablefooter[$i][$js]['x'] = $x;
25785 $tablefooter[$i][$js]['y'] = $y;
25786 $tablefooter[$i][$js]['h'] = $h;
25787 $tablefooter[$i][$js]['w'] = $w;
25788 if (isset($cell['textbuffer'])) { $tablefooter[$i][$js]['textbuffer'] = $cell['textbuffer']; }
25789 else { $tablefooter[$i][$js]['textbuffer'] = ''; }
25790 $tablefooter[$i][$js]['a'] = $cell['a'];
25791 $tablefooter[$i][$js]['R'] = $cell['R'];
25792 $tablefooter[$i][$js]['va'] = $cell['va'];
25793 $tablefooter[$i][$js]['mih'] = $cell['mih'];
25794 $tablefooter[$i][$js]['gradient'] = $cell['gradient']; // *BACKGROUNDS*
25795 $tablefooter[$i][$js]['background-image'] = $cell['background-image']; // *BACKGROUNDS*
25796 //CELL FILL BGCOLOR
25797 if (!$this->simpleTables){
25798 if ($this->packTableData) {
25799 $c = $this->_unpackCellBorder($cell['borderbin']);
25800 $tablefooter[$i][$js]['border'] = $c['border'];
25801 $tablefooter[$i][$js]['border_details'] = $c['border_details'];
25802 }
25803 else {
25804 $tablefooter[$i][$js]['border'] = $cell['border'];
25805 $tablefooter[$i][$js]['border_details'] = $cell['border_details'];
25806 }
25807 }
25808 else if ($this->simpleTables){
25809 $tablefooter[$i][$js]['border'] = $table['simple']['border'];
25810 $tablefooter[$i][$js]['border_details'] = $table['simple']['border_details'];
25811 }
25812 $tablefooter[$i][$js]['bgcolor'] = $cell['bgcolor'];
25813 $tablefooter[$i][$js]['padding'] = $cell['padding'];
25814 $tablefooter[$i][$js]['rowspan'] = $cell['rowspan'];
25815 $tablefooter[$i][$js]['colspan'] = $cell['colspan'];
25816 }
25817 }
25818 }
25819 }
25820
25821 if ($level==1) { $this->_out('___TABLE___BACKGROUNDS'.date('jY')); }
25822 $tableheaderadj = 0;
25823 $tablefooteradj = 0;
25824
25825 $tablestartpageno = $this->page;
25826
25827 //Draw Table Contents and Borders
25828 for( $i = 0; $i < $numrows ; $i++ ) { //Rows
25829 if ($split && $startrow > 0) {
25830 $thnr = (isset($table['is_thead']) ? count($table['is_thead']) : 0);
25831 if ($i >= $thnr && $i < $startrow) { continue; }
25832 if ($i == $startrow){ $returny = $rety - $tableheaderrowheight; }
25833 }
25834
25835 // Get Maximum row/cell height in row - including rowspan>1 + 1 overlapping
25836 $maxrowheight = $this->_tableGetMaxRowHeight($table, $i, $fh);
25837
25838 $skippage = false;
25839 $newpagestarted = false;
25840 for( $j = $startcol ; $j < $numcols ; $j++ ) { //Columns
25841 if ($split) {
25842 if ($table['colPg'][$j] > $splitpg) { break; }
25843 $lastCol = $j;
25844 }
25845 if (isset($cells[$i][$j]) && $cells[$i][$j]) {
25846 if ($this->cacheTables) {
25847 $cell = $this->_uncacheCell($table['cells'][$i][$j], '', $fh);
25848 }
25849 else
25850 $cell = &$cells[$i][$j];
25851 if ($split) {
25852 $lastCol = $j + (isset($cell['colspan']) ? ($cell['colspan']-1) : 0) ;
25853 list($x,$w) = $this->_splitTableGetWidth($table, $i, $j, $fh);
25854 }
25855 else { list($x,$w) = $this->_tableGetWidth($table, $i, $j, $fh); }
25856
25857 list($y,$h) = $this->_tableGetHeight($table, $i, $j, $fh);
25858 $x += $x0;
25859 $y += $y0;
25860 $y -= $returny;
25861
25862 if ($table['borders_separate']) {
25863 if (!empty($tablefooter) || $i == ($numrows-1) || (isset($cell['rowspan']) && ($i+$cell['rowspan']) == $numrows) || (!isset($cell['rowspan']) && ($i+1) == $numrows) ) {
25864 $extra = $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2;
25865 //$extra = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2;
25866 }
25867 else {
25868 $extra = $table['border_spacing_V']/2;
25869 }
25870 }
25871 else { $extra = $table['max_cell_border_width']['B']/2; }
25872
25873 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 ) {
25874
25875 if (!$skippage) {
25876 $finalSpread = true;
25877 $firstSpread = true;
25878 if ($split) {
25879 for($t=$startcol; $t<$numcols; $t++) {
25880 // Are there more columns to print on a next page?
25881 if ($table['colPg'][$t] > $splitpg) {
25882 $finalSpread = false;
25883 break;
25884 }
25885 }
25886 if ($startcol>0) { $firstSpread = false; }
25887 }
25888
25889 if (($this->keepColumns || !$this->ColActive) && !empty($tablefooter) && $i > 0 ) {
25890 $this->y = $y;
25891 $ya = $this->y;
25892 $this->TableHeaderFooter($tablefooter,$tablestartpage,$tablestartcolumn,'F',$level, $firstSpread, $finalSpread);
25893 if ($this->table_rotate) {
25894 $this->tbrot_h += $this->y - $ya ;
25895 }
25896 $tablefooteradj = $this->y - $ya ;
25897 }
25898 $y -= $y0;
25899 $returny += $y;
25900
25901 $oldcolumn = $this->CurrCol;
25902 if ($this->AcceptPageBreak()) {
25903 $newpagestarted = true;
25904 $this->y = $y + $y0;
25905
25906 // Move down to account for border-spacing or
25907 // extra half border width in case page breaks in middle
25908 if($i>0 && !$this->table_rotate && $level==1 && !$this->ColActive) {
25909 if ($table['borders_separate']) {
25910 $adv = $table['border_spacing_V']/2;
25911 // If table footer
25912 if (($this->keepColumns || !$this->ColActive) && !empty($tablefooter) && $i > 0 ) {
25913 $adv += ($table['padding']['B'] + $table['border_details']['B']['w']);
25914 }
25915 }
25916 else {
25917 $maxbwtop = 0;
25918 $maxbwbottom = 0;
25919 if (!$this->simpleTables){
25920 if (!empty($tablefooter)) { $maxbwbottom = $table['max_cell_border_width']['B']; }
25921 else {
25922 $brow = $i-1;
25923 for( $ctj = 0 ; $ctj < $numcols ; $ctj++ ) {
25924 if (isset($cells[$brow][$ctj]) && $cells[$brow][$ctj]) {
25925 if ($this->cacheTables) {
25926 $cadj = $this->_uncacheCell($table['cells'][$brow][$ctj], '', $fh);
25927 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($cadj['borderbin']);
25928 }
25929 else if ($this->packTableData) {
25930 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($cells[$brow][$ctj]['borderbin']);
25931 }
25932 else {
25933 $bb = $cells[$brow][$ctj]['border_details']['B']['w'];
25934 }
25935 $maxbwbottom = max($maxbwbottom , $bb);
25936 }
25937 }
25938 }
25939 if (!empty($tableheader)) { $maxbwtop = $table['max_cell_border_width']['T']; }
25940 else {
25941 $trow = $i-1;
25942 for( $ctj = 0 ; $ctj < $numcols ; $ctj++ ) {
25943 if (isset($cells[$trow][$ctj]) && $cells[$trow][$ctj]) {
25944 if ($this->cacheTables) {
25945 $cadj = $this->_uncacheCell($table['cells'][$trow][$ctj], '', $fh);
25946 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($cadj['borderbin']);
25947 }
25948 else if ($this->packTableData) {
25949 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($cells[$trow][$ctj]['borderbin']);
25950 }
25951 else {
25952 $bt = $cells[$trow][$ctj]['border_details']['T']['w'];
25953 }
25954 $maxbwtop = max($maxbwtop , $bt);
25955 }
25956 }
25957 }
25958 }
25959 else if ($this->simpleTables){
25960 $maxbwtop = $table['simple']['border_details']['T']['w'];
25961 $maxbwbottom = $table['simple']['border_details']['B']['w'];
25962 }
25963 $adv = $maxbwbottom /2;
25964 }
25965 $this->y += $adv;
25966 }
25967
25968 // Rotated table split over pages - needs this->y for borders/backgrounds
25969 if($i>0 && $this->table_rotate && $level==1) {
25970 // $this->y = $y0 + $this->tbrot_w;
25971 }
25972
25973 if ($this->tableClipPath ) { $this->_out("Q"); }
25974
25975 $bx = $x0;
25976 $by = $y0;
25977
25978 if ($table['borders_separate']) {
25979 $bx -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['border_spacing_H']/2);
25980 if ($tablestartpageno != $this->page) { // IF already broken across a previous pagebreak
25981 $by += $table['max_cell_border_width']['T']/2;
25982 if (empty($tableheader)) { $by -= ($table['border_spacing_V']/2); }
25983 }
25984 else {
25985 $by -= ($table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V']/2);
25986 }
25987 }
25988
25989 else if ($tablestartpageno != $this->page && !empty($tableheader)) { $by += $maxbwtop /2; }
25990
25991 $by -= $tableheaderadj;
25992 $bh = $this->y - $by + $tablefooteradj;
25993 if (!$table['borders_separate']) { $bh -= $adv ; }
25994 if ($split) {
25995 $bw = 0;
25996 for($t=$startcol; $t<$numcols; $t++) {
25997 if ($table['colPg'][$t] == $splitpg) { $bw += $table['wc'][$t]; }
25998 if ($table['colPg'][$t] > $splitpg) { break; }
25999 }
26000 if ($table['borders_separate']) {
26001 if ($firstSpread) {
26002 $bw += $table['padding']['L'] + $table['border_details']['L']['w'] + $table['border_spacing_H'];
26003 }
26004 else {
26005 $bx += ($table['padding']['L'] + $table['border_details']['L']['w']);
26006 $bw += $table['border_spacing_H'];
26007 }
26008 if ($finalSpread) {
26009 $bw += $table['padding']['R'] + $table['border_details']['R']['w']/2 + $table['border_spacing_H'];
26010 }
26011 }
26012 }
26013 else {
26014 $bw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
26015 }
26016
26017 // mPDF 5.4.16
26018 if ($this->splitTableBorderWidth && ($this->keepColumns || !$this->ColActive) && empty($tablefooter) && $i > 0 && $table['border_details']['B']['w']) {
26019 $prevDrawColor = $this->DrawColor;
26020 $lw = $this->LineWidth;
26021 $this->SetLineWidth($this->splitTableBorderWidth);
26022 $this->SetDColor($table['border_details']['B']['c']);
26023 $this->SetLineJoin(0);
26024 $this->SetLineCap(0);
26025 $blx = $bx;
26026 $blw = $bw;
26027 if (!$table['borders_separate']) {
26028 $blx -= ($table['max_cell_border_width']['L']/2);
26029 $blw += ($table['max_cell_border_width']['L']/2 + $table['max_cell_border_width']['R']/2);
26030 }
26031 $this->Line($blx,$this->y+($this->splitTableBorderWidth/2),$blx+$blw,$this->y+($this->splitTableBorderWidth/2));
26032 $this->DrawColor = $prevDrawColor;
26033 $this->_out($this->DrawColor);
26034 $this->SetLineWidth($lw);
26035 $this->SetLineJoin(2);
26036 $this->SetLineCap(2);
26037 }
26038
26039 if (!$this->ColActive && ($i > 0 || $j > 0)) {
26040 if (isset($table['bgcolor'][-1])) {
26041 $color = $this->ConvertColor($table['bgcolor'][-1]);
26042 if ($color) {
26043 if (!$table['borders_separate']) { $bh -= $table['max_cell_border_width']['B']/2; }
26044 $this->tableBackgrounds[$level*9][] = array('gradient'=>false, 'x'=>$bx, 'y'=>$by, 'w'=>$bw, 'h'=>$bh, 'col'=>$color);
26045 }
26046 }
26047
26048 /*-- BACKGROUNDS --*/
26049 if (isset($table['gradient'])) {
26050 $g = $this->grad->parseBackgroundGradient($table['gradient']);
26051 if ($g) {
26052 $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'=>'');
26053 }
26054 }
26055
26056 if (isset($table['background-image'])) {
26057 if ($table['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['background-image']['gradient'] )) {
26058 $g = $this->grad->parseMozGradient( $table['background-image']['gradient'] );
26059 if ($g) {
26060 $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'=>'');
26061 }
26062 }
26063 else {
26064 $image_id = $table['background-image']['image_id'];
26065 $orig_w = $table['background-image']['orig_w'];
26066 $orig_h = $table['background-image']['orig_h'];
26067 $x_pos = $table['background-image']['x_pos'];
26068 $y_pos = $table['background-image']['y_pos'];
26069 $x_repeat = $table['background-image']['x_repeat'];
26070 $y_repeat = $table['background-image']['y_repeat'];
26071 $resize = $table['background-image']['resize'];
26072 $opacity = $table['background-image']['opacity'];
26073 $itype = $table['background-image']['itype'];
26074 $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);
26075 }
26076 }
26077 /*-- END BACKGROUNDS --*/
26078 }
26079
26080 // $this->AcceptPageBreak() has moved tablebuffer to $this->pages content
26081 if ($this->tableBackgrounds) {
26082 $s = $this->PrintTableBackgrounds();
26083 if ($this->bufferoutput) {
26084 $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS'.date('jY').')/', '\\1'."\n".$s."\n", $this->headerbuffer);
26085 $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS'.date('jY').')/', " ", $this->headerbuffer );
26086 }
26087 else {
26088 $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
26089 $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS'.date('jY').')/', " ", $this->pages[$this->page]);
26090 }
26091 $this->tableBackgrounds = array();
26092 }
26093
26094 if ($split) {
26095 if ($i == 0 && $j == 0) { $y0 = -1; }
26096 else if ($finalSpread) {
26097 $splitpg = 0;
26098 $startcol = 0;
26099 $startrow = $i;
26100 }
26101 else {
26102 $splitpg++;
26103 $startcol = $t;
26104 $returny -= $y;
26105 }
26106 return array(false, $startrow, $startcol, $splitpg, $returny, $y0);
26107 }
26108
26109 $this->AddPage($this->CurOrientation);
26110
26111 $this->_out('___TABLE___BACKGROUNDS'.date('jY'));
26112
26113
26114 if ($this->tableClipPath ) { $this->_out($this->tableClipPath); }
26115
26116 // Added to correct for OddEven Margins
26117 $x= $x + $this->MarginCorrection;
26118 $x0= $x0 + $this->MarginCorrection;
26119
26120 // mPDF 5.4.16
26121 if ($this->splitTableBorderWidth && ($this->keepColumns || !$this->ColActive) && empty($tableheader) && $i > 0 && $table['border_details']['T']['w'] ) {
26122 $prevDrawColor = $this->DrawColor;
26123 $lw = $this->LineWidth;
26124 $this->SetLineWidth($this->splitTableBorderWidth);
26125 $this->SetDColor($table['border_details']['T']['c']);
26126 $this->SetLineJoin(0);
26127 $this->SetLineCap(0);
26128 $blx += $this->MarginCorrection;
26129 $this->Line($blx,$this->y-($this->splitTableBorderWidth/2),$blx+$blw,$this->y-($this->splitTableBorderWidth/2));
26130 $this->DrawColor = $prevDrawColor;
26131 $this->_out($this->DrawColor);
26132 $this->SetLineWidth($lw);
26133 $this->SetLineJoin(2);
26134 $this->SetLineCap(2);
26135 }
26136
26137 // Move down to account for half of top border-spacing or
26138 // extra half border width in case page was broken in middle
26139 if($i>0 && !$this->table_rotate && $level==1 && $table['headernrows']==0) {
26140 if ($table['borders_separate']) { $adv = $table['border_spacing_V']/2; }
26141 else {
26142 $maxbwtop = 0;
26143 for( $ctj = 0 ; $ctj < $numcols ; $ctj++ ) {
26144 if (isset($cells[$i][$ctj]) && $cells[$i][$ctj]) {
26145 if (!$this->simpleTables){
26146 if ($this->cacheTables) {
26147 $celltj = $this->_uncacheCell($table['cells'][$i][$ctj], '', $fh);
26148 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($celltj['borderbin']);
26149 }
26150 else if ($this->packTableData) {
26151 list($bt,$br,$bb,$bl) = $this->_getBorderWidths($cells[$i][$ctj]['borderbin']);
26152 }
26153 else {
26154 $bt = $cells[$i][$ctj]['border_details']['T']['w'];
26155 }
26156 $maxbwtop = max($maxbwtop, $bt);
26157 }
26158 else if ($this->simpleTables){
26159 $maxbwtop = max($maxbwtop, $table['simple']['border_details']['T']['w']);
26160 }
26161 }
26162 }
26163 $adv = $maxbwtop /2;
26164 }
26165 $this->y += $adv;
26166 }
26167
26168
26169 if ($this->table_rotate) {
26170 $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'];
26171 if ($table['borders_separate']) { $this->tbrot_h = $table['margin']['T'] + $table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V']/2; }
26172 else { $this->tbrot_h = $table['margin']['T'] + $table['max_cell_border_width']['T'] ; }
26173 $this->tbrot_y0 = $this->y;
26174 $pagetrigger = $y0 - $tableheaderadj + ($this->blk[$this->blklvl]['inner_width']);
26175 }
26176 else {
26177 $pagetrigger = $this->PageBreakTrigger;
26178 }
26179
26180 if ($this->kwt_saved && $level==1) {
26181 $this->kwt_moved = true;
26182 }
26183
26184
26185 // Disable Table header repeat if Keep Block together
26186 if (!$this->keep_block_together && !empty($tableheader)) {
26187 $ya = $this->y;
26188 $this->TableHeaderFooter($tableheader,$tablestartpage,$tablestartcolumn,'H',$level);
26189 if ($this->table_rotate) {
26190 $this->tbrot_h = $this->y - $ya ;
26191 }
26192 $tableheaderadj = $this->y - $ya ;
26193 }
26194
26195 else if ($i==0 && !$this->keep_block_together && !$this->table_rotate && $level==1 && !$this->ColActive) {
26196 // Advance down page
26197 if ($table['borders_separate']) { $adv = $table['border_spacing_V']/2 + $table['border_details']['T']['w'] + $table['padding']['T']; }
26198 else { $adv = $table['max_cell_border_width']['T'] /2 ; }
26199 if ($adv) {
26200 if ($this->table_rotate) {
26201 $this->y += ($adv);
26202 }
26203 else {
26204 $this->DivLn($adv,$this->blklvl,true);
26205 }
26206 }
26207 }
26208
26209 $outerfilled = 0;
26210 $y = $y0 = $this->y;
26211 }
26212
26213 /*-- COLUMNS --*/
26214 // COLS
26215 // COLUMN CHANGE
26216 if ($this->CurrCol != $oldcolumn) {
26217 // Added to correct for Columns
26218 $x += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
26219 $x0 += $this->ChangeColumn * ($this->ColWidth+$this->ColGap);
26220 if ($this->CurrCol == 0) { // just added a page - possibly with tableheader
26221 $y0 = $this->y; // this->y0 is global used by Columns - $y0 is internal to tablewrite
26222 }
26223 else {
26224 $y0 = $this->y0; // this->y0 is global used by Columns - $y0 is internal to tablewrite
26225 }
26226 $y = $y0;
26227 $outerfilled = 0;
26228 if ($this->CurrCol != 0 && ($this->keepColumns && $this->ColActive) && !empty($tableheader) && $i > 0 ) {
26229 $this->x = $x;
26230 $this->y = $y;
26231 $this->TableHeaderFooter($tableheader,$tablestartpage,$tablestartcolumn,'H',$level);
26232 $y0 = $y=$this->y;
26233 }
26234 }
26235 /*-- END COLUMNS --*/
26236 }
26237 $skippage = true;
26238 }
26239
26240 $this->x = $x;
26241 $this->y = $y;
26242
26243 if ($this->kwt_saved && $level==1) {
26244 $this->printkwtbuffer();
26245 $x0 = $x = $this->x;
26246 $y0 = $y = $this->y;
26247 $this->kwt_moved = false;
26248 $this->kwt_saved = false;
26249 }
26250
26251
26252 // Set the Page & Column where table actually starts
26253 if ($i==0 && $j==0 && $level==1) {
26254 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
26255 $tablestartpage = 'EVEN';
26256 }
26257 else if (($this->mirrorMargins) && (($this->page)%2==1)) { // ODD
26258 $tablestartpage = 'ODD';
26259 }
26260 else { $tablestartpage = ''; }
26261 $tablestartpageno = $this->page;
26262 if ($this->ColActive) { $tablestartcolumn = $this->CurrCol; } // *COLUMNS*
26263 }
26264
26265
26266 //ALIGN
26267 $align = $cell['a'];
26268
26269
26270 /*-- COLUMNS --*/
26271 // If outside columns, this is done in PaintDivBB
26272 if ($this->ColActive) {
26273 //OUTER FILL BGCOLOR of DIVS
26274 if ($this->blklvl > 0 && ($j==0) && !$this->table_rotate && $level==1) {
26275 $firstblockfill = $this->GetFirstBlockFill();
26276 if ($firstblockfill && $this->blklvl >= $firstblockfill) {
26277 $divh = $maxrowheight;
26278 // Last row
26279 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)))) { // mPDF 5.6.54
26280 if ($table['borders_separate']) {
26281 $adv = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2;
26282 }
26283 else {
26284 $adv = $table['margin']['B'] + $table['max_cell_border_width']['B']/2;
26285 }
26286 $divh += $adv; //last row: fill bottom half of bottom border (y advanced at end)
26287 }
26288
26289 if (($this->y + $divh) > $outerfilled ) { // if not already painted by previous rowspan
26290 $bak_x = $this->x;
26291 $bak_y = $this->y;
26292 if ($outerfilled > $this->y) {
26293 $divh = ($this->y + $divh) - $outerfilled;
26294 $this->y = $outerfilled;
26295 }
26296
26297 $this->DivLn($divh,-3,false);
26298 $outerfilled = $this->y + $divh;
26299 // Reset current block fill
26300 $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
26301 if ($bcor ) $this->SetFColor($bcor);
26302 $this->x = $bak_x;
26303 $this->y = $bak_y;
26304 }
26305 }
26306 }
26307 }
26308
26309
26310 //TABLE BACKGROUND FILL BGCOLOR - for cellSpacing
26311 if ($this->ColActive) {
26312 if ($table['borders_separate']) {
26313 $fill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0;
26314 if ($fill) {
26315 $color = $this->ConvertColor($fill);
26316 if ($color) {
26317 $xadj = ($table['border_spacing_H']/2);
26318 $yadj = ($table['border_spacing_V']/2);
26319 $wadj = $table['border_spacing_H'];
26320 $hadj = $table['border_spacing_V'];
26321 if ($i == 0) { // Top
26322 $yadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
26323 $hadj += $table['padding']['T'] + $table['border_details']['T']['w'] ;
26324 }
26325 if ($j == 0) { // Left
26326 $xadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
26327 $wadj += $table['padding']['L'] + $table['border_details']['L']['w'] ;
26328 }
26329 if ($i == ($numrows-1) || (isset($cell['rowspan']) && ($i+$cell['rowspan']) == $numrows) || (!isset($cell['rowspan']) && ($i+1) == $numrows)) { // Bottom
26330 $hadj += $table['padding']['B'] + $table['border_details']['B']['w'] ;
26331 }
26332 if ($j == ($numcols-1) || (isset($cell['colspan']) && ($j+$cell['colspan']) == $numcols) || (!isset($cell['colspan']) && ($j+1) == $numcols)) { // Right
26333 $wadj += $table['padding']['R'] + $table['border_details']['R']['w'] ;
26334 }
26335 $this->SetFColor($color);
26336 $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F');
26337 }
26338 }
26339 }
26340 }
26341 /*-- END COLUMNS --*/
26342
26343 if ($table['empty_cells']!='hide' || !empty($cell['textbuffer']) || (isset($cell['nestedcontent']) && $cell['nestedcontent']) || !$table['borders_separate'] ) { $paintcell = true; }
26344 else { $paintcell = false; }
26345
26346 //Set Borders
26347 $bord = 0;
26348 $bord_det = array();
26349
26350 if (!$this->simpleTables){
26351 if ($this->packTableData) {
26352 if ($cell['borderbin']) {
26353 $c = $this->_unpackCellBorder($cell['borderbin']);
26354 $bord = $c['border'];
26355 $bord_det = $c['border_details'];
26356 }
26357 }
26358 else if ($cell['border']) {
26359 $bord = $cell['border'];
26360 $bord_det = $cell['border_details'];
26361 }
26362 }
26363 else if ($this->simpleTables){
26364 if ($table['simple']['border']) {
26365 $bord = $table['simple']['border'];
26366 $bord_det = $table['simple']['border_details'];
26367 }
26368 }
26369
26370 //TABLE ROW OR CELL FILL BGCOLOR
26371 $fill = 0;
26372 if (isset($cell['bgcolor']) && $cell['bgcolor'] && $cell['bgcolor']!='transparent') {
26373 $fill = $cell['bgcolor'];
26374 $leveladj = 6;
26375 }
26376 else if (isset($table['bgcolor'][$i]) && $table['bgcolor'][$i] && $table['bgcolor'][$i]!='transparent') { // Row color
26377 $fill = $table['bgcolor'][$i];
26378 $leveladj = 3;
26379 }
26380 if ($fill && $paintcell) {
26381 $color = $this->ConvertColor($fill);
26382 if ($color) {
26383 if ($table['borders_separate']) {
26384 if ($this->ColActive) {
26385 $this->SetFColor($color);
26386 $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');
26387 }
26388 else {
26389 $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);
26390 }
26391 }
26392 else {
26393 if ($this->ColActive) {
26394 $this->SetFColor($color);
26395 $this->Rect($x, $y, $w, $h, 'F');
26396 }
26397 else {
26398 $this->tableBackgrounds[$level*9+$leveladj][] = array('gradient'=>false, 'x'=>$x, 'y'=>$y, 'w'=>$w, 'h'=>$h, 'col'=>$color);
26399 }
26400 }
26401 }
26402 }
26403
26404 /*-- BACKGROUNDS --*/
26405 if (isset($cell['gradient']) && $cell['gradient'] && $paintcell){
26406 $g = $this->grad->parseBackgroundGradient($cell['gradient']);
26407 if ($g) {
26408 if ($table['borders_separate']) {
26409 $px = $x+ ($table['border_spacing_H']/2);
26410 $py = $y+ ($table['border_spacing_V']/2);
26411 $pw = $w- $table['border_spacing_H'];
26412 $ph = $h- $table['border_spacing_V'];
26413 }
26414 else {
26415 $px = $x;
26416 $py = $y;
26417 $pw = $w;
26418 $ph = $h;
26419 }
26420 if ($this->ColActive) {
26421 $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
26422 }
26423 else {
26424 $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'=>'');
26425 }
26426 }
26427 }
26428
26429 if (isset($cell['background-image']) && $paintcell) {
26430 if ($cell['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $cell['background-image']['gradient'] )) {
26431 $g = $this->grad->parseMozGradient( $cell['background-image']['gradient'] );
26432 if ($g) {
26433 if ($table['borders_separate']) {
26434 $px = $x+ ($table['border_spacing_H']/2);
26435 $py = $y+ ($table['border_spacing_V']/2);
26436 $pw = $w- $table['border_spacing_H'];
26437 $ph = $h- $table['border_spacing_V'];
26438 }
26439 else {
26440 $px = $x;
26441 $py = $y;
26442 $pw = $w;
26443 $ph = $h;
26444 }
26445 if ($this->ColActive) {
26446 $this->grad->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
26447 }
26448 else {
26449 $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'=>'');
26450 }
26451 }
26452 }
26453 else if ($cell['background-image']['image_id']) { // Background pattern
26454 $n = count($this->patterns)+1;
26455 if ($table['borders_separate']) {
26456 $px = $x+ ($table['border_spacing_H']/2);
26457 $py = $y+ ($table['border_spacing_V']/2);
26458 $pw = $w- $table['border_spacing_H'];
26459 $ph = $h- $table['border_spacing_V'];
26460 }
26461 else {
26462 $px = $x;
26463 $py = $y;
26464 $pw = $w;
26465 $ph = $h;
26466 }
26467 if ($this->ColActive) {
26468 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']);
26469 $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);
26470 if ($cell['background-image']['opacity']>0 && $cell['background-image']['opacity']<1) { $opac = $this->SetAlpha($cell['background-image']['opacity'],'Normal',true); }
26471 else { $opac = ''; }
26472 $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));
26473 }
26474 else {
26475 $image_id = $cell['background-image']['image_id'];
26476 $orig_w = $cell['background-image']['orig_w'];
26477 $orig_h = $cell['background-image']['orig_h'];
26478 $x_pos = $cell['background-image']['x_pos'];
26479 $y_pos = $cell['background-image']['y_pos'];
26480 $x_repeat = $cell['background-image']['x_repeat'];
26481 $y_repeat = $cell['background-image']['y_repeat'];
26482 $resize = $cell['background-image']['resize'];
26483 $opacity = $cell['background-image']['opacity'];
26484 $itype = $cell['background-image']['itype'];
26485 $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);
26486 }
26487 }
26488 }
26489 /*-- END BACKGROUNDS --*/
26490
26491 if (isset($cell['colspan']) && $cell['colspan']>1) { $ccolsp = $cell['colspan']; }
26492 else { $ccolsp = 1; }
26493 if (isset($cell['rowspan']) && $cell['rowspan']>1) { $crowsp = $cell['rowspan']; }
26494 else { $crowsp = 1; }
26495
26496
26497 // but still need to do this for repeated headers...
26498 if (!$table['borders_separate'] && $this->tabletheadjustfinished && !$this->simpleTables){
26499 if (isset($table['topntail']) && $table['topntail']) {
26500 $bord_det['T'] = $this->border_details($table['topntail']);
26501 $bord_det['T']['w'] /= $this->shrin_k;
26502 $this->setBorder($bord, _BORDER_TOP);
26503 }
26504 if (isset($table['thead-underline']) && $table['thead-underline']) {
26505 $bord_det['T'] = $this->border_details($table['thead-underline']);
26506 $bord_det['T']['w'] /= $this->shrin_k;
26507 $this->setBorder($bord, _BORDER_TOP);
26508 }
26509 }
26510
26511
26512 //Get info of first row ==>> table header
26513 //Use > 1 row if THEAD
26514 if (isset($table['is_thead'][$i]) && $table['is_thead'][$i] && $level==1) {
26515 if ($j==0) $tableheaderrowheight += $table['hr'][$i];
26516 $tableheader[$i][0]['trbackground-images'] = (isset($table['trbackground-images'][$i]) ? $table['trbackground-images'][$i] : null);
26517 $tableheader[$i][0]['trgradients'] = (isset($table['trgradients'][$i]) ? $table['trgradients'][$i] : null);
26518 $tableheader[$i][0]['trbgcolor'] = (isset($table['bgcolor'][$i]) ? $table['bgcolor'][$i] : null);
26519 $tableheader[$i][$j]['x'] = $x;
26520 $tableheader[$i][$j]['y'] = $y;
26521 $tableheader[$i][$j]['h'] = $h;
26522 $tableheader[$i][$j]['w'] = $w;
26523 if (isset($cell['textbuffer'])) { $tableheader[$i][$j]['textbuffer'] = $cell['textbuffer']; }
26524 else { $tableheader[$i][$j]['textbuffer'] = ''; }
26525 $tableheader[$i][$j]['a'] = $cell['a'];
26526 $tableheader[$i][$j]['R'] = $cell['R'];
26527
26528 $tableheader[$i][$j]['va'] = $cell['va'];
26529 $tableheader[$i][$j]['mih'] = $cell['mih'];
26530 $tableheader[$i][$j]['gradient'] = (isset($cell['gradient']) ? $cell['gradient'] : null); // *BACKGROUNDS*
26531 $tableheader[$i][$j]['background-image'] = (isset($cell['background-image']) ? $cell['background-image'] : null); // *BACKGROUNDS*
26532 $tableheader[$i][$j]['rowspan'] = (isset($cell['rowspan']) ? $cell['rowspan'] : null);
26533 $tableheader[$i][$j]['colspan'] = (isset($cell['colspan']) ? $cell['colspan'] : null);
26534 $tableheader[$i][$j]['bgcolor'] = $cell['bgcolor'];
26535
26536 if (!$this->simpleTables){
26537 $tableheader[$i][$j]['border'] = $bord;
26538 $tableheader[$i][$j]['border_details'] = $bord_det;
26539 }
26540 else if ($this->simpleTables){
26541 $tableheader[$i][$j]['border'] = $table['simple']['border'];
26542 $tableheader[$i][$j]['border_details'] = $table['simple']['border_details'];
26543 }
26544 $tableheader[$i][$j]['padding'] = $cell['padding'];
26545 }
26546
26547 // CELL BORDER
26548 if ($bord || $bord_det) {
26549 if ($table['borders_separate'] && $paintcell) {
26550 $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']);
26551 }
26552 else if (!$table['borders_separate']) {
26553 $this->_tableRect($x, $y, $w, $h, $bord, $bord_det, true, $table['borders_separate']); // true causes buffer
26554 }
26555
26556 }
26557
26558 //VERTICAL ALIGN
26559 if ($cell['R'] && INTVAL($cell['R']) > 0 && INTVAL($cell['R']) < 90 && isset($cell['va']) && $cell['va']!='B') { $cell['va']='B';}
26560 if (!isset($cell['va']) || $cell['va']=='M') $this->y += ($h-$cell['mih'])/2;
26561 elseif (isset($cell['va']) && $cell['va']=='B') $this->y += $h-$cell['mih'];
26562
26563 // NESTED CONTENT
26564
26565 // TEXT (and nested tables)
26566 $this->divalign=$align;
26567
26568 $this->divwidth=$w;
26569 if (!empty($cell['textbuffer'])) {
26570 if ($level==1) {
26571 if (isset($table['is_tfoot'][$i]) && $table['is_tfoot'][$i]) {
26572 if (preg_match('/{colsum([0-9]*)[_]*}/', $cell['textbuffer'][0][0], $m)) {
26573 $rep = sprintf("%01.".intval($m[1])."f", $this->colsums[$j]);
26574 $cell['textbuffer'][0][0] = preg_replace('/{colsum[0-9_]*}/', $rep ,$cell['textbuffer'][0][0]);
26575 }
26576 }
26577 else if (!isset($table['is_thead'][$i])) { $this->colsums[$j] += floatval(preg_replace('/^[^0-9\.\,]*/','',$cell['textbuffer'][0][0])); } // mPDF 5.6.66
26578 }
26579 $opy = $this->y;
26580 // mPDF ITERATION
26581 if ($this->iterationCounter) {
26582 foreach($cell['textbuffer'] AS $k=>$t) {
26583 if (preg_match('/{iteration ([a-zA-Z0-9_]+)}/',$t[0], $m)) {
26584 $vname = '__'.$m[1].'_';
26585 if (!isset($this->$vname)) { $this->$vname = 1; }
26586 else { $this->$vname++; }
26587 $cell['textbuffer'][$k][0] = preg_replace('/{iteration '.$m[1].'}/', $this->$vname, $cell['textbuffer'][$k][0]);
26588 }
26589 }
26590 }
26591
26592
26593 if ($cell['R']) {
26594 $cellPtSize = $cell['textbuffer'][0][11] / $this->shrin_k;
26595 if (!$cellPtSize) { $cellPtSize = $this->default_font_size; }
26596 $cellFontHeight = ($cellPtSize/_MPDFK);
26597 $opx = $this->x;
26598 $angle = INTVAL($cell['R']);
26599 // Only allow 45 to 89 degrees (when bottom-aligned) or exactly 90 or -90
26600 if ($angle > 90) { $angle = 90; }
26601 else if ($angle > 0 && $angle <45) { $angle = 45; }
26602 else if ($angle < 0) { $angle = -90; }
26603 $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight);
26604 if (isset($cell['a']) && $cell['a']=='R') {
26605 $this->x += ($w) + ($offset) - ($cellFontHeight/3) - ($cell['padding']['R'] + ($table['border_spacing_H']/2));
26606 }
26607 else if (!isset($cell['a']) || $cell['a']=='C') {
26608 $this->x += ($w/2) + ($offset);
26609 }
26610 else {
26611 $this->x += ($offset) + ($cellFontHeight/3)+($cell['padding']['L'] +($table['border_spacing_H']/2));
26612 }
26613 $str = '';
26614 foreach($cell['textbuffer'] AS $t) { $str .= $t[0].' '; }
26615 $str = trim($str);
26616 if (!isset($cell['va']) || $cell['va']=='M') {
26617 $this->y -= ($h-$cell['mih'])/2; //Undo what was added earlier VERTICAL ALIGN
26618 if ($angle > 0) { $this->y += (($h-$cell['mih'])/2) + $cell['padding']['T'] + ($cell['mih']-($cell['padding']['T'] + $cell['padding']['B'])); }
26619 else if ($angle < 0) { $this->y += (($h-$cell['mih'])/2)+ ($cell['padding']['T'] + ($table['border_spacing_V']/2)); }
26620 }
26621 elseif (isset($cell['va']) && $cell['va']=='B') {
26622 $this->y -= $h-$cell['mih']; //Undo what was added earlier VERTICAL ALIGN
26623 if ($angle > 0) { $this->y += $h-($cell['padding']['B'] + ($table['border_spacing_V']/2)); }
26624 else if ($angle < 0) { $this->y += $h-$cell['mih'] + ($cell['padding']['T'] + ($table['border_spacing_V']/2)); }
26625 }
26626 elseif (isset($cell['va']) && $cell['va']=='T') {
26627 if ($angle > 0) { $this->y += $cell['mih']-($cell['padding']['B'] + ($table['border_spacing_V']/2)); }
26628 else if ($angle < 0) { $this->y += ($cell['padding']['T'] + ($table['border_spacing_V']/2)); }
26629 }
26630 $this->Rotate($angle,$this->x,$this->y);
26631 $s_fs = $this->FontSizePt;
26632 $s_f = $this->FontFamily;
26633 $s_st = $this->FontStyle;
26634 if (!empty($cell['textbuffer'][0][3])) { //Font Color
26635 $cor = $cell['textbuffer'][0][3];
26636 $this->SetTColor($cor);
26637 }
26638 $s_str = $this->strike;
26639 $this->strike = $cell['textbuffer'][0][8]; //Strikethrough
26640 $this->SetFont($cell['textbuffer'][0][4],$cell['textbuffer'][0][2],$cellPtSize,true,true);
26641 $this->Text($this->x,$this->y,$str);
26642 $this->Rotate(0);
26643 $this->SetFont($s_f,$s_st,$s_fs,true,true);
26644 $this->SetTColor(0);
26645 $this->strike = $s_str;
26646 $this->x = $opx;
26647 }
26648 else {
26649
26650 if (!$this->simpleTables){
26651 if ($bord_det) {
26652 $btlw = $bord_det['L']['w'];
26653 $btrw = $bord_det['R']['w'];
26654 $bttw = $bord_det['T']['w'];
26655 }
26656 else {
26657 $btlw = 0;
26658 $btrw = 0;
26659 $bttw = 0;
26660 }
26661 if ($table['borders_separate']) {
26662 $xadj = $btlw + $cell['padding']['L'] +($table['border_spacing_H']/2);
26663 $wadj = $btlw + $btrw + $cell['padding']['L'] +$cell['padding']['R'] + $table['border_spacing_H'];
26664 $yadj = $bttw + $cell['padding']['T'] + ($table['border_spacing_H']/2);
26665 }
26666 else {
26667 $xadj = $btlw/2 + $cell['padding']['L'];
26668 $wadj = ($btlw + $btrw)/2 + $cell['padding']['L'] + $cell['padding']['R'];
26669 $yadj = $bttw/2 + $cell['padding']['T'];
26670 }
26671 }
26672 else if ($this->simpleTables){
26673 if ($table['borders_separate']) { // NB twice border width
26674 $xadj = $table['simple']['border_details']['L']['w'] + $cell['padding']['L'] +($table['border_spacing_H']/2);
26675 $wadj = $table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w'] + $cell['padding']['L'] +$cell['padding']['R'] + $table['border_spacing_H'];
26676 $yadj = $table['simple']['border_details']['T']['w'] + $cell['padding']['T'] + ($table['border_spacing_H']/2);
26677 }
26678 else {
26679 $xadj = $table['simple']['border_details']['L']['w']/2 + $cell['padding']['L'];
26680 $wadj = ($table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w'])/2 + $cell['padding']['L'] + $cell['padding']['R'];
26681 $yadj = $table['simple']['border_details']['T']['w']/2 + $cell['padding']['T'];
26682 }
26683 }
26684 // mPDF 5.6.13
26685 $this->decimal_offset = 0;
26686 if(substr($cell['a'],0,1) == 'D') {
26687 if ($cell['colspan'] > 1) { $this->divalign = $c['a'] = substr($cell['a'],2,1); }
26688 else {
26689 $smax = $table['decimal_align'][$j]['maxs0'];
26690 $d_content = $table['decimal_align'][$j]['maxs0'] + $table['decimal_align'][$j]['maxs1'];
26691 $this->decimal_offset = $smax;
26692 $extra = ($w - $d_content - $wadj);
26693 if ($extra > 0) {
26694 if(substr($cell['a'],2,1) == 'R') { $this->decimal_offset += $extra; }
26695 else if(substr($cell['a'],2,1) == 'C') { $this->decimal_offset += ($extra)/2; }
26696 }
26697 }
26698 }
26699 $this->divwidth=$w-$wadj;
26700 if ($this->divwidth == 0) { $this->divwidth = 0.0001; }
26701 $this->x += $xadj;
26702 $this->y += $yadj;
26703 $this->printbuffer($cell['textbuffer'],'',true);
26704 }
26705 $this->y = $opy;
26706 }
26707
26708 /*-- BACKGROUNDS --*/
26709 if (!$this->ColActive) {
26710 if (isset($table['trgradients'][$i]) && ($j==0 || $table['borders_separate'])) {
26711 $g = $this->grad->parseBackgroundGradient($table['trgradients'][$i]);
26712 if ($g) {
26713 $gx = $x0;
26714 $gy = $y;
26715 $gh = $h;
26716 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
26717 if ($table['borders_separate']) {
26718 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
26719 $s = '';
26720 $clx = $x+ ($table['border_spacing_H']/2);
26721 $cly = $y+ ($table['border_spacing_V']/2);
26722 $clw = $w- $table['border_spacing_H'];
26723 $clh = $h- $table['border_spacing_V'];
26724 // Set clipping path
26725 $s = ' q 0 w '; // Line width=0
26726 $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
26727 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
26728 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
26729 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
26730 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
26731 $s .= ' W n '; // Ends path no-op & Sets the clipping path
26732 $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);
26733 }
26734 else {
26735 $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'=>'');
26736 }
26737 }
26738 }
26739 if (isset($table['trbackground-images'][$i]) && ($j==0 || $table['borders_separate'])) {
26740 if ($table['trbackground-images'][$i]['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['trbackground-images'][$i]['gradient'] )) {
26741 $g = $this->grad->parseMozGradient( $table['trbackground-images'][$i]['gradient'] );
26742 if ($g) {
26743 $gx = $x0;
26744 $gy = $y;
26745 $gh = $h;
26746 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
26747 if ($table['borders_separate']) {
26748 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
26749 $s = '';
26750 $clx = $x+ ($table['border_spacing_H']/2);
26751 $cly = $y+ ($table['border_spacing_V']/2);
26752 $clw = $w- $table['border_spacing_H'];
26753 $clh = $h- $table['border_spacing_V'];
26754 // Set clipping path
26755 $s = ' q 0 w '; // Line width=0
26756 $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL before the arc
26757 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
26758 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
26759 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
26760 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
26761 $s .= ' W n '; // Ends path no-op & Sets the clipping path
26762 $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);
26763 }
26764 else {
26765 $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'=>'');
26766 }
26767 }
26768 }
26769 else {
26770 $image_id = $table['trbackground-images'][$i]['image_id'];
26771 $orig_w = $table['trbackground-images'][$i]['orig_w'];
26772 $orig_h = $table['trbackground-images'][$i]['orig_h'];
26773 $x_pos = $table['trbackground-images'][$i]['x_pos'];
26774 $y_pos = $table['trbackground-images'][$i]['y_pos'];
26775 $x_repeat = $table['trbackground-images'][$i]['x_repeat'];
26776 $y_repeat = $table['trbackground-images'][$i]['y_repeat'];
26777 $resize = $table['trbackground-images'][$i]['resize'];
26778 $opacity = $table['trbackground-images'][$i]['opacity'];
26779 $itype = $table['trbackground-images'][$i]['itype'];
26780 $clippath = '';
26781 $gx = $x0;
26782 $gy = $y;
26783 $gh = $h;
26784 $gw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
26785 if ($table['borders_separate']) {
26786 $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
26787 $s = '';
26788 $clx = $x + ($table['border_spacing_H']/2);
26789 $cly = $y + ($table['border_spacing_V']/2);
26790 $clw = $w - $table['border_spacing_H'];
26791 $clh = $h - $table['border_spacing_V'];
26792 // Set clipping path
26793 $s = ' q 0 w '; // Line width=0
26794 $s .= sprintf('%.3F %.3F m ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // start point TL
26795 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BL
26796 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly+$clh))*_MPDFK); // line to BR
26797 $s .= sprintf('%.3F %.3F l ', ($clx+$clw)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TR
26798 $s .= sprintf('%.3F %.3F l ', ($clx)*_MPDFK, ($this->h-($cly))*_MPDFK); // line to TL
26799 $s .= ' W n '; // Ends path no-op & Sets the clipping path
26800 $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);
26801 }
26802 else {
26803 $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);
26804 }
26805 }
26806 }
26807 }
26808
26809 /*-- END BACKGROUNDS --*/
26810
26811 // TABLE BORDER - if separate
26812 if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) {
26813 $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H']/2);
26814 $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H']/2);
26815 $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V']/2);
26816 $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V']/2);
26817 $tbx = $x;
26818 $tby = $y;
26819 $tbw = $w;
26820 $tbh = $h;
26821 $tab_bord = 0;
26822
26823 $corner = '';
26824 if ($i == 0) { // Top
26825 $tby -= $halfspaceT + ($table['border_details']['T']['w']/2);
26826 $tbh += $halfspaceT + ($table['border_details']['T']['w']/2);
26827 $this->setBorder($tab_bord , _BORDER_TOP);
26828 $corner .= 'T';
26829 }
26830 if ($i == ($numrows-1) || (isset($cell['rowspan']) && ($i+$cell['rowspan']) == $numrows)) { // Bottom
26831 $tbh += $halfspaceB + ($table['border_details']['B']['w']/2);
26832 $this->setBorder($tab_bord , _BORDER_BOTTOM);
26833 $corner .= 'B';
26834 }
26835 if ($j == 0) { // Left
26836 $tbx -= $halfspaceL + ($table['border_details']['L']['w']/2);
26837 $tbw += $halfspaceL + ($table['border_details']['L']['w']/2);
26838 $this->setBorder($tab_bord , _BORDER_LEFT);
26839 $corner .= 'L';
26840 }
26841 if ($j == ($numcols-1) || (isset($cell['colspan']) && ($j+$cell['colspan']) == $numcols)) { // Right
26842 $tbw += $halfspaceR + ($table['border_details']['R']['w']/2);
26843 $this->setBorder($tab_bord , _BORDER_RIGHT);
26844 $corner .= 'R';
26845 }
26846 $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'] );
26847 }
26848
26849 unset($cell );
26850 //Reset values
26851 $this->Reset();
26852
26853 }//end of (if isset(cells)...)
26854 }// end of columns
26855
26856 $newpagestarted = false;
26857 $this->tabletheadjustfinished = false;
26858
26859 if ($this->ColActive && $i < $numrows-1 && $level==1) { $this->breakpoints[$this->CurrCol][] = $y + $h; } // *COLUMNS*
26860
26861 /*-- COLUMNS --*/
26862 if ($this->ColActive) {
26863 if (count($this->cellBorderBuffer)) { $this->printcellbuffer(); }
26864 }
26865 /*-- END COLUMNS --*/
26866
26867 if ($i == $numrows-1) { $this->y = $y + $h; } //last row jump (update this->y position)
26868 if ($this->table_rotate && $level==1) {
26869 $this->tbrot_h += $h;
26870 }
26871
26872
26873
26874 }// end of rows
26875
26876 if ($this->progressBar) { $this->UpdateProgressBar(7,70,' '); } // *PROGRESS-BAR*
26877
26878 if (count($this->cellBorderBuffer)) { $this->printcellbuffer(); }
26879
26880
26881 if ($this->tableClipPath ) { $this->_out("Q"); }
26882 $this->tableClipPath = '';
26883
26884 // Advance down page by half width of bottom border
26885 if ($table['borders_separate']) { $this->y += $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2; }
26886 else { $this->y += $table['max_cell_border_width']['B']/2; }
26887
26888 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; }
26889 else if ($level==1) { $this->tbrot_h += $table['margin']['B'] + $table['max_cell_border_width']['B']/2; }
26890
26891 $bx = $x0;
26892 $by = $y0;
26893 if ($table['borders_separate']) {
26894 $bx -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['border_spacing_H']/2);
26895 if ($tablestartpageno != $this->page) { // IF broken across page
26896 $by += $table['max_cell_border_width']['T']/2;
26897 if (empty($tableheader)) { $by -= ($table['border_spacing_V']/2); }
26898 }
26899 else if ($split && $startrow > 0 && empty($tableheader)) {
26900 $by -= ($table['border_spacing_V']/2);
26901 }
26902 else {
26903 $by -= ($table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V']/2);
26904 }
26905 }
26906 else if ($tablestartpageno != $this->page && !empty($tableheader)) { $by += $maxbwtop /2; }
26907 $by -= $tableheaderadj;
26908 $bh = $this->y - $by;
26909 if (!$table['borders_separate']) { $bh -= $table['max_cell_border_width']['B']/2; }
26910
26911 if ($split) {
26912 $bw = 0;
26913 $finalSpread = true;
26914 for($t=$startcol; $t<$numcols; $t++) {
26915 if ($table['colPg'][$t] == $splitpg) { $bw += $table['wc'][$t]; }
26916 if ($table['colPg'][$t] > $splitpg) { $finalSpread = false; break; }
26917 }
26918 if ($startcol==0) { $firstSpread = true; }
26919 else { $firstSpread = false; }
26920 if ($table['borders_separate']) {
26921 $bw += $table['border_spacing_H'];
26922 if ($firstSpread) {
26923 $bw += $table['padding']['L'] + $table['border_details']['L']['w'];
26924 }
26925 else {
26926 $bx += ($table['padding']['L'] + $table['border_details']['L']['w']);
26927 }
26928 if ($finalSpread) {
26929 $bw += $table['padding']['R'] + $table['border_details']['R']['w'];
26930 }
26931 }
26932 }
26933 else {
26934 $bw = $table['w'] - ($table['max_cell_border_width']['L']/2) - ($table['max_cell_border_width']['R']/2) - $table['margin']['L'] - $table['margin']['R'];
26935 }
26936
26937 if (!$this->ColActive) {
26938 if (isset($table['bgcolor'][-1])) {
26939 $color = $this->ConvertColor($table['bgcolor'][-1]);
26940 if ($color) {
26941 $this->tableBackgrounds[$level*9][] = array('gradient'=>false, 'x'=>$bx, 'y'=>$by, 'w'=>$bw, 'h'=>$bh, 'col'=>$color);
26942 }
26943 }
26944
26945 /*-- BACKGROUNDS --*/
26946 if (isset($table['gradient'])) {
26947 $g = $this->grad->parseBackgroundGradient($table['gradient']);
26948 if ($g) {
26949 $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'=>'');
26950 }
26951 }
26952
26953 if (isset($table['background-image'])) {
26954 if ($table['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['background-image']['gradient'] )) {
26955 $g = $this->grad->parseMozGradient( $table['background-image']['gradient'] );
26956 if ($g) {
26957 $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'=>'');
26958 }
26959 }
26960 else {
26961 $image_id = $table['background-image']['image_id'];
26962 $orig_w = $table['background-image']['orig_w'];
26963 $orig_h = $table['background-image']['orig_h'];
26964 $x_pos = $table['background-image']['x_pos'];
26965 $y_pos = $table['background-image']['y_pos'];
26966 $x_repeat = $table['background-image']['x_repeat'];
26967 $y_repeat = $table['background-image']['y_repeat'];
26968 $resize = $table['background-image']['resize'];
26969 $opacity = $table['background-image']['opacity'];
26970 $itype = $table['background-image']['itype'];
26971 $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);
26972 }
26973 }
26974 /*-- END BACKGROUNDS --*/
26975 }
26976
26977 if ($this->tableBackgrounds && $level == 1) {
26978 $s = $this->PrintTableBackgrounds();
26979 if ($this->table_rotate && !$this->processingHeader && !$this->processingFooter) {
26980 $this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS'.date('jY').')/', '\\1'."\n".$s."\n", $this->tablebuffer);
26981 if ($level == 1) { $this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS'.date('jY').')/', " ", $this->tablebuffer); }
26982 }
26983 else if ($this->bufferoutput) {
26984 $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS'.date('jY').')/', '\\1'."\n".$s."\n", $this->headerbuffer);
26985 if ($level == 1) { $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS'.date('jY').')/', " ", $this->headerbuffer ); }
26986 }
26987 else {
26988 $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS'.date('jY').')/', '\\1'."\n".$s."\n", $this->pages[$this->page]);
26989 if ($level == 1) { $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS'.date('jY').')/', " ", $this->pages[$this->page]); }
26990 }
26991 $this->tableBackgrounds = array();
26992 }
26993
26994
26995 // TABLE BOTTOM MARGIN
26996 if ($table['margin']['B']) {
26997 if (!$this->table_rotate && $level==1) {
26998 $this->DivLn($table['margin']['B'],$this->blklvl,true); // collapsible
26999 }
27000 else {
27001 $this->y += ($table['margin']['B']);
27002 }
27003 }
27004
27005 if ($this->ColActive && $level==1) { $this->breakpoints[$this->CurrCol][] = $this->y; } // *COLUMNS*
27006
27007 if ($this->cacheTables) { fclose($fh); }
27008
27009 if ($split) {
27010 // Are there more columns to print on a next page?
27011 if ($lastCol < $numcols-1) {
27012 $splitpg++;
27013 $startcol = $lastCol + 1;
27014 return array(false, $startrow, $startcol, $splitpg, $returny, $y0);
27015 }
27016 else {
27017 if ($this->cacheTables) {
27018 unlink($table['cache']);
27019 @unlink($table['cache'].'.bak');
27020 }
27021 return array(true,0,0,0);
27022 }
27023 }
27024 if ($this->cacheTables) {
27025 unlink($table['cache']);
27026 @unlink($table['cache'].'.bak');
27027 }
27028
27029 }//END OF FUNCTION _tableWrite()
27030
27031
27032 /////////////////////////END OF TABLE CODE//////////////////////////////////
27033 /*-- END TABLES --*/
27034
27035 function _putextgstates() {
27036 for ($i = 1; $i <= count($this->extgstates); $i++) {
27037 $this->_newobj();
27038 $this->extgstates[$i]['n'] = $this->n;
27039 $this->_out('<</Type /ExtGState');
27040 foreach ($this->extgstates[$i]['parms'] as $k=>$v)
27041 $this->_out('/'.$k.' '.$v);
27042 $this->_out('>>');
27043 $this->_out('endobj');
27044 }
27045 }
27046
27047 function _putocg() {
27048 if ($this->hasOC) { // mPDF 5.6.01
27049 $this->_newobj();
27050 $this->n_ocg_print=$this->n;
27051 $this->_out('<</Type /OCG /Name '.$this->_textstring('Print only'));
27052 $this->_out('/Usage <</Print <</PrintState /ON>> /View <</ViewState /OFF>>>>>>');
27053 $this->_out('endobj');
27054 $this->_newobj();
27055 $this->n_ocg_view=$this->n;
27056 $this->_out('<</Type /OCG /Name '.$this->_textstring('Screen only'));
27057 $this->_out('/Usage <</Print <</PrintState /OFF>> /View <</ViewState /ON>>>>>>');
27058 $this->_out('endobj');
27059 $this->_newobj();
27060 $this->n_ocg_hidden=$this->n;
27061 $this->_out('<</Type /OCG /Name '.$this->_textstring('Hidden'));
27062 $this->_out('/Usage <</Print <</PrintState /OFF>> /View <</ViewState /OFF>>>>>>');
27063 $this->_out('endobj');
27064 }
27065 // mPDF 5.6.01 Add Layers
27066 if (count($this->layers)) {
27067 ksort($this->layers);
27068 foreach($this->layers as $id=>$layer) {
27069 $this->_newobj();
27070 $this->layers[$id]['n'] = $this->n;
27071 // mPDF 5.6.28
27072 if (isset($this->layerDetails[$id]['name']) && $this->layerDetails[$id]['name']) {
27073 $name = $this->layerDetails[$id]['name'];
27074 }
27075 else { $name = $layer['name']; }
27076 $this->_out('<</Type /OCG /Name '.$this->_UTF16BEtextstring($name).'>>');
27077 $this->_out('endobj');
27078 }
27079 }
27080 }
27081
27082
27083 /*-- IMPORTS --*/
27084
27085 // from mPDFI
27086 function _putimportedobjects() {
27087 if (is_array($this->parsers) && count($this->parsers) > 0) {
27088 foreach($this->parsers AS $filename => $p) {
27089 $this->current_parser =& $this->parsers[$filename];
27090 if (is_array($this->_obj_stack[$filename])) {
27091 while($n = key($this->_obj_stack[$filename])) {
27092 $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c,$this->_obj_stack[$filename][$n][1]);
27093 $this->_newobj($this->_obj_stack[$filename][$n][0]);
27094 if ($nObj[0] == PDF_TYPE_STREAM) {
27095 $this->pdf_write_value($nObj);
27096 }
27097 else {
27098 $this->pdf_write_value($nObj[1]);
27099 }
27100 $this->_out('endobj');
27101 $this->_obj_stack[$filename][$n] = null; // free memory
27102 unset($this->_obj_stack[$filename][$n]);
27103 reset($this->_obj_stack[$filename]);
27104 }
27105 }
27106 }
27107 }
27108 }
27109
27110
27111 function _putformxobjects() {
27112 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
27113 reset($this->tpls);
27114 foreach($this->tpls AS $tplidx => $tpl) {
27115 $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
27116 $this->_newobj();
27117 $this->tpls[$tplidx]['n'] = $this->n;
27118 $this->_out('<<'.$filter.'/Type /XObject');
27119 $this->_out('/Subtype /Form');
27120 $this->_out('/FormType 1');
27121 // Left/Bottom/Right/Top
27122 $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
27123 $tpl['box']['x']*_MPDFK,
27124 $tpl['box']['y']*_MPDFK,
27125 ($tpl['box']['x'] + $tpl['box']['w'])*_MPDFK,
27126 ($tpl['box']['y'] + $tpl['box']['h'])*_MPDFK )
27127 );
27128
27129
27130 if (isset($tpl['box']))
27131 $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]',-$tpl['box']['x']*_MPDFK, -$tpl['box']['y']*_MPDFK));
27132 $this->_out('/Resources ');
27133
27134 if (isset($tpl['resources'])) {
27135 $this->current_parser =& $tpl['parser'];
27136 $this->pdf_write_value($tpl['resources']);
27137 } else {
27138 $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
27139 if (isset($this->_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) {
27140 $this->_out('/Font <<');
27141 foreach($this->_res['tpl'][$tplidx]['fonts'] as $font)
27142 $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
27143 $this->_out('>>');
27144 }
27145 if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) ||
27146 isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls']))
27147 {
27148 $this->_out('/XObject <<');
27149 if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) {
27150 foreach($this->_res['tpl'][$tplidx]['images'] as $image)
27151 $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
27152 }
27153 if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) {
27154 foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $itpl)
27155 $this->_out($this->tplprefix.$i.' '.$itpl['n'].' 0 R');
27156 }
27157 $this->_out('>>');
27158 }
27159 $this->_out('>>');
27160 }
27161
27162 $this->_out('/Length '.strlen($p).' >>');
27163 $this->_putstream($p);
27164 $this->_out('endobj');
27165 }
27166 }
27167
27168 /*-- END IMPORTS --*/
27169
27170
27171 function _putpatterns() {
27172 for ($i = 1; $i <= count($this->patterns); $i++) {
27173 $x = $this->patterns[$i]['x'];
27174 $y = $this->patterns[$i]['y'];
27175 $w = $this->patterns[$i]['w'];
27176 $h = $this->patterns[$i]['h'];
27177 $pgh = $this->patterns[$i]['pgh'];
27178 $orig_w = $this->patterns[$i]['orig_w'];
27179 $orig_h = $this->patterns[$i]['orig_h'];
27180 $image_id = $this->patterns[$i]['image_id'];
27181 $itype = $this->patterns[$i]['itype'];
27182 $bpa = $this->patterns[$i]['bpa']; // mPDF 5.6.10 background positioning area
27183
27184 if ($this->patterns[$i]['x_repeat']) { $x_repeat = true; }
27185 else { $x_repeat = false; }
27186 if ($this->patterns[$i]['y_repeat']) { $y_repeat = true; }
27187 else { $y_repeat = false; }
27188 $x_pos = $this->patterns[$i]['x_pos'];
27189 if (stristr($x_pos ,'%') ) {
27190 $x_pos += 0;
27191 $x_pos /= 100;
27192 if (isset($bpa['w']) && $bpa['w']) $x_pos = ($bpa['w'] * $x_pos) - ($orig_w/_MPDFK * $x_pos); // mPDF 5.6.10
27193 else $x_pos = ($w * $x_pos) - ($orig_w/_MPDFK * $x_pos);
27194 }
27195 $y_pos = $this->patterns[$i]['y_pos'];
27196 if (stristr($y_pos ,'%') ) {
27197 $y_pos += 0;
27198 $y_pos /= 100;
27199 if (isset($bpa['h']) && $bpa['h']) $y_pos = ($bpa['h'] * $y_pos) - ($orig_h/_MPDFK * $y_pos); // mPDF 5.6.10
27200 else $y_pos = ($h * $y_pos) - ($orig_h/_MPDFK * $y_pos);
27201 }
27202 if (isset($bpa['x']) && $bpa['x']) $adj_x = ($x_pos + $bpa['x']) *_MPDFK; // mPDF 5.6.10
27203 else $adj_x = ($x_pos + $x) *_MPDFK;
27204 if (isset($bpa['y']) && $bpa['y']) $adj_y = (($pgh - $y_pos - $bpa['y'])*_MPDFK) - $orig_h ; // mPDF 5.6.10
27205 else $adj_y = (($pgh - $y_pos - $y)*_MPDFK) - $orig_h ;
27206 $img_obj = false;
27207 if ($itype == 'svg' || $itype == 'wmf') {
27208 foreach($this->formobjects AS $fo) {
27209 if ($fo['i'] == $image_id) {
27210 $img_obj = $fo['n'];
27211 $fo_w = $fo['w'];
27212 $fo_h = -$fo['h'];
27213 $wmf_x = $fo['x'];
27214 $wmf_y = $fo['y'];
27215 break;
27216 }
27217 }
27218 }
27219 else {
27220 foreach($this->images AS $img) {
27221 if ($img['i'] == $image_id) { $img_obj = $img['n']; break; }
27222 }
27223 }
27224 if (!$img_obj ) { echo "Problem: Image object not found for background pattern ".$img['i']; exit; }
27225
27226 $this->_newobj();
27227 $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
27228 if ($itype == 'svg' || $itype == 'wmf') {
27229 $this->_out('/XObject <</FO'.$image_id.' '.$img_obj.' 0 R >>');
27230 // ******* ADD ANY ExtGStates, Shading AND Fonts needed for the FormObject
27231 // Set in classes/svg array['fo'] = true
27232 // Required that _putshaders comes before _putpatterns in _putresources
27233 // This adds any resources associated with any FormObject to every Formobject - overkill but works!
27234 if (count($this->extgstates)) {
27235 $this->_out('/ExtGState <<');
27236 foreach($this->extgstates as $k=>$extgstate)
27237 if (isset($extgstate['fo']) && $extgstate['fo']) {
27238 if (isset($extgstate['trans'])) $this->_out('/'.$extgstate['trans'].' '.$extgstate['n'].' 0 R');
27239 else $this->_out('/GS'.$k.' '.$extgstate['n'].' 0 R');
27240 }
27241 $this->_out('>>');
27242 }
27243 /*-- BACKGROUNDS --*/
27244 if (isset($this->gradients) AND (count($this->gradients) > 0)) {
27245 $this->_out('/Shading <<');
27246 foreach ($this->gradients as $id => $grad) {
27247 if (isset($grad['fo']) && $grad['fo']) {
27248 $this->_out('/Sh'.$id.' '.$grad['id'].' 0 R');
27249 }
27250 }
27251 $this->_out('>>');
27252 }
27253 /*-- END BACKGROUNDS --*/
27254 $this->_out('/Font <<');
27255 foreach($this->fonts as $font) {
27256 if (!$font['used'] && $font['type']=='TTF') { continue; }
27257 if (isset($font['fo']) && $font['fo']) {
27258 if ($font['type']=='TTF' && ($font['sip'] || $font['smp'])) {
27259 foreach($font['n'] AS $k => $fid) {
27260 $this->_out('/F'.$font['subsetfontids'][$k].' '.$font['n'][$k].' 0 R');
27261 }
27262 }
27263 else {
27264 $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
27265 }
27266 }
27267 }
27268 $this->_out('>>');
27269 }
27270 else {
27271 $this->_out('/XObject <</I'.$image_id.' '.$img_obj.' 0 R >>');
27272 }
27273 $this->_out('>>');
27274 $this->_out('endobj');
27275
27276 $this->_newobj();
27277 $this->patterns[$i]['n'] = $this->n;
27278 $this->_out('<< /Type /Pattern /PatternType 1 /PaintType 1 /TilingType 2');
27279 $this->_out('/Resources '. ($this->n-1) .' 0 R');
27280
27281 $this->_out(sprintf('/BBox [0 0 %.3F %.3F]',$orig_w,$orig_h));
27282 if ($x_repeat) { $this->_out(sprintf('/XStep %.3F',$orig_w)); }
27283 else { $this->_out(sprintf('/XStep %d',99999)); }
27284 if ($y_repeat) { $this->_out(sprintf('/YStep %.3F',$orig_h)); }
27285 else { $this->_out(sprintf('/YStep %d',99999)); }
27286
27287 if ($itype == 'svg' || $itype == 'wmf') {
27288 $this->_out(sprintf('/Matrix [1 0 0 -1 %.3F %.3F]', $adj_x, ($adj_y+$orig_h)));
27289 $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);
27290 }
27291 else {
27292 $this->_out(sprintf('/Matrix [1 0 0 1 %.3F %.3F]',$adj_x,$adj_y));
27293 $s = sprintf("q %.3F 0 0 %.3F 0 0 cm /I%d Do Q",$orig_w,$orig_h,$image_id);
27294 }
27295
27296 if ($this->compress) {
27297 $this->_out('/Filter /FlateDecode');
27298 $s = gzcompress($s);
27299 }
27300 $this->_out('/Length '.strlen($s).'>>');
27301 $this->_putstream($s);
27302 $this->_out('endobj');
27303 }
27304 }
27305
27306 /*-- BACKGROUNDS --*/
27307 function _putshaders() {
27308 $maxid = count($this->gradients); //index for transparency gradients
27309 foreach ($this->gradients as $id => $grad) {
27310 if (($grad['type'] == 2 || $grad['type'] == 3) && empty($grad['is_mask'])) {
27311 $this->_newobj();
27312 $this->_out('<<');
27313 $this->_out('/FunctionType 3');
27314 $this->_out('/Domain [0 1]');
27315 $fn = array();
27316 $bd = array();
27317 $en = array();
27318 for($i=0; $i<(count($grad['stops'])-1); $i++) {
27319 $fn[] = ($this->n+1+$i).' 0 R';
27320 $en[] = '0 1';
27321 if ($i>0) { $bd[] = sprintf('%.3F', $grad['stops'][$i]['offset']); }
27322 }
27323 $this->_out('/Functions ['.implode(' ',$fn).']');
27324 $this->_out('/Bounds ['.implode(' ',$bd).']');
27325 $this->_out('/Encode ['.implode(' ',$en).']');
27326 $this->_out('>>');
27327 $this->_out('endobj');
27328 $f1 = $this->n;
27329 for($i=0; $i<(count($grad['stops'])-1); $i++) {
27330 $this->_newobj();
27331 $this->_out('<<');
27332 $this->_out('/FunctionType 2');
27333 $this->_out('/Domain [0 1]');
27334 $this->_out('/C0 ['.$grad['stops'][$i]['col'].']');
27335 $this->_out('/C1 ['.$grad['stops'][$i+1]['col'].']');
27336 $this->_out('/N 1');
27337 $this->_out('>>');
27338 $this->_out('endobj');
27339 }
27340 }
27341 if ($grad['type'] == 2 || $grad['type'] == 3) {
27342 if (isset($grad['trans']) && $grad['trans']) {
27343 $this->_newobj();
27344 $this->_out('<<');
27345 $this->_out('/FunctionType 3');
27346 $this->_out('/Domain [0 1]');
27347 $fn = array();
27348 $bd = array();
27349 $en = array();
27350 for($i=0; $i<(count($grad['stops'])-1); $i++) {
27351 $fn[] = ($this->n+1+$i).' 0 R';
27352 $en[] = '0 1';
27353 if ($i>0) { $bd[] = sprintf('%.3F', $grad['stops'][$i]['offset']); }
27354 }
27355 $this->_out('/Functions ['.implode(' ',$fn).']');
27356 $this->_out('/Bounds ['.implode(' ',$bd).']');
27357 $this->_out('/Encode ['.implode(' ',$en).']');
27358 $this->_out('>>');
27359 $this->_out('endobj');
27360 $f2 = $this->n;
27361 for($i=0; $i<(count($grad['stops'])-1); $i++) {
27362 $this->_newobj();
27363 $this->_out('<<');
27364 $this->_out('/FunctionType 2');
27365 $this->_out('/Domain [0 1]');
27366 $this->_out(sprintf('/C0 [%.3F]', $grad['stops'][$i]['opacity']));
27367 $this->_out(sprintf('/C1 [%.3F]', $grad['stops'][$i+1]['opacity']));
27368 $this->_out('/N 1');
27369 $this->_out('>>');
27370 $this->_out('endobj');
27371 }
27372 }
27373 }
27374
27375 if (empty($grad['is_mask'])) {
27376 $this->_newobj();
27377 $this->_out('<<');
27378 $this->_out('/ShadingType '.$grad['type']);
27379 if (isset($grad['colorspace'])) {
27380 $this->_out('/ColorSpace /Device'.$grad['colorspace']); // Can use CMYK if all C0 and C1 above have 4 values
27381 } else {
27382 $this->_out('/ColorSpace /DeviceRGB');
27383 }
27384 if ($grad['type'] == 2) {
27385 $this->_out(sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]));
27386 $this->_out('/Function '.$f1.' 0 R');
27387 $this->_out('/Extend ['.$grad['extend'][0].' '.$grad['extend'][1].'] ');
27388 $this->_out('>>');
27389 }
27390 else if ($grad['type'] == 3) {
27391 //x0, y0, r0, x1, y1, r1
27392 //at this this time radius of inner circle is 0
27393 $ir = 0;
27394 if (isset($grad['coords'][5]) && $grad['coords'][5]) { $ir = $grad['coords'][5]; }
27395 $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]));
27396 $this->_out('/Function '.$f1.' 0 R');
27397 $this->_out('/Extend ['.$grad['extend'][0].' '.$grad['extend'][1].'] ');
27398 $this->_out('>>');
27399 }
27400 else if ($grad['type']==6) {
27401 $this->_out('/BitsPerCoordinate 16');
27402 $this->_out('/BitsPerComponent 8');
27403 if ($grad['colorspace'] == 'CMYK') { $this->_out('/Decode[0 1 0 1 0 1 0 1 0 1 0 1]'); }
27404 else if ($grad['colorspace'] == 'Gray') { $this->_out('/Decode[0 1 0 1 0 1]'); }
27405 else { $this->_out('/Decode[0 1 0 1 0 1 0 1 0 1]'); }
27406 $this->_out('/BitsPerFlag 8');
27407 $this->_out('/Length '.strlen($grad['stream']));
27408 $this->_out('>>');
27409 $this->_putstream($grad['stream']);
27410 }
27411 $this->_out('endobj');
27412 }
27413
27414 $this->gradients[$id]['id'] = $this->n;
27415
27416 // set pattern object
27417 $this->_newobj();
27418 $out = '<< /Type /Pattern /PatternType 2';
27419 $out .= ' /Shading '.$this->gradients[$id]['id'].' 0 R';
27420 $out .= ' >>';
27421 $out .= "\n".'endobj';
27422 $this->_out($out);
27423
27424
27425 $this->gradients[$id]['pattern'] = $this->n;
27426
27427 if (isset($grad['trans']) && $grad['trans']) {
27428 // luminosity pattern
27429 $transid = $id + $maxid;
27430 $this->_newobj();
27431 $this->_out('<<');
27432 $this->_out('/ShadingType '.$grad['type']);
27433 $this->_out('/ColorSpace /DeviceGray');
27434 if ($grad['type'] == 2) {
27435 $this->_out(sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]));
27436 $this->_out('/Function '.$f2.' 0 R');
27437 $this->_out('/Extend ['.$grad['extend'][0].' '.$grad['extend'][1].'] ');
27438 $this->_out('>>');
27439 }
27440 else if ($grad['type'] == 3) {
27441 //x0, y0, r0, x1, y1, r1
27442 //at this this time radius of inner circle is 0
27443 $ir = 0;
27444 if (isset($grad['coords'][5]) && $grad['coords'][5]) { $ir = $grad['coords'][5]; }
27445 $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]));
27446 $this->_out('/Function '.$f2.' 0 R');
27447 $this->_out('/Extend ['.$grad['extend'][0].' '.$grad['extend'][1].'] ');
27448 $this->_out('>>');
27449 }
27450 else if ($grad['type']==6) {
27451 $this->_out('/BitsPerCoordinate 16');
27452 $this->_out('/BitsPerComponent 8');
27453 $this->_out('/Decode[0 1 0 1 0 1]');
27454 $this->_out('/BitsPerFlag 8');
27455 $this->_out('/Length '.strlen($grad['stream_trans']));
27456 $this->_out('>>');
27457 $this->_putstream($grad['stream_trans']);
27458 }
27459 $this->_out('endobj');
27460
27461 $this->gradients[$transid]['id'] = $this->n;
27462 $this->_newobj();
27463 $this->_out('<< /Type /Pattern /PatternType 2');
27464 $this->_out('/Shading '.$this->gradients[$transid]['id'].' 0 R');
27465 $this->_out('>>');
27466 $this->_out('endobj');
27467 $this->gradients[$transid]['pattern'] = $this->n;
27468 $this->_newobj();
27469 // Need to extend size of viewing box in case of transformations
27470 $str = 'q /a0 gs /Pattern cs /p'.$transid.' scn -'.($this->wPt/2).' -'.($this->hPt/2).' '.(2*$this->wPt).' '.(2*$this->hPt).' re f Q';
27471 $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
27472 $p=($this->compress) ? gzcompress($str) : $str;
27473 $this->_out('<< /Type /XObject /Subtype /Form /FormType 1 '.$filter);
27474 $this->_out('/Length '.strlen($p));
27475 $this->_out('/BBox [-'.($this->wPt/2).' -'.($this->hPt/2).' '.(2*$this->wPt).' '.(2*$this->hPt).']');
27476 $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceGray >>');
27477 $this->_out('/Resources <<');
27478 $this->_out('/ExtGState << /a0 << /ca 1 /CA 1 >> >>');
27479 $this->_out('/Pattern << /p'.$transid.' '.$this->gradients[$transid]['pattern'].' 0 R >>');
27480 $this->_out('>>');
27481 $this->_out('>>');
27482 $this->_putstream($p);
27483 $this->_out('endobj');
27484 $this->_newobj();
27485 $this->_out('<< /Type /Mask /S /Luminosity /G '.($this->n - 1).' 0 R >>'."\n".'endobj');
27486 $this->_newobj();
27487 $this->_out('<< /Type /ExtGState /SMask '.($this->n - 1).' 0 R /AIS false >>'."\n".'endobj');
27488 if ($grad['fo']) { $this->extgstates[] = array('n' => $this->n, 'trans' => 'TGS'.$id, 'fo'=>true); }
27489 else { $this->extgstates[] = array('n' => $this->n, 'trans' => 'TGS'.$id); }
27490 }
27491 }
27492 }
27493 /*-- END BACKGROUNDS --*/
27494
27495 function _putspotcolors() {
27496 foreach($this->spotColors as $name=>$color) {
27497 $this->_newobj();
27498 $this->_out('[/Separation /'.str_replace(' ','#20',$name));
27499 $this->_out('/DeviceCMYK <<');
27500 $this->_out('/Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0] ');
27501 $this->_out(sprintf('/C1 [%.3F %.3F %.3F %.3F] ',$color['c']/100,$color['m']/100,$color['y']/100,$color['k']/100));
27502 $this->_out('/FunctionType 2 /Domain [0 1] /N 1>>]');
27503 $this->_out('endobj');
27504 $this->spotColors[$name]['n']=$this->n;
27505 }
27506 }
27507
27508
27509 function _putresources() {
27510 if ($this->hasOC || count($this->layers)) // mPDF 5.6.01
27511 $this->_putocg();
27512 $this->_putextgstates();
27513 $this->_putspotcolors();
27514 if ($this->progressBar) { $this->UpdateProgressBar(2,'40','Compiling Fonts'); } // *PROGRESS-BAR*
27515 $this->_putfonts();
27516 if ($this->progressBar) { $this->UpdateProgressBar(2,'50','Compiling Images'); } // *PROGRESS-BAR*
27517 $this->_putimages();
27518 $this->_putformobjects(); // *IMAGES-CORE*
27519
27520 /*-- IMPORTS --*/
27521 if ($this->enableImports) {
27522 $this->_putformxobjects();
27523 $this->_putimportedobjects();
27524 }
27525 /*-- END IMPORTS --*/
27526
27527 /*-- BACKGROUNDS --*/
27528 $this->_putshaders();
27529 $this->_putpatterns();
27530 /*-- END BACKGROUNDS --*/
27531
27532
27533 //Resource dictionary
27534 $this->offsets[2]=strlen($this->buffer);
27535 $this->_out('2 0 obj');
27536 $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
27537
27538 $this->_out('/Font <<');
27539 foreach($this->fonts as $font) {
27540 if (!$font['used'] && $font['type']=='TTF') { continue; }
27541 if ($font['type']=='TTF' && ($font['sip'] || $font['smp'])) {
27542 foreach($font['n'] AS $k => $fid) {
27543 $this->_out('/F'.$font['subsetfontids'][$k].' '.$font['n'][$k].' 0 R');
27544 }
27545 }
27546 else {
27547 $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
27548 }
27549 }
27550 $this->_out('>>');
27551
27552 if (count($this->spotColors)) {
27553 $this->_out('/ColorSpace <<');
27554 foreach($this->spotColors as $color)
27555 $this->_out('/CS'.$color['i'].' '.$color['n'].' 0 R');
27556 $this->_out('>>');
27557 }
27558
27559 if (count($this->extgstates)) {
27560 $this->_out('/ExtGState <<');
27561 foreach($this->extgstates as $k=>$extgstate)
27562 if (isset($extgstate['trans'])) $this->_out('/'.$extgstate['trans'].' '.$extgstate['n'].' 0 R');
27563 else $this->_out('/GS'.$k.' '.$extgstate['n'].' 0 R');
27564 $this->_out('>>');
27565 }
27566
27567 /*-- BACKGROUNDS --*/
27568 if (isset($this->gradients) AND (count($this->gradients) > 0)) {
27569 $this->_out('/Shading <<');
27570 foreach ($this->gradients as $id => $grad) {
27571 $this->_out('/Sh'.$id.' '.$grad['id'].' 0 R');
27572 }
27573 $this->_out('>>');
27574
27575 /*
27576 // ??? Not needed !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
27577 $this->_out('/Pattern <<');
27578 foreach ($this->gradients as $id => $grad) {
27579 $this->_out('/P'.$id.' '.$grad['pattern'].' 0 R');
27580 }
27581 $this->_out('>>');
27582 */
27583 }
27584 /*-- END BACKGROUNDS --*/
27585
27586 if(count($this->images) || count($this->formobjects) || ($this->enableImports && count($this->tpls))) {
27587 $this->_out('/XObject <<');
27588 foreach($this->images as $image)
27589 $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
27590 foreach($this->formobjects as $formobject)
27591 $this->_out('/FO'.$formobject['i'].' '.$formobject['n'].' 0 R');
27592 /*-- IMPORTS --*/
27593 if ($this->enableImports && count($this->tpls)) {
27594 foreach($this->tpls as $tplidx => $tpl) {
27595 $this->_out($this->tplprefix.$tplidx.' '.$tpl['n'].' 0 R');
27596 }
27597 }
27598 /*-- END IMPORTS --*/
27599 $this->_out('>>');
27600 }
27601
27602 /*-- BACKGROUNDS --*/
27603
27604 if (count($this->patterns)) {
27605 $this->_out('/Pattern <<');
27606 foreach($this->patterns as $k=>$patterns)
27607 $this->_out('/P'.$k.' '.$patterns['n'].' 0 R');
27608 $this->_out('>>');
27609 }
27610 /*-- END BACKGROUNDS --*/
27611
27612 // mPDF 5.6.01
27613 if ($this->hasOC || count($this->layers)) {
27614 $this->_out('/Properties <<');
27615 if ($this->hasOC) {
27616 $this->_out('/OC1 '.$this->n_ocg_print.' 0 R /OC2 '.$this->n_ocg_view.' 0 R /OC3 '.$this->n_ocg_hidden.' 0 R ');
27617 }
27618 if (count($this->layers)) {
27619 foreach($this->layers as $id=>$layer)
27620 $this->_out('/ZI'.$id.' '.$layer['n'].' 0 R');
27621 }
27622 $this->_out('>>');
27623 }
27624
27625 $this->_out('>>');
27626 $this->_out('endobj'); // end resource dictionary
27627
27628 $this->_putbookmarks(); // *BOOKMARKS*
27629
27630 if (isset($this->js) && $this->js) {
27631 $this->_putjavascript();
27632 }
27633
27634 /*-- ENCRYPTION --*/
27635 if ($this->encrypted) {
27636 $this->_newobj();
27637 $this->enc_obj_id = $this->n;
27638 $this->_out('<<');
27639 $this->_putencryption();
27640 $this->_out('>>');
27641 $this->_out('endobj');
27642 }
27643 /*-- END ENCRYPTION --*/
27644 }
27645
27646
27647 function _putjavascript() {
27648 $this->_newobj();
27649 $this->n_js = $this->n;
27650 $this->_out('<<');
27651 $this->_out('/Names [(EmbeddedJS) '.(1 + $this->n).' 0 R ]');
27652 $this->_out('>>');
27653 $this->_out('endobj');
27654
27655 $this->_newobj();
27656 $this->_out('<<');
27657 $this->_out('/S /JavaScript');
27658 $this->_out('/JS '.$this->_textstring($this->js));
27659 $this->_out('>>');
27660 $this->_out('endobj');
27661 }
27662
27663
27664
27665
27666 /*-- ENCRYPTION --*/
27667 function _putencryption() {
27668 $this->_out('/Filter /Standard');
27669 if ($this->useRC128encryption) {
27670 $this->_out('/V 2');
27671 $this->_out('/R 3');
27672 $this->_out('/Length 128');
27673 }
27674 else {
27675 $this->_out('/V 1');
27676 $this->_out('/R 2');
27677 }
27678 $this->_out('/O ('.$this->_escape($this->Ovalue).')');
27679 $this->_out('/U ('.$this->_escape($this->Uvalue).')');
27680 $this->_out('/P '.$this->Pvalue);
27681 }
27682 /*-- END ENCRYPTION --*/
27683
27684 function _puttrailer() {
27685 $this->_out('/Size '.($this->n+1));
27686 $this->_out('/Root '.$this->n.' 0 R');
27687 $this->_out('/Info '.$this->InfoRoot.' 0 R');
27688 /*-- ENCRYPTION --*/
27689 if ($this->encrypted) {
27690 $this->_out('/Encrypt '.$this->enc_obj_id.' 0 R');
27691 $this->_out('/ID [<'.$this->uniqid.'> <'.$this->uniqid.'>]');
27692 }
27693 else {
27694 /*-- END ENCRYPTION --*/
27695 $uniqid = md5(time() . $this->buffer);
27696 $this->_out('/ID [<'.$uniqid.'> <'.$uniqid.'>]');
27697 /*-- ENCRYPTION --*/
27698 }
27699 /*-- END ENCRYPTION --*/
27700 }
27701
27702 /*-- ENCRYPTION --*/
27703 function SetProtection($permissions=array(),$user_pass='',$owner_pass=null, $length=40) {
27704 $this->encrypted=false;
27705 if (is_string($permissions) && strlen($permissions)>0) { $permissions = array($permissions); }
27706 else if (!is_array($permissions)) { return 0; }
27707 $this->last_rc4_key='';
27708 $this->padding="\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08".
27709 "\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
27710
27711 $options = array(
27712 'print' => 4, // bit 3
27713 'modify' => 8, // bit 4
27714 'copy' => 16, // bit 5
27715 'annot-forms' => 32, // bit 6
27716 'fill-forms' => 256, // bit 9
27717 'extract' => 512, // bit 10
27718 'assemble' => 1024,// bit 11
27719 'print-highres' => 2048 // bit 12
27720 );
27721 // bit 31 = 1073741824
27722 // bit 32 = 2147483648
27723 // bits 13-31 = 2147479552
27724 // bits 13-32 = 4294963200 + 192 = 4294963392
27725 $protection = 4294963392; // bits 7,8,13-32
27726 foreach ($permissions as $permission) {
27727 if (!isset($options[$permission]))
27728 $this->Error('Incorrect permission: '.$permission);
27729 if ($options[$permission] > 32) { $this->useRC128encryption = true; }
27730 if (isset($options[$permission])) $protection += $options[$permission];
27731 }
27732 if ($length==128) { $this->useRC128encryption = true; }
27733 if ($owner_pass === null)
27734 $owner_pass = uniqid(rand());
27735 $this->encrypted = true;
27736 $this->_generateencryptionkey($user_pass, $owner_pass, $protection);
27737 }
27738
27739
27740 // Compute key depending on object number where the encrypted data is stored
27741 function _objectkey($n) {
27742 if ($this->useRC128encryption)
27743 $len = 16;
27744 else
27745 $len = 10;
27746 return substr($this->_md5_16($this->encryption_key.pack('VXxx',$n)),0,$len);
27747 }
27748
27749 // RC4 is the standard encryption algorithm used in PDF format
27750 function _RC4($key, $text) {
27751 if ($this->last_rc4_key != $key) {
27752 $k = str_repeat($key, 256/strlen($key)+1);
27753 $rc4 = range(0,255);
27754 $j = 0;
27755 for ($i=0; $i<256; $i++){
27756 $t = $rc4[$i];
27757 $j = ($j + $t + ord($k[$i])) % 256;
27758 $rc4[$i] = $rc4[$j];
27759 $rc4[$j] = $t;
27760 }
27761 $this->last_rc4_key = $key;
27762 $this->last_rc4_key_c = $rc4;
27763 } else {
27764 $rc4 = $this->last_rc4_key_c;
27765 }
27766
27767 $len = strlen($text);
27768 $a = 0;
27769 $b = 0;
27770 $out = '';
27771 for ($i=0; $i<$len; $i++){
27772 $a = ($a+1)%256;
27773 $t= $rc4[$a];
27774 $b = ($b+$t)%256;
27775 $rc4[$a] = $rc4[$b];
27776 $rc4[$b] = $t;
27777 $k = $rc4[($rc4[$a]+$rc4[$b])%256];
27778 $out.= chr(ord($text[$i]) ^ $k);
27779 }
27780 return $out;
27781 }
27782
27783 // Get MD5 as binary string
27784 function _md5_16($string) {
27785 return pack('H*',md5($string));
27786 }
27787
27788 // Compute O value
27789 function _Ovalue($user_pass, $owner_pass) {
27790 $tmp = $this->_md5_16($owner_pass);
27791 if ($this->useRC128encryption) {
27792 for ($i = 0; $i < 50; ++$i) {
27793 $tmp = $this->_md5_16($tmp);
27794 }
27795 }
27796 if ($this->useRC128encryption)
27797 $keybytelen = (128 / 8);
27798 else
27799 $keybytelen = (40 / 8);
27800 $owner_RC4_key = substr($tmp,0,$keybytelen);
27801 $enc = $this->_RC4($owner_RC4_key, $user_pass);
27802 if ($this->useRC128encryption) {
27803 $len = strlen($owner_RC4_key);
27804 for ($i = 1; $i <= 19; ++$i) {
27805 $key = '';
27806 for ($j = 0; $j < $len; ++$j) {
27807 $key .= chr(ord($owner_RC4_key{$j}) ^ $i);
27808 }
27809 $enc = $this->_RC4($key, $enc);
27810 }
27811 }
27812 return $enc;
27813 }
27814
27815 // Compute U value
27816 function _Uvalue() {
27817 if ($this->useRC128encryption) {
27818 $tmp = $this->_md5_16($this->padding.$this->_hexToString($this->uniqid));
27819 $enc = $this->_RC4($this->encryption_key, $tmp);
27820 $len = strlen($tmp);
27821 for ($i=1; $i<=19; ++$i) {
27822 $key = '';
27823 for ($j=0; $j<$len; ++$j) {
27824 $key .= chr(ord($this->encryption_key{$j}) ^ $i);
27825 }
27826 $enc = $this->_RC4($key, $enc);
27827 }
27828 $enc .= str_repeat("\x00", 16);
27829 return substr($enc, 0, 32);
27830 }
27831 else {
27832 return $this->_RC4($this->encryption_key, $this->padding);
27833 }
27834 }
27835
27836 // Compute encryption key
27837 function _generateencryptionkey($user_pass, $owner_pass, $protection) {
27838 // Pad passwords
27839 $user_pass = substr($user_pass.$this->padding,0,32);
27840 $owner_pass = substr($owner_pass.$this->padding,0,32);
27841 $chars = 'ABCDEF1234567890';
27842 $id = '';
27843 for ($i=0; $i<32; $i++) { $id .= $chars{rand(0, 15)}; }
27844 $this->uniqid = md5($id);
27845 // Compute O value
27846 $this->Ovalue = $this->_Ovalue($user_pass,$owner_pass);
27847 // Compute encyption key
27848 if ($this->useRC128encryption)
27849 $keybytelen = (128/8);
27850 else
27851 $keybytelen = (40/8);
27852 $prot = sprintf('%032b', $protection);
27853 $perms = chr(bindec(substr($prot,24,8)));
27854 $perms .= chr(bindec(substr($prot,16,8)));
27855 $perms .= chr(bindec(substr($prot,8,8)));
27856 $perms .= chr(bindec(substr($prot,0,8)));
27857 $tmp = $this->_md5_16($user_pass.$this->Ovalue.$perms.$this->_hexToString($this->uniqid));
27858 if ($this->useRC128encryption) {
27859 for ($i=0; $i<50; ++$i) {
27860 $tmp = $this->_md5_16(substr($tmp, 0, $keybytelen));
27861 }
27862 }
27863 $this->encryption_key = substr($tmp,0,$keybytelen);
27864 // Compute U value
27865 $this->Uvalue = $this->_Uvalue();
27866 // Compute P value
27867 $this->Pvalue = $protection;
27868 }
27869
27870
27871 function _hexToString($hs) {
27872 $s = '';
27873 $len = strlen($hs);
27874 if (($len % 2) != 0) {
27875 $hs .= '0';
27876 ++$len;
27877 }
27878 for ($i = 0; $i < $len; $i += 2) {
27879 $s .= chr(hexdec($hs{$i}.$hs{($i + 1)}));
27880 }
27881 return $s;
27882 }
27883
27884 /*-- END ENCRYPTION --*/
27885
27886 //=========================================
27887 /*-- BOOKMARKS --*/
27888 // FROM class PDF_Bookmark
27889
27890 function Bookmark($txt,$level=0,$y=0) {
27891 $txt = $this->purify_utf8_text($txt);
27892 if ($this->text_input_as_HTML) {
27893 $txt = $this->all_entities_to_utf8($txt);
27894 }
27895 if($y==-1) {
27896 if (!$this->ColActive){ $y=$this->y; }
27897 else { $y = $this->y0; } // If columns are on - mark top of columns
27898 }
27899 // else y is used as set, or =0 i.e. top of page
27900 // DIRECTIONALITY RTL
27901 $bmo = array('t'=>$txt,'l'=>$level,'y'=>$y,'p'=>$this->page);
27902 if ($this->keep_block_together) {
27903 $this->ktBMoutlines[]= $bmo;
27904 }
27905 /*-- TABLES --*/
27906 else if ($this->table_rotate) {
27907 $this->tbrot_BMoutlines[]= $bmo;
27908 }
27909 else if ($this->kwt) {
27910 $this->kwt_BMoutlines[]= $bmo;
27911 }
27912 /*-- END TABLES --*/
27913 else if ($this->ColActive) { // *COLUMNS*
27914 $this->col_BMoutlines[]= $bmo; // *COLUMNS*
27915 } // *COLUMNS*
27916 else {
27917 $this->BMoutlines[]= $bmo;
27918 }
27919 }
27920
27921
27922 function _putbookmarks()
27923 {
27924 $nb=count($this->BMoutlines);
27925 if($nb==0)
27926 return;
27927
27928 // mPDF 5.6.36
27929 $bmo = $this->BMoutlines;
27930 $this->BMoutlines = array();
27931 $lastlevel = -1;
27932 for($i=0;$i<count($bmo);$i++) {
27933 if ($bmo[$i]['l']>0) {
27934 while($bmo[$i]['l']-$lastlevel > 1) { // If jump down more than one level, insert a new entry
27935 $new = $bmo[$i];
27936 $new['t']="[".$new['t']."]"; // Put [] around text/title to highlight
27937 $new['l']=$lastlevel+1;
27938 $lastlevel++;
27939 $this->BMoutlines[] = $new;
27940 }
27941 }
27942 $this->BMoutlines[] = $bmo[$i];
27943 $lastlevel = $bmo[$i]['l'];
27944 }
27945 $nb=count($this->BMoutlines);
27946
27947 $lru=array();
27948 $level=0;
27949 foreach($this->BMoutlines as $i=>$o) {
27950 if($o['l']>0) {
27951 $parent=$lru[$o['l']-1];
27952 //Set parent and last pointers
27953 $this->BMoutlines[$i]['parent']=$parent;
27954 $this->BMoutlines[$parent]['last']=$i;
27955 if($o['l']>$level) {
27956 //Level increasing: set first pointer
27957 $this->BMoutlines[$parent]['first']=$i;
27958 }
27959 }
27960 else {
27961 $this->BMoutlines[$i]['parent']=$nb;
27962 }
27963 if($o['l']<=$level and $i>0) {
27964 //Set prev and next pointers
27965 $prev=$lru[$o['l']];
27966 $this->BMoutlines[$prev]['next']=$i;
27967 $this->BMoutlines[$i]['prev']=$prev;
27968 }
27969 $lru[$o['l']]=$i;
27970 $level=$o['l'];
27971 }
27972
27973
27974 //Outline items
27975 $n=$this->n+1;
27976 foreach($this->BMoutlines as $i=>$o) {
27977 $this->_newobj();
27978 $this->_out('<</Title '.$this->_UTF16BEtextstring($o['t']));
27979 $this->_out('/Parent '.($n+$o['parent']).' 0 R');
27980 if(isset($o['prev']))
27981 $this->_out('/Prev '.($n+$o['prev']).' 0 R');
27982 if(isset($o['next']))
27983 $this->_out('/Next '.($n+$o['next']).' 0 R');
27984 if(isset($o['first']))
27985 $this->_out('/First '.($n+$o['first']).' 0 R');
27986 if(isset($o['last']))
27987 $this->_out('/Last '.($n+$o['last']).' 0 R');
27988
27989
27990 if (isset($this->pageDim[$o['p']]['h'])) { $h=$this->pageDim[$o['p']]['h']; }
27991 else { $h = 0; }
27992
27993 $this->_out(sprintf('/Dest [%d 0 R /XYZ 0 %.3F null]',1+2*($o['p']),($h-$o['y'])*_MPDFK));
27994 if (isset($this->bookmarkStyles) && isset($this->bookmarkStyles[$o['l']])) {
27995 // font style
27996 $bms = $this->bookmarkStyles[$o['l']]['style'];
27997 $style = 0;
27998 if (strpos($bms,'B') !== false) { $style += 2; }
27999 if (strpos($bms,'I') !== false) { $style += 1; }
28000 $this->_out(sprintf('/F %d', $style));
28001 // Colour
28002 $col = $this->bookmarkStyles[$o['l']]['color'];
28003 if (isset($col) && is_array($col) && count($col)==3) {
28004 $this->_out(sprintf('/C [%.3F %.3F %.3F]', ($col[0]/255), ($col[1]/255), ($col[2]/255)));
28005 }
28006 }
28007
28008 $this->_out('/Count 0>>');
28009 $this->_out('endobj');
28010 }
28011 //Outline root
28012 $this->_newobj();
28013 $this->OutlineRoot=$this->n;
28014 $this->_out('<</Type /BMoutlines /First '.$n.' 0 R');
28015 $this->_out('/Last '.($n+$lru[0]).' 0 R>>');
28016 $this->_out('endobj');
28017 }
28018 /*-- END BOOKMARKS --*/
28019
28020
28021
28022 //======================================================
28023
28024
28025 // DEPRACATED but included for backwards compatability
28026 function startPageNums() {
28027 }
28028
28029 //======================================================
28030 /*-- TOC --*/
28031 // ToC TABLE OF CONTENTS
28032
28033 // Initiate, and Mark a place for the Table of Contents to be inserted
28034 function TOC($tocfont='', $tocfontsize=0, $tocindent=0, $resetpagenum='', $pagenumstyle='', $suppress='', $toc_orientation='', $TOCusePaging=true, $TOCuseLinking=false, $toc_id=0, $tocoutdent='') { // mPDF 5.6.19
28035 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
28036 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
28037 $this->tocontents->TOC($tocfont, $tocfontsize, $tocindent, $resetpagenum, $pagenumstyle, $suppress, $toc_orientation, $TOCusePaging, $TOCuseLinking, $toc_id, $tocoutdent); // mPDF 5.6.19
28038 }
28039
28040
28041 function TOCpagebreakByArray($a) {
28042 if (!is_array($a)) { $a = array(); }
28043 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
28044 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
28045 $tocoutdent = (isset($a['tocoutdent']) ? $a['tocoutdent'] : (isset($a['outdent']) ? $a['outdent'] : ''));
28046 $TOCusePaging = (isset($a['TOCusePaging']) ? $a['TOCusePaging'] : (isset($a['paging']) ? $a['paging'] : true));
28047 $TOCuseLinking = (isset($a['TOCuseLinking']) ? $a['TOCuseLinking'] : (isset($a['links']) ? $a['links'] : ''));
28048 $toc_orientation = (isset($a['toc_orientation']) ? $a['toc_orientation'] : (isset($a['toc-orientation']) ? $a['toc-orientation'] : ''));
28049 $toc_mgl = (isset($a['toc_mgl']) ? $a['toc_mgl'] : (isset($a['toc-margin-left']) ? $a['toc-margin-left'] : ''));
28050 $toc_mgr = (isset($a['toc_mgr']) ? $a['toc_mgr'] : (isset($a['toc-margin-right']) ? $a['toc-margin-right'] : ''));
28051 $toc_mgt = (isset($a['toc_mgt']) ? $a['toc_mgt'] : (isset($a['toc-margin-top']) ? $a['toc-margin-top'] : ''));
28052 $toc_mgb = (isset($a['toc_mgb']) ? $a['toc_mgb'] : (isset($a['toc-margin-bottom']) ? $a['toc-margin-bottom'] : ''));
28053 $toc_mgh = (isset($a['toc_mgh']) ? $a['toc_mgh'] : (isset($a['toc-margin-header']) ? $a['toc-margin-header'] : ''));
28054 $toc_mgf = (isset($a['toc_mgf']) ? $a['toc_mgf'] : (isset($a['toc-margin-footer']) ? $a['toc-margin-footer'] : ''));
28055 $toc_ohname = (isset($a['toc_ohname']) ? $a['toc_ohname'] : (isset($a['toc-odd-header-name']) ? $a['toc-odd-header-name'] : ''));
28056 $toc_ehname = (isset($a['toc_ehname']) ? $a['toc_ehname'] : (isset($a['toc-even-header-name']) ? $a['toc-even-header-name'] : ''));
28057 $toc_ofname = (isset($a['toc_ofname']) ? $a['toc_ofname'] : (isset($a['toc-odd-footer-name']) ? $a['toc-odd-footer-name'] : ''));
28058 $toc_efname = (isset($a['toc_efname']) ? $a['toc_efname'] : (isset($a['toc-even-footer-name']) ? $a['toc-even-footer-name'] : ''));
28059 $toc_ohvalue = (isset($a['toc_ohvalue']) ? $a['toc_ohvalue'] : (isset($a['toc-odd-header-value']) ? $a['toc-odd-header-value'] : 0));
28060 $toc_ehvalue = (isset($a['toc_ehvalue']) ? $a['toc_ehvalue'] : (isset($a['toc-even-header-value']) ? $a['toc-even-header-value'] : 0));
28061 $toc_ofvalue = (isset($a['toc_ofvalue']) ? $a['toc_ofvalue'] : (isset($a['toc-odd-footer-value']) ? $a['toc-odd-footer-value'] : 0));
28062 $toc_efvalue = (isset($a['toc_efvalue']) ? $a['toc_efvalue'] : (isset($a['toc-even-footer-value']) ? $a['toc-even-footer-value'] : 0));
28063 $toc_preHTML = (isset($a['toc_preHTML']) ? $a['toc_preHTML'] : (isset($a['toc-preHTML']) ? $a['toc-preHTML'] : ''));
28064 $toc_postHTML = (isset($a['toc_postHTML']) ? $a['toc_postHTML'] : (isset($a['toc-postHTML']) ? $a['toc-postHTML'] : ''));
28065 $toc_bookmarkText = (isset($a['toc_bookmarkText']) ? $a['toc_bookmarkText'] : (isset($a['toc-bookmarkText']) ? $a['toc-bookmarkText'] : ''));
28066 $resetpagenum = (isset($a['resetpagenum']) ? $a['resetpagenum'] : '');
28067 $pagenumstyle = (isset($a['pagenumstyle']) ? $a['pagenumstyle'] : '');
28068 $suppress = (isset($a['suppress']) ? $a['suppress'] : '');
28069 $orientation = (isset($a['orientation']) ? $a['orientation'] : '');
28070 $mgl = (isset($a['mgl']) ? $a['mgl'] : (isset($a['margin-left']) ? $a['margin-left'] : ''));
28071 $mgr = (isset($a['mgr']) ? $a['mgr'] : (isset($a['margin-right']) ? $a['margin-right'] : ''));
28072 $mgt = (isset($a['mgt']) ? $a['mgt'] : (isset($a['margin-top']) ? $a['margin-top'] : ''));
28073 $mgb = (isset($a['mgb']) ? $a['mgb'] : (isset($a['margin-bottom']) ? $a['margin-bottom'] : ''));
28074 $mgh = (isset($a['mgh']) ? $a['mgh'] : (isset($a['margin-header']) ? $a['margin-header'] : ''));
28075 $mgf = (isset($a['mgf']) ? $a['mgf'] : (isset($a['margin-footer']) ? $a['margin-footer'] : ''));
28076 $ohname = (isset($a['ohname']) ? $a['ohname'] : (isset($a['odd-header-name']) ? $a['odd-header-name'] : ''));
28077 $ehname = (isset($a['ehname']) ? $a['ehname'] : (isset($a['even-header-name']) ? $a['even-header-name'] : ''));
28078 $ofname = (isset($a['ofname']) ? $a['ofname'] : (isset($a['odd-footer-name']) ? $a['odd-footer-name'] : ''));
28079 $efname = (isset($a['efname']) ? $a['efname'] : (isset($a['even-footer-name']) ? $a['even-footer-name'] : ''));
28080 $ohvalue = (isset($a['ohvalue']) ? $a['ohvalue'] : (isset($a['odd-header-value']) ? $a['odd-header-value'] : 0));
28081 $ehvalue = (isset($a['ehvalue']) ? $a['ehvalue'] : (isset($a['even-header-value']) ? $a['even-header-value'] : 0));
28082 $ofvalue = (isset($a['ofvalue']) ? $a['ofvalue'] : (isset($a['odd-footer-value']) ? $a['odd-footer-value'] : 0));
28083 $efvalue = (isset($a['efvalue']) ? $a['efvalue'] : (isset($a['even-footer-value']) ? $a['even-footer-value'] : 0));
28084 $toc_id = (isset($a['toc_id']) ? $a['toc_id'] : (isset($a['name']) ? $a['name'] : 0));
28085 $pagesel = (isset($a['pagesel']) ? $a['pagesel'] : (isset($a['pageselector']) ? $a['pageselector'] : ''));
28086 $toc_pagesel = (isset($a['toc_pagesel']) ? $a['toc_pagesel'] : (isset($a['toc-pageselector']) ? $a['toc-pageselector'] : ''));
28087 $sheetsize = (isset($a['sheetsize']) ? $a['sheetsize'] : (isset($a['sheet-size']) ? $a['sheet-size'] : ''));
28088 $toc_sheetsize = (isset($a['toc_sheetsize']) ? $a['toc_sheetsize'] : (isset($a['toc-sheet-size']) ? $a['toc-sheet-size'] : ''));
28089
28090 $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); // mPDF 5.6.19
28091
28092 }
28093
28094 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='') { // mPDF 5.6.19) {
28095 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
28096 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
28097 //Start a new page
28098 if($this->state==0) $this->AddPage();
28099 if ($this->y == $this->tMargin && (!$this->mirrorMargins ||($this->mirrorMargins && $this->page % 2==1))) {
28100 // Don't add a page
28101 if ($this->page==1 && count($this->PageNumSubstitutions)==0) {
28102 if (!$suppress) { $suppress = 'off'; }
28103 if (!$resetpagenum) { $resetpagenum= 1; }
28104 //$this->PageNumSubstitutions[] = array('from'=>1, 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=> $suppress);
28105 }
28106 $this->PageNumSubstitutions[] = array('from'=>$this->page, 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=> $suppress);
28107 }
28108 else {
28109 $this->AddPage($orientation,'NEXT-ODD', $resetpagenum, $pagenumstyle, $suppress,$mgl,$mgr,$mgt,$mgb,$mgh,$mgf,$ohname,$ehname,$ofname,$efname,$ohvalue,$ehvalue,$ofvalue,$efvalue,$pagesel,$sheetsize);
28110 }
28111
28112 $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); // mPDF 5.6.19
28113 }
28114
28115 function TOC_Entry($txt, $level=0, $toc_id=0) {
28116 $txt = $this->purify_utf8_text($txt);
28117 if ($this->text_input_as_HTML) {
28118 $txt = $this->all_entities_to_utf8($txt);
28119 }
28120 if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
28121 if ($this->ColActive) { $ily = $this->y0; } else { $ily = $this->y; } // use top of columns
28122
28123 // mPDF 5.6.19 mPDF 5.6.25 mPDF 5.6.37
28124 if (!class_exists('tocontents', false)) { include(_MPDF_PATH.'classes/tocontents.php'); }
28125 if (empty($this->tocontents)) { $this->tocontents = new tocontents($this); }
28126 $linkn = $this->AddLink();
28127 $uid = '__mpdfinternallink_' . $linkn ;
28128 if ($this->keep_block_together) { $this->internallink[$uid] = array("Y"=>$ily,"PAGE"=>$this->page, "kt"=>true ); }
28129 else if ($this->table_rotate) { $this->internallink[$uid] = array("Y"=>$ily,"PAGE"=>$this->page, "tbrot"=>true ); }
28130 else if ($this->kwt) { $this->internallink[$uid] = array("Y"=>$ily,"PAGE"=>$this->page, "kwt"=>true ); }
28131 else if ($this->ColActive) { $this->internallink[$uid] = array("Y"=>$ily,"PAGE"=>$this->page, "col"=>$this->CurrCol ); }
28132 else $this->internallink[$uid] = array("Y"=>$ily,"PAGE"=>$this->page );
28133 $this->internallink['#'.$uid] = $linkn;
28134 $this->SetLink($linkn,$ily,$this->page);
28135
28136 /*-- RTL --*/
28137 if ($this->biDirectional) {
28138 $txt = preg_replace_callback("/([".$this->pregRTLchars."]+)/u", array($this, 'arabJoinPregCallback'), $txt ); // mPDF 5.7+
28139 }
28140 /*-- END RTL --*/
28141 if (strtoupper($toc_id)=='ALL') { $toc_id = '_mpdf_all'; }
28142 else if (!$toc_id) { $toc_id = 0; }
28143 else { $toc_id = strtolower($toc_id); }
28144 $btoc = array('t'=>$txt,'l'=>$level,'p'=>$this->page, 'link'=>$linkn, 'toc_id'=>$toc_id);
28145 if ($this->keep_block_together) {
28146 $this->_kttoc[]= $btoc;
28147 }
28148 /*-- TABLES --*/
28149 else if ($this->table_rotate) {
28150 $this->tbrot_toc[]= $btoc;
28151 }
28152 else if ($this->kwt) {
28153 $this->kwt_toc[]= $btoc;
28154 }
28155 /*-- END TABLES --*/
28156 else if ($this->ColActive) { // *COLUMNS*
28157 $this->col_toc[]= $btoc; // *COLUMNS*
28158 } // *COLUMNS*
28159 else {
28160 $this->tocontents->_toc[]= $btoc;
28161 }
28162 }
28163
28164 /*-- END TOC --*/
28165
28166 //======================================================
28167 function MovePages($target_page, $start_page, $end_page=-1) {
28168 // move a page/pages EARLIER in the document
28169 if ($end_page<1) { $end_page = $start_page; }
28170 $n_toc = $end_page - $start_page + 1;
28171
28172 // Set/Update PageNumSubstitutions changes before moving anything
28173 if (count($this->PageNumSubstitutions)) {
28174 $tp_present = false;
28175 $sp_present = false;
28176 $ep_present = false;
28177 foreach($this->PageNumSubstitutions AS $k=>$v) {
28178 if ($this->PageNumSubstitutions[$k]['from']==$target_page) {
28179 $tp_present = true;
28180 if ($this->PageNumSubstitutions[$k]['suppress']!='on' && $this->PageNumSubstitutions[$k]['suppress']!=1) {
28181 $this->PageNumSubstitutions[$k]['suppress']='off';
28182 }
28183 }
28184 if ($this->PageNumSubstitutions[$k]['from']==$start_page) {
28185 $sp_present = true;
28186 if ($this->PageNumSubstitutions[$k]['suppress']!='on' && $this->PageNumSubstitutions[$k]['suppress']!=1) {
28187 $this->PageNumSubstitutions[$k]['suppress']='off';
28188 }
28189 }
28190 if ($this->PageNumSubstitutions[$k]['from']==($end_page+1)) {
28191 $ep_present = true;
28192 if ($this->PageNumSubstitutions[$k]['suppress']!='on' && $this->PageNumSubstitutions[$k]['suppress']!=1) {
28193 $this->PageNumSubstitutions[$k]['suppress']='off';
28194 }
28195 }
28196 }
28197
28198 if (!$tp_present) {
28199 list($tp_type, $tp_suppress, $tp_reset) = $this->docPageSettings($target_page);
28200 }
28201 if (!$sp_present) {
28202 list($sp_type, $sp_suppress, $sp_reset) = $this->docPageSettings($start_page);
28203 }
28204 if (!$ep_present) {
28205 list($ep_type, $ep_suppress, $ep_reset) = $this->docPageSettings($start_page-1);
28206 }
28207
28208 }
28209
28210 $last = array();
28211 //store pages
28212 for($i = $start_page;$i <= $end_page ;$i++)
28213 $last[]=$this->pages[$i];
28214 //move pages
28215 for($i=$start_page - 1;$i>=($target_page);$i--) {
28216 $this->pages[$i+$n_toc]=$this->pages[$i];
28217 }
28218 //Put toc pages at insert point
28219 for($i = 0;$i < $n_toc;$i++) {
28220 $this->pages[$target_page + $i]=$last[$i];
28221 }
28222
28223 /*-- BOOKMARKS --*/
28224 // Update Bookmarks
28225 foreach($this->BMoutlines as $i=>$o) {
28226 if($o['p']>=$target_page) {
28227 $this->BMoutlines[$i]['p'] += $n_toc;
28228 }
28229 }
28230 /*-- END BOOKMARKS --*/
28231
28232 // Update Page Links
28233 if (count($this->PageLinks)) {
28234 $newarr = array();
28235 foreach($this->PageLinks as $i=>$o) {
28236 foreach($this->PageLinks[$i] as $key => $pl) {
28237 if (strpos($pl[4],'@')===0) {
28238 $p=substr($pl[4],1);
28239 if($p>=$start_page && $p<=$end_page) {
28240 $this->PageLinks[$i][$key][4] = '@'.($p + ($target_page - $start_page));
28241 }
28242 else if($p>=$target_page && $p<$start_page) {
28243 $this->PageLinks[$i][$key][4] = '@'.($p+$n_toc);
28244 }
28245 }
28246 }
28247 if($i>=$start_page && $i<=$end_page) {
28248 $newarr[($i + ($target_page - $start_page))] = $this->PageLinks[$i];
28249 }
28250 else if($i>=$target_page && $i<$start_page) {
28251 $newarr[($i + $n_toc)] = $this->PageLinks[$i];
28252 }
28253 else {
28254 $newarr[$i] = $this->PageLinks[$i];
28255 }
28256 }
28257 $this->PageLinks = $newarr;
28258 }
28259
28260 // OrientationChanges
28261 if (count($this->OrientationChanges)) {
28262 $newarr = array();
28263 foreach($this->OrientationChanges AS $p=>$v) {
28264 if($p>=$start_page && $p<=$end_page) { $newarr[($p + ($target_page - $start_page))] = $this->OrientationChanges[$p]; }
28265 else if($p>=$target_page && $p<$start_page) { $newarr[$p+$n_toc] = $this->OrientationChanges[$p]; }
28266 else { $newarr[$p] = $this->OrientationChanges[$p]; }
28267 }
28268 ksort($newarr);
28269 $this->OrientationChanges = $newarr;
28270 }
28271
28272 // Page Dimensions
28273 if (count($this->pageDim)) {
28274 $newarr = array();
28275 foreach($this->pageDim AS $p=>$v) {
28276 if($p>=$start_page && $p<=$end_page) { $newarr[($p + ($target_page - $start_page))] = $this->pageDim[$p]; }
28277 else if($p>=$target_page && $p<$start_page) { $newarr[$p+$n_toc] = $this->pageDim[$p]; }
28278 else { $newarr[$p] = $this->pageDim[$p]; }
28279 }
28280 ksort($newarr);
28281 $this->pageDim = $newarr;
28282 }
28283
28284 // HTML Headers & Footers
28285 if (count($this->saveHTMLHeader)) {
28286 $newarr = array();
28287 foreach($this->saveHTMLHeader AS $p=>$v) {
28288 if($p>=$start_page && $p<=$end_page) { $newarr[($p + ($target_page - $start_page))] = $this->saveHTMLHeader[$p]; }
28289 else if($p>=$target_page && $p<$start_page) { $newarr[$p+$n_toc] = $this->saveHTMLHeader[$p]; }
28290 else { $newarr[$p] = $this->saveHTMLHeader[$p]; }
28291 }
28292 ksort($newarr);
28293 $this->saveHTMLHeader = $newarr;
28294 }
28295 if (count($this->saveHTMLFooter)) {
28296 $newarr = array();
28297 foreach($this->saveHTMLFooter AS $p=>$v) {
28298 if($p>=$start_page && $p<=$end_page) { $newarr[($p + ($target_page - $start_page))] = $this->saveHTMLFooter[$p]; }
28299 else if($p>=$target_page && $p<$start_page) { $newarr[$p+$n_toc] = $this->saveHTMLFooter[$p]; }
28300 else { $newarr[$p] = $this->saveHTMLFooter[$p]; }
28301 }
28302 ksort($newarr);
28303 $this->saveHTMLFooter = $newarr;
28304 }
28305
28306 // Update Internal Links
28307 if (count($this->internallink)) {
28308 foreach($this->internallink as $key=>$o) {
28309 if($o['PAGE']>=$start_page && $o['PAGE']<=$end_page) {
28310 $this->internallink[$key]['PAGE'] += ($target_page - $start_page);
28311 }
28312 else if($o['PAGE']>=$target_page && $o['PAGE']<$start_page) {
28313 $this->internallink[$key]['PAGE'] += $n_toc;
28314 }
28315 }
28316 }
28317
28318 // Update Links
28319 if (count($this->links)) {
28320 foreach($this->links as $key=>$o) {
28321 if($o[0]>=$start_page && $o[0]<=$end_page) {
28322 $this->links[$key][0] += ($target_page - $start_page);
28323 }
28324 if($o[0]>=$target_page && $o[0]<$start_page) {
28325 $this->links[$key][0] += $n_toc;
28326 }
28327 }
28328 }
28329
28330 // Update Form fields
28331 if (count($this->form->forms)) {
28332 foreach($this->form->forms as $key=>$f) {
28333 if($f['page']>=$start_page && $f['page']<=$end_page) {
28334 $this->form->forms[$key]['page'] += ($target_page - $start_page);
28335 }
28336 if($f['page']>=$target_page && $f['page']<$start_page) {
28337 $this->form->forms[$key]['page'] += $n_toc;
28338 }
28339 }
28340 }
28341
28342 /*-- ANNOTATIONS --*/
28343 // Update Annotations
28344 if (count($this->PageAnnots)) {
28345 $newarr = array();
28346 foreach($this->PageAnnots as $p=>$anno) {
28347 if($p>=$start_page && $p<=$end_page) {
28348 $np = $p + ($target_page - $start_page);
28349 foreach($anno as $o) {
28350 $newarr[$np][] = $o;
28351 }
28352 }
28353 else if($p>=$target_page && $p<$start_page) {
28354 $np = $p + $n_toc;
28355 foreach($anno as $o) {
28356 $newarr[$np][] = $o;
28357 }
28358 }
28359 else {
28360 $newarr[$p] = $this->PageAnnots[$p];
28361 }
28362 }
28363 $this->PageAnnots = $newarr;
28364 unset($newarr);
28365 }
28366 /*-- END ANNOTATIONS --*/
28367
28368 // Update PageNumSubstitutions
28369 if (count($this->PageNumSubstitutions)) {
28370 $newarr = array();
28371 foreach($this->PageNumSubstitutions AS $k=>$v) {
28372 if($this->PageNumSubstitutions[$k]['from']>=$start_page && $this->PageNumSubstitutions[$k]['from']<=$end_page) {
28373 $this->PageNumSubstitutions[$k]['from'] += ($target_page - $start_page);
28374 $newarr[$this->PageNumSubstitutions[$k]['from']] = $this->PageNumSubstitutions[$k];
28375 }
28376 else if($this->PageNumSubstitutions[$k]['from']>=$target_page && $this->PageNumSubstitutions[$k]['from']<$start_page) {
28377 $this->PageNumSubstitutions[$k]['from'] += $n_toc;
28378 $newarr[$this->PageNumSubstitutions[$k]['from']] = $this->PageNumSubstitutions[$k];
28379 }
28380 else {
28381 $newarr[$this->PageNumSubstitutions[$k]['from']] = $this->PageNumSubstitutions[$k];
28382 }
28383 }
28384
28385 if (!$sp_present) {
28386 $newarr[$target_page] = array('from'=>$target_page, 'suppress'=>$sp_suppress, 'reset'=>$sp_reset, 'type'=>$sp_type);
28387 }
28388 if (!$tp_present) {
28389 $newarr[($target_page + $n_toc)] = array('from'=>($target_page+$n_toc), 'suppress'=>$tp_suppress, 'reset'=>$tp_reset, 'type'=>$tp_type);
28390 }
28391 if (!$ep_present && $end_page>count($this->pages)) {
28392 $newarr[($end_page+1)] = array('from'=>($end_page+1), 'suppress'=>$ep_suppress, 'reset'=>$ep_reset, 'type'=>$ep_type);
28393 }
28394 ksort($newarr);
28395 $this->PageNumSubstitutions = array();
28396 foreach($newarr as $v) {
28397 $this->PageNumSubstitutions[] = $v;
28398 }
28399 }
28400 }
28401
28402 //======================================================
28403 function DeletePages($start_page, $end_page=-1) {
28404 // move a page/pages EARLIER in the document
28405 if ($end_page<1) { $end_page = $start_page; }
28406 $n_tod = $end_page - $start_page + 1;
28407 $last_page = count($this->pages);
28408 $n_atend = $last_page - $end_page + 1;
28409
28410 //move pages
28411 for($i=0;$i<$n_atend;$i++) {
28412 $this->pages[$start_page+$i]=$this->pages[$end_page+1+$i];
28413 }
28414 //delete pages
28415 for($i = 0;$i < $n_tod ;$i++)
28416 unset($this->pages[$last_page-$i]);
28417
28418
28419 /*-- BOOKMARKS --*/
28420 // Update Bookmarks
28421 foreach($this->BMoutlines as $i=>$o) {
28422 if($o['p']>=$end_page) { $this->BMoutlines[$i]['p'] -= $n_tod; }
28423 else if($p<$start_page) { unset($this->BMoutlines[$i]); }
28424 }
28425 /*-- END BOOKMARKS --*/
28426
28427 // Update Page Links
28428 if (count($this->PageLinks)) {
28429 $newarr = array();
28430 foreach($this->PageLinks as $i=>$o) {
28431 foreach($this->PageLinks[$i] as $key => $pl) {
28432 if (strpos($pl[4],'@')===0) {
28433 $p=substr($pl[4],1);
28434 if($p>$end_page) { $this->PageLinks[$i][$key][4] = '@'.($p - $n_tod); }
28435 else if($p<$start_page) { unset($this->PageLinks[$i][$key]); }
28436 }
28437 }
28438 if($i>$end_page) { $newarr[($i - $n_tod)] = $this->PageLinks[$i]; }
28439 else if($p<$start_page) { $newarr[$i] = $this->PageLinks[$i]; }
28440 }
28441 $this->PageLinks = $newarr;
28442 }
28443
28444 // OrientationChanges
28445 if (count($this->OrientationChanges)) {
28446 $newarr = array();
28447 foreach($this->OrientationChanges AS $p=>$v) {
28448 if($p>$end_page) { $newarr[($p - $t_tod)] = $this->OrientationChanges[$p]; }
28449 else if($p<$start_page) { $newarr[$p] = $this->OrientationChanges[$p]; }
28450 }
28451 ksort($newarr);
28452 $this->OrientationChanges = $newarr;
28453 }
28454
28455 // Page Dimensions
28456 if (count($this->pageDim)) {
28457 $newarr = array();
28458 foreach($this->pageDim AS $p=>$v) {
28459 if($p>$end_page) { $newarr[($p - $n_tod)] = $this->pageDim[$p]; }
28460 else if($p<$start_page) { $newarr[$p] = $this->pageDim[$p]; }
28461 }
28462 ksort($newarr);
28463 $this->pageDim = $newarr;
28464 }
28465
28466 // HTML Headers & Footers
28467 if (count($this->saveHTMLHeader)) {
28468 foreach($this->saveHTMLHeader AS $p=>$v) {
28469 if($p>end_page) { $newarr[($p - $n_tod)] = $this->saveHTMLHeader[$p]; }
28470 else if($p<$start_page) { $newarr[$p] = $this->saveHTMLHeader[$p]; }
28471 }
28472 ksort($newarr);
28473 $this->saveHTMLHeader = $newarr;
28474 }
28475 if (count($this->saveHTMLFooter)) {
28476 $newarr = array();
28477 foreach($this->saveHTMLFooter AS $p=>$v) {
28478 if($p>$end_page) { $newarr[($p - $n_tod)] = $this->saveHTMLFooter[$p]; }
28479 else if($p<$start_page) { $newarr[$p] = $this->saveHTMLFooter[$p]; }
28480 }
28481 ksort($newarr);
28482 $this->saveHTMLFooter = $newarr;
28483 }
28484
28485 // Update Internal Links
28486 foreach($this->internallink as $key=>$o) {
28487 if($o['PAGE']>$end_page) { $this->internallink[$key]['PAGE'] -= $n_tod; }
28488 else if($o['PAGE']<$start_page) { unset($this->internallink[$key]); }
28489 }
28490
28491 // Update Links
28492 foreach($this->links as $key=>$o) {
28493 if($o[0]>$end_page) { $this->links[$key][0] -= $n_tod; }
28494 else if($o[0]<$start_page) { unset($this->links[$key]); }
28495 }
28496
28497 // Update Form fields
28498 foreach($this->form->forms as $key=>$f) {
28499 if($f['page']>$end_page) { $this->form->forms[$key]['page'] -= $n_tod; }
28500 else if($f['page']<$start_page) { unset($this->form->forms[$key]); }
28501 }
28502
28503 /*-- ANNOTATIONS --*/
28504 // Update Annotations
28505 if (count($this->PageAnnots)) {
28506 $newarr = array();
28507 foreach($this->PageAnnots as $p=>$anno) {
28508 if($p>$end_page) { foreach($anno as $o) { $newarr[($p - $n_tod)][] = $o; } }
28509 else if($p<$start_page) { $newarr[$p] = $this->PageAnnots[$p]; }
28510 }
28511 ksort($newarr);
28512 $this->PageAnnots = $newarr;
28513 }
28514 /*-- END ANNOTATIONS --*/
28515
28516 // Update PageNumSubstitutions
28517 foreach($this->PageNumSubstitutions AS $k=>$v) {
28518 if($this->PageNumSubstitutions[$k]['from']>$end_page) { $this->PageNumSubstitutions[$k]['from'] -= $n_tod; }
28519 else if($this->PageNumSubstitutions[$k]['from']<$start_page) { unset($this->PageNumSubstitutions[$k]); }
28520 }
28521
28522 unset($newarr);
28523 $this->page = count($this->pages);
28524 }
28525
28526
28527 //======================================================
28528 /*-- INDEX --*/
28529 // FROM class PDF_Ref == INDEX
28530
28531 function Reference($txt) {
28532 $this->IndexEntry($txt);
28533 }
28534
28535
28536 function IndexEntry($txt, $xref='') {
28537 if ($xref) {
28538 $this->IndexEntrySee($txt,$xref);
28539 return;
28540 }
28541 $txt = strip_tags($txt);
28542 $txt = $this->purify_utf8_text($txt);
28543 if ($this->text_input_as_HTML) {
28544 $txt = $this->all_entities_to_utf8($txt);
28545 }
28546 if ($this->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mb_enc,'UTF-8'); }
28547
28548 $Present=0;
28549 $size=sizeof($this->Reference);
28550
28551 if ($this->directionality == 'rtl') { // *RTL*
28552 $txt = str_replace(':',' - ',$txt); // *RTL*
28553 } // *RTL*
28554 else { // *RTL*
28555 $txt = str_replace(':',', ',$txt);
28556 } // *RTL*
28557
28558
28559 //Search the reference (AND Ref/PageNo) in the array
28560 for ($i=0;$i<$size;$i++){
28561 if ($this->keep_block_together) {
28562 if (isset($this->ktReference[$i]['t']) && $this->ktReference[$i]['t']==$txt){
28563 $Present=1;
28564 if (!in_array($this->page,$this->ktReference[$i]['p'])) {
28565 $this->ktReference[$i]['op'] = $this->page;
28566 }
28567 }
28568 }
28569 /*-- TABLES --*/
28570 else if ($this->table_rotate) {
28571 if (isset($this->tbrot_Reference[$i]['t']) && $this->tbrot_Reference[$i]['t']==$txt){
28572 $Present=1;
28573 if (!in_array($this->page,$this->tbrot_Reference[$i]['p'])) {
28574 $this->tbrot_Reference[$i]['op'] = $this->page;
28575 }
28576 }
28577 }
28578 else if ($this->kwt) {
28579 if (isset($this->kwt_Reference[$i]['t']) && $this->kwt_Reference[$i]['t']==$txt){
28580 $Present=1;
28581 if (!in_array($this->page,$this->kwt_Reference[$i]['p'])) {
28582 $this->kwt_Reference[$i]['op'] = $this->page;
28583 }
28584 }
28585 }
28586 /*-- END TABLES --*/
28587 /*-- COLUMNS --*/
28588 else if ($this->ColActive) {
28589 if (isset($this->col_Reference[$i]['t']) && $this->col_Reference[$i]['t']==$txt){
28590 $Present=1;
28591 if (!in_array($this->page,$this->col_Reference[$i]['p'])) {
28592 $this->col_Reference[$i]['op'] = $this->page;
28593 }
28594 }
28595 }
28596 /*-- END COLUMNS --*/
28597 else {
28598 if (isset($this->Reference[$i]['t']) && $this->Reference[$i]['t']==$txt){
28599 $Present=1;
28600 if (!in_array($this->page,$this->Reference[$i]['p'])) {
28601 $this->Reference[$i]['p'][] = $this->page;
28602 }
28603 }
28604 }
28605 }
28606 //If not found, add it
28607 if ($Present==0) {
28608 $opr = array('t'=>$txt, 'op'=>$this->page);
28609 if ($this->keep_block_together) {
28610 $this->ktReference[]= $opr;
28611 }
28612 /*-- TABLES --*/
28613 else if ($this->table_rotate) {
28614 $this->tbrot_Reference[]= $opr;
28615 }
28616 else if ($this->kwt) {
28617 $this->kwt_Reference[]= $opr;
28618 }
28619 /*-- END TABLES --*/
28620 /*-- COLUMNS --*/
28621 else if ($this->ColActive) {
28622 $this->col_Reference[]= $opr;
28623 }
28624 /*-- END COLUMNS --*/
28625 else {
28626 $this->Reference[]=array('t'=>$txt,'p'=>array($this->page));
28627 }
28628 }
28629 }
28630
28631 // Added function to add a reference "Elephants. See Chickens"
28632 function ReferenceSee($txta,$txtb) {
28633 $this->IndexEntrySee($txta,$txtb);
28634 }
28635
28636 function IndexEntrySee($txta,$txtb) {
28637 $txta = strip_tags($txta);
28638 $txtb = strip_tags($txtb);
28639 $txta = $this->purify_utf8_text($txta);
28640 $txtb = $this->purify_utf8_text($txtb);
28641 if ($this->text_input_as_HTML) {
28642 $txta = $this->all_entities_to_utf8($txta);
28643 $txtb = $this->all_entities_to_utf8($txtb);
28644 }
28645 if ($this->usingCoreFont) {
28646 $txta = mb_convert_encoding($txta,$this->mb_enc,'UTF-8');
28647 $txtb = mb_convert_encoding($txtb,$this->mb_enc,'UTF-8');
28648 }
28649 if ($this->directionality == 'rtl') { // *RTL*
28650 $txta = str_replace(':',' - ',$txta); // *RTL*
28651 $txtb = str_replace(':',' - ',$txtb); // *RTL*
28652 } // *RTL*
28653 else { // *RTL*
28654 $txta = str_replace(':',', ',$txta);
28655 $txtb = str_replace(':',', ',$txtb);
28656 } // *RTL*
28657 $this->Reference[]=array('t'=>$txta.' - see '.$txtb,'p'=>array());
28658 }
28659
28660 function CreateReference($NbCol=1, $reffontsize='', $linespacing='', $offset=3, $usedivletters=1, $divlettfontsize='', $gap=5, $reffont='',$divlettfont='', $useLinking=false) {
28661 $this->CreateIndex($NbCol, $reffontsize, $linespacing, $offset, $usedivletters, $divlettfontsize, $gap, $reffont, $divlettfont, $useLinking);
28662 }
28663
28664 function CreateIndex($NbCol=1, $reffontsize='', $linespacing='', $offset=3, $usedivletters=1, $divlettfontsize='', $gap=5, $reffont='',$divlettfont='', $useLinking=false) {
28665 if (!$reffontsize) { $reffontsize = $this->default_font_size; }
28666 if (!$divlettfontsize) { $divlettfontsize = ($this->default_font_size * 1.8); }
28667 if (!$reffont) { $reffont = $this->default_font; }
28668 if (!$divlettfont) { $divlettfont = $reffont; }
28669 if (!$linespacing) { $linespacing= $this->default_lineheight_correction; }
28670 if ($this->ColActive) { $this->SetColumns(0); } // *COLUMNS*
28671 $size=sizeof($this->Reference);
28672 if ($size == 0) { return false; }
28673
28674
28675 if ($NbCol<2) {
28676 $NbCol = 1;
28677 $colWidth = $this->pgwidth;
28678 }
28679 else {
28680 $this->SetColumns($NbCol,'',$gap);
28681 $colWidth = $this->ColWidth;
28682 }
28683 if ($this->directionality == 'rtl') { $align = 'R'; }
28684 else { $align = 'L'; }
28685 $lett = '';
28686 if (!function_exists('cmp')) {
28687 function cmp ($a, $b) {
28688 return strnatcmp(strtolower($a['t']), strtolower($b['t']));
28689 }
28690 }
28691 //Alphabetic sort of the references
28692 usort($this->Reference, 'cmp');
28693 $size=sizeof($this->Reference);
28694 $this->breakpoints[$this->CurrCol][] = $this->y; // *COLUMNS*
28695
28696 $divlettjuststarted = false;
28697
28698 $this->OpenTag('DIV',array('STYLE'=>'line-height: '.$linespacing.'; font-family: '.$reffont.'; font-size: '.$reffontsize.'pt; '));
28699
28700 $last_lett = '';
28701 for ($i=0;$i<$size;$i++){
28702 if ($this->Reference[$i]['t']) {
28703 if ($usedivletters) {
28704
28705 $lett = mb_strtoupper(mb_substr($this->Reference[$i]['t'],0,1,$this->mb_enc ),$this->mb_enc );
28706 if ($lett != $last_lett) {
28707
28708 $save_bp = $this->breakpoints[$this->CurrCol]; // *COLUMNS*
28709 $divlettjuststarted = true;
28710
28711 if ($i>0) {
28712 $this->OpenTag('DIV',array('STYLE'=>'line-height: '.$linespacing.'; font-family: '.$divlettfont.'; font-size: '.$divlettfontsize.'pt; font-weight: bold; page-break-after: avoid; margin-top: 0.5em; margin-collapse: collapse; '));
28713 }
28714 else {
28715 $this->OpenTag('DIV',array('STYLE'=>'line-height: '.$linespacing.'; font-family: '.$divlettfont.'; font-size: '.$divlettfontsize.'pt; font-weight: bold; page-break-after: avoid; '));
28716 }
28717 $this->_saveTextBuffer($lett);
28718 $this->CloseTag('DIV');
28719 }
28720 }
28721
28722 $this->OpenTag('DIV',array('STYLE'=>'text-indent: -'.$offset.'mm; line-height: '.$linespacing.'; font-family: '.$reffont.'; font-size: '.$reffontsize.'pt; '));
28723
28724 /*-- RTL --*/
28725 // Change Arabic + Persian. to Presentation Forms
28726 if ($this->biDirectional) {
28727 $this->Reference[$i]['t'] = preg_replace_callback("/([".$this->pregRTLchars."]+)/u", array($this, 'arabJoinPregCallback'), $this->Reference[$i]['t'] ); // mPDF 5.7+
28728 }
28729 /*-- END RTL --*/
28730
28731 // Font-specific ligature substitution for Indic fonts
28732 if (isset($this->CurrentFont['indic']) && $this->CurrentFont['indic']) $this->ConvertIndic($this->Reference[$i]['t']); // *INDIC*
28733
28734 $this->_saveTextBuffer($this->Reference[$i]['t']);
28735 $ppp = $this->Reference[$i]['p']; // = array of page numbers to point to
28736 if (count($ppp)) {
28737 sort($ppp);
28738 $newarr = array();
28739 $range_start = $ppp[0];
28740 $range_end = 0;
28741
28742 if (!$this->usingCoreFont) { $spacer = "\xc2\xa0 "; }
28743 else { $spacer = chr(160).' '; }
28744 $this->_saveTextBuffer($spacer);
28745 if ($this->directionality == 'rtl') { $sep = '.'; $joiner = '-'; }
28746 else { $sep = ', '; $joiner = '-'; }
28747 for ($zi=1;$zi<count($ppp);$zi++) {
28748 // RTL - Each number separately
28749 if ($this->directionality == 'rtl') {
28750 /*-- RTL --*/
28751 if ($zi<count($ppp)-1) {
28752 $txt = $sep . $this->docPageNum($ppp[$zi]);
28753 if ($useLinking) { $href = '@'.$ppp[$zi]; }
28754 else { $href = ''; }
28755 $this->_saveTextBuffer($txt, $href);
28756 }
28757 /*-- END RTL --*/
28758 }
28759
28760 else if ($ppp[$zi] == ($ppp[($zi-1)]+1)) {
28761 $range_end = $ppp[$zi];
28762 }
28763 else {
28764 if ($range_end) {
28765 if ($range_end == $range_start+1) {
28766 if ($useLinking) { $href = '@'.$range_start; }
28767 else { $href = ''; }
28768 $txt = $this->docPageNum($range_start) . $sep;
28769 $this->_saveTextBuffer($txt, $href);
28770 if ($useLinking) { $href = '@'.$ppp[$zi-1]; }
28771 else { $href = ''; }
28772 $txt = $this->docPageNum($ppp[$zi-1]) . $sep;
28773 $this->_saveTextBuffer($txt, $href);
28774 }
28775 else {
28776 if ($useLinking) { $href = '@'.$range_start; }
28777 else { $href = ''; }
28778 }
28779 }
28780 else {
28781 if ($useLinking) { $href = '@'.$ppp[$zi-1]; }
28782 else { $href = ''; }
28783 $txt = $this->docPageNum($ppp[$zi-1]) . $sep;
28784 $this->_saveTextBuffer($txt, $href);
28785 }
28786 $range_start = $ppp[$zi];
28787 $range_end = 0;
28788 }
28789 }
28790
28791 if ($range_end) {
28792 if ($range_end == $range_start+1) {
28793 if ($useLinking) { $href = '@'.$range_start; }
28794 else { $href = ''; }
28795 $txt = $this->docPageNum($range_start) . $sep;
28796 $this->_saveTextBuffer($txt, $href);
28797 if ($useLinking) { $href = '@'.$range_end; }
28798 else { $href = ''; }
28799 $txt = $this->docPageNum($range_end);
28800 $this->_saveTextBuffer($txt, $href);
28801 }
28802 else {
28803 if ($useLinking) { $href = '@'.$range_start; }
28804 else { $href = ''; }
28805 $txt = $this->docPageNum($range_start) . $joiner;
28806 $this->_saveTextBuffer($txt, $href);
28807 if ($useLinking) { $href = '@'.$range_end; }
28808 else { $href = ''; }
28809 $txt = $this->docPageNum($range_end);
28810 $this->_saveTextBuffer($txt, $href);
28811 }
28812 }
28813 else {
28814 if ($useLinking) { $href = '@'.$ppp[(count($ppp)-1)]; }
28815 else { $href = ''; }
28816 $txt = $this->docPageNum($ppp[(count($ppp)-1)]);
28817 $this->_saveTextBuffer($txt, $href);
28818 }
28819 }
28820 }
28821 $this->CloseTag('DIV');
28822
28823 if ($divlettjuststarted) { $this->breakpoints[$this->CurrCol] = $save_bp; } // *COLUMNS*
28824 $divlettjuststarted = false;
28825
28826 $this->breakpoints[$this->CurrCol][] = $this->y; // *COLUMNS*
28827 $last_lett = $lett;
28828 }
28829 $this->CloseTag('DIV');
28830 $this->breakpoints[$this->CurrCol][] = $this->y; // *COLUMNS*
28831 if ($this->ColActive) { $this->SetColumns(0); } // *COLUMNS*
28832 }
28833 /*-- END INDEX --*/
28834
28835
28836 function AcceptPageBreak() {
28837 if (count($this->cellBorderBuffer)) { $this->printcellbuffer(); } // *TABLES*
28838 /*-- COLUMNS --*/
28839 if ($this->ColActive==1) {
28840 if($this->CurrCol<$this->NbCol-1) {
28841 //Go to the next column
28842 $this->CurrCol++;
28843 $this->SetCol($this->CurrCol);
28844 $this->y=$this->y0;
28845 $this->ChangeColumn=1; // Number (and direction) of columns changed +1, +2, -2 etc.
28846 // DIRECTIONALITY RTL
28847 if ($this->directionality == 'rtl') { $this->ChangeColumn = -($this->ChangeColumn); } // *RTL*
28848
28849 //Stay on the page
28850 return false;
28851 }
28852 else {
28853 //Go back to the first column - NEW PAGE
28854 if (count($this->columnbuffer)) { $this->printcolumnbuffer(); }
28855 $this->SetCol(0);
28856 $this->y0 = $this->tMargin;
28857 $this->ChangeColumn= -($this->NbCol-1);
28858 // DIRECTIONALITY RTL
28859 if ($this->directionality == 'rtl') { $this->ChangeColumn = -($this->ChangeColumn); } // *RTL*
28860 //Page break
28861 return true;
28862 }
28863 }
28864 /*-- END COLUMNS --*/
28865 /*-- TABLES --*/
28866 else if ($this->table_rotate) {
28867 if ($this->tablebuffer) { $this->printtablebuffer(); }
28868 return true;
28869 }
28870 /*-- END TABLES --*/
28871 else { // *COLUMNS*
28872 $this->ChangeColumn=0;
28873 return $this->autoPageBreak;
28874 } // *COLUMNS*
28875 return $this->autoPageBreak;
28876 }
28877
28878
28879 //----------- COLUMNS ---------------------
28880 /*-- COLUMNS --*/
28881
28882 function SetColumns($NbCol,$vAlign='',$gap=5) {
28883 // NbCol = number of columns
28884 // CurrCol = Number of the current column starting at 0
28885 // Called externally to set columns on/off and number
28886 // Integer 2 upwards sets columns on to that number
28887 // Anything less than 2 turns columns off
28888 if ($NbCol<2) { // SET COLUMNS OFF
28889 if ($this->ColActive) {
28890 $this->ColActive=0;
28891 if (count($this->columnbuffer)) { $this->printcolumnbuffer(); }
28892 $this->NbCol=1;
28893 $this->ResetMargins();
28894 $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
28895 $this->divwidth = 0;
28896 $this->Ln();
28897 }
28898 $this->ColActive=0;
28899 $this->columnbuffer = array();
28900 $this->ColDetails = array();
28901 $this->columnLinks = array();
28902 $this->columnAnnots = array();
28903 $this->columnForms = array();
28904 $this->col_Reference = array();
28905 $this->col_BMoutlines = array();
28906 $this->col_toc = array();
28907 $this->breakpoints = array();
28908 }
28909 else { // SET COLUMNS ON
28910 if ($this->ColActive) {
28911 $this->ColActive=0;
28912 if (count($this->columnbuffer)) { $this->printcolumnbuffer(); }
28913 $this->ResetMargins();
28914 }
28915 if (isset($this->y) && $this->y>$this->tMargin) $this->Ln();
28916 $this->NbCol=$NbCol;
28917 $this->ColGap = $gap;
28918 $this->divwidth = 0;
28919 $this->ColActive=1;
28920 $this->ColumnAdjust = true; // enables column height adjustment for the page
28921 $this->columnbuffer = array();
28922 $this->ColDetails = array();
28923 $this->columnLinks = array();
28924 $this->columnAnnots = array();
28925 $this->columnForms = array();
28926 $this->col_Reference = array();
28927 $this->col_BMoutlines = array();
28928 $this->col_toc = array();
28929 $this->breakpoints = array();
28930 if ((strtoupper($vAlign) == 'J') || (strtoupper($vAlign) == 'JUSTIFY')) { $vAlign = 'J'; }
28931 else { $vAlign = ''; }
28932 $this->colvAlign = $vAlign;
28933 //Save the ordinate
28934 $absL = $this->DeflMargin-($gap/2);
28935 $absR = $this->DefrMargin-($gap/2);
28936 $PageWidth = $this->w-$absL-$absR; // virtual pagewidth for calculation only
28937 $ColWidth = (($PageWidth - ($gap * ($NbCol)))/$NbCol);
28938 $this->ColWidth = $ColWidth;
28939 /*-- RTL --*/
28940
28941 if ($this->directionality == 'rtl') {
28942 for ($i=0;$i<$this->NbCol;$i++) {
28943 $this->ColL[$i] = $absL + ($gap/2) + (($NbCol - ($i+1))*($PageWidth/$NbCol)) ;
28944 $this->ColR[$i] = $this->ColL[$i] + $ColWidth; // NB This is not R margin -> R pos
28945 }
28946 }
28947 else {
28948 /*-- END RTL --*/
28949 for ($i=0;$i<$this->NbCol;$i++) {
28950 $this->ColL[$i] = $absL + ($gap/2) + ($i* ($PageWidth/$NbCol) );
28951 $this->ColR[$i] = $this->ColL[$i] + $ColWidth; // NB This is not R margin -> R pos
28952 }
28953 } // *RTL*
28954 $this->pgwidth = $ColWidth;
28955 $this->SetCol(0);
28956 $this->y0=$this->y;
28957 }
28958 $this->x = $this->lMargin;
28959 }
28960
28961 function SetCol($CurrCol) {
28962 // Used internally to set column by number: 0 is 1st column
28963 //Set position on a column
28964 $this->CurrCol=$CurrCol;
28965 $x = $this->ColL[$CurrCol];
28966 $xR = $this->ColR[$CurrCol]; // NB This is not R margin -> R pos
28967 if (($this->mirrorMargins) && (($this->page)%2==0)) { // EVEN
28968 $x += $this->MarginCorrection ;
28969 $xR += $this->MarginCorrection ;
28970 }
28971 $this->SetMargins($x,($this->w - $xR),$this->tMargin);
28972 }
28973
28974 function AddColumn() {
28975 $this->NewColumn();
28976 $this->ColumnAdjust = false; // disables all column height adjustment for the page.
28977 }
28978 function NewColumn() {
28979 if ($this->ColActive==1) {
28980 if($this->CurrCol<$this->NbCol-1) {
28981 //Go to the next column
28982 $this->CurrCol++;
28983 $this->SetCol($this->CurrCol);
28984 $this->y = $this->y0;
28985 $this->ChangeColumn=1;
28986 // DIRECTIONALITY RTL
28987 if ($this->directionality == 'rtl') { $this->ChangeColumn = -($this->ChangeColumn); } // *RTL*
28988 //Stay on the page
28989 }
28990 else {
28991 //Go back to the first column
28992 //Page break
28993 if (count($this->columnbuffer)) { $this->printcolumnbuffer(); }
28994 $this->AddPage($this->CurOrientation);
28995 $this->SetCol(0);
28996 $this->y0 = $this->tMargin;
28997 $this->ChangeColumn= -($this->NbCol-1);
28998 // DIRECTIONALITY RTL
28999 if ($this->directionality == 'rtl') { $this->ChangeColumn = -($this->ChangeColumn); } // *RTL*
29000 }
29001 $this->x = $this->lMargin;
29002 }
29003 else {
29004 $this->AddPage($this->CurOrientation);
29005 }
29006 }
29007
29008 function printcolumnbuffer() {
29009 // Columns ended (but page not ended) -> try to match all columns - unless disabled by using a custom column-break
29010 if (!$this->ColActive && $this->ColumnAdjust && !$this->keepColumns) {
29011 // Calculate adjustment to add to each column to calculate rel_y value
29012 $this->ColDetails[0]['add_y'] = 0;
29013 $last_col = 0;
29014 // Recursively add previous column's height
29015 for($i=1;$i<$this->NbCol;$i++) {
29016 if (isset($this->ColDetails[$i]['bottom_margin']) && $this->ColDetails[$i]['bottom_margin']) { // If any entries in the column
29017 $this->ColDetails[$i]['add_y'] = ($this->ColDetails[$i-1]['bottom_margin'] - $this->y0) + $this->ColDetails[$i-1]['add_y'];
29018 $last_col = $i; // Last column actually printed
29019 }
29020 }
29021
29022 // Calculate value for each position sensitive entry as though for one column
29023 foreach($this->columnbuffer AS $key=>$s) {
29024 $t = $s['s'];
29025 if ($t == 'ACROFORM') {
29026 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29027 $this->columnbuffer[$key]['s'] = '';
29028 }
29029 else if (preg_match('/BT \d+\.\d\d+ (\d+\.\d\d+) Td/',$t)) {
29030 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29031 }
29032 else if (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ [\-]{0,1}\d+\.\d\d+ re/',$t)) {
29033 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29034 }
29035 else if (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) m/',$t)) {
29036 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29037 }
29038 else if (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) l/',$t)) {
29039 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29040 }
29041 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)) {
29042 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29043 }
29044 else if (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ c/',$t)) {
29045 $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0;
29046 }
29047 }
29048 foreach($this->internallink AS $key => $f) {
29049 if (is_array($f) && isset($f['col'])) {
29050 $this->internallink[$key]['rel_y'] = $f['Y'] + $this->ColDetails[$f['col']]['add_y'] - $this->y0;
29051 }
29052 }
29053
29054 $breaks = array();
29055 foreach($this->breakpoints AS $c => $bpa) {
29056 foreach($bpa AS $rely) {
29057 $breaks[] = $rely + $this->ColDetails[$c]['add_y'] - $this->y0;
29058 }
29059 }
29060
29061 if (isset($this->ColDetails[$last_col]['bottom_margin'])) { $lcbm = $this->ColDetails[$last_col]['bottom_margin']; }
29062 else { $lcbm = 0; }
29063 $sum_h = $this->ColDetails[$last_col]['add_y'] + $lcbm - $this->y0;
29064 //$sum_h = max($this->ColDetails[$last_col]['add_y'] + $this->ColDetails[$last_col]['bottom_margin'] - $this->y0, end($breaks));
29065 $target_h = ($sum_h / $this->NbCol);
29066
29067 $cbr = array();
29068 for($i=1;$i<$this->NbCol;$i++) {
29069 $th = ($sum_h * $i / $this->NbCol);
29070 foreach($breaks AS $bk=>$val) {
29071 if ($val > $th) {
29072 if (($val-$th) < ($th-$breaks[$bk-1])) { $cbr[$i-1] = $val; }
29073 else { $cbr[$i-1] = $breaks[$bk-1]; }
29074 break;
29075 }
29076 }
29077 }
29078 $cbr[($this->NbCol-1)] = $sum_h;
29079
29080 // Now update the columns - divide into columns of approximately equal value
29081 $last_new_col = 0;
29082 $yadj = 0; // mm
29083 $xadj = 0;
29084 $last_col_bottom = 0;
29085 $lowest_bottom_y = 0;
29086 $block_bottom = 0;
29087 $newcolumn = 0;
29088 foreach($this->columnbuffer AS $key=>$s) {
29089 if (isset($s['rel_y'])) { // only process position sensitive data
29090 if ($s['rel_y'] >= $cbr[$newcolumn]) {
29091 $newcolumn++;
29092 }
29093 else {
29094 $newcolumn = $last_new_col ;
29095 }
29096
29097
29098 $block_bottom = max($block_bottom,($s['rel_y']+$s['h']));
29099
29100 if ($this->directionality == 'rtl') { // *RTL*
29101 $xadj = -(($newcolumn - $s['col']) * ($this->ColWidth + $this->ColGap)); // *RTL*
29102 } // *RTL*
29103 else { // *RTL*
29104 $xadj = ($newcolumn - $s['col']) * ($this->ColWidth + $this->ColGap);
29105 } // *RTL*
29106
29107 if ($last_new_col != $newcolumn) { // Added new column
29108 $last_col_bottom = $this->columnbuffer[$key]['rel_y'];
29109 $block_bottom = 0;
29110 }
29111 $yadj = ($s['rel_y'] - $s['y']) - ($last_col_bottom)+$this->y0;
29112 // callback function
29113 $t = $s['s'];
29114
29115 // mPDF 5.7+
29116 $t = $this->columnAdjustPregReplace('Td', $xadj, $yadj, '/BT (\d+\.\d\d+) (\d+\.\d\d+) Td/', $t);
29117 $t = $this->columnAdjustPregReplace('re', $xadj, $yadj, '/(\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) ([\-]{0,1}\d+\.\d\d+) re/', $t);
29118 $t = $this->columnAdjustPregReplace('l', $xadj, $yadj, '/(\d+\.\d\d+) (\d+\.\d\d+) l/', $t);
29119 $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);
29120 $t = $this->columnAdjustPregReplace('draw', $xadj, $yadj, '/(\d+\.\d\d+) (\d+\.\d\d+) m/', $t);
29121 $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);
29122
29123 $this->columnbuffer[$key]['s'] = $t;
29124 $this->columnbuffer[$key]['newcol'] = $newcolumn;
29125 $this->columnbuffer[$key]['newy'] = $s['y'] + $yadj;
29126 $last_new_col = $newcolumn;
29127 $clb = $s['y'] + $yadj + $s['h'] ; // bottom_margin of current
29128 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; }
29129 if ($clb > $lowest_bottom_y) { $lowest_bottom_y = $clb; }
29130 // Adjust LINKS
29131 if (isset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29132 $ref = $this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29133 $this->PageLinks[$this->page][$ref][0] += ($xadj*_MPDFK);
29134 $this->PageLinks[$this->page][$ref][1] -= ($yadj*_MPDFK);
29135 unset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29136 }
29137 // Adjust FORM FIELDS
29138 if (isset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29139 $ref = $this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29140 $this->form->forms[$ref]['x'] += ($xadj);
29141 $this->form->forms[$ref]['y'] += ($yadj);
29142 unset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29143 }
29144 /*-- ANNOTATIONS --*/
29145 if (isset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29146 $ref = $this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29147 if ($this->PageAnnots[$this->page][$ref]['x'] < 0) {
29148 $this->PageAnnots[$this->page][$ref]['x'] -= ($xadj);
29149 }
29150 else {
29151 $this->PageAnnots[$this->page][$ref]['x'] += ($xadj);
29152 }
29153 $this->PageAnnots[$this->page][$ref]['y'] += ($yadj); // unlike PageLinks, Page annots has y values from top in mm
29154 unset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29155 }
29156 /*-- END ANNOTATIONS --*/
29157 }
29158 }
29159
29160 /*-- BOOKMARKS --*/
29161 // Adjust Bookmarks
29162 foreach($this->col_BMoutlines AS $v) {
29163 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$this->y0,'p'=>$v['p']);
29164 }
29165 /*-- END BOOKMARKS --*/
29166
29167 /*-- INDEX --*/
29168 // Adjust Reference (index)
29169 foreach($this->col_Reference AS $v) {
29170 $Present=0;
29171 //Search the reference (AND Ref/PageNo) in the array
29172 for ($i=0;$i<count($this->Reference);$i++){
29173 if ($this->Reference[$i]['t']==$v['t']){
29174 $Present=1;
29175 if (!in_array($v['op'],$this->Reference[$i]['p'])) {
29176 $this->Reference[$i]['p'][] = $v['op'];
29177 }
29178 }
29179 }
29180 if ($Present==0) {
29181 $this->Reference[]=array('t'=>$v['t'],'p'=>array($v['op']));
29182 }
29183 }
29184 /*-- END INDEX --*/
29185
29186 /*-- TOC --*/
29187
29188 // Adjust ToC
29189 foreach($this->col_toc AS $v) {
29190 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$v['p'],'link'=>$v['link'],'toc_id'=>$v['toc_id']);
29191 $this->links[$v['link']][1] = $this->y0;
29192 }
29193 /*-- END TOC --*/
29194
29195 // Adjust column length to be equal
29196 if ($this->colvAlign == 'J') {
29197 foreach($this->columnbuffer AS $key=>$s) {
29198 if (isset($s['rel_y'])) { // only process position sensitive data
29199 // Set ratio to expand y values or heights
29200 if (isset($this->ColDetails[$s['newcol']]['max_bottom']) && $this->ColDetails[$s['newcol']]['max_bottom'] && $this->ColDetails[$s['newcol']]['max_bottom']!=$this->y0) {
29201 $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['newcol']]['max_bottom'] - ($this->y0));
29202 }
29203 else { $ratio = 1; }
29204 if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) {
29205 $yadj = ($s['newy'] - $this->y0) * ($ratio - 1);
29206
29207 // Adjust LINKS
29208 if (isset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29209 $ref = $this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29210 $this->PageLinks[$this->page][$ref][1] -= ($yadj*_MPDFK); // y value
29211 $this->PageLinks[$this->page][$ref][3] *= $ratio; // height
29212 unset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29213 }
29214 // Adjust FORM FIELDS
29215 if (isset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29216 $ref = $this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29217 $this->form->forms[$ref]['x'] += ($xadj);
29218 $this->form->forms[$ref]['y'] += ($yadj);
29219 unset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29220 }
29221 /*-- ANNOTATIONS --*/
29222 if (isset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29223 $ref = $this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29224 $this->PageAnnots[$this->page][$ref]['y'] += ($yadj);
29225 unset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29226 }
29227 /*-- END ANNOTATIONS --*/
29228 }
29229 }
29230 }
29231 foreach($this->internallink AS $key => $f) {
29232 if (is_array($f) && isset($f['col'])) {
29233 $last_col_bottom = 0;
29234 for ($nbc=0; $nbc<$this->NbCol; $nbc++) {
29235 if ($f['rel_y'] >= $cbr[$nbc]) { $last_col_bottom = $cbr[$nbc]; }
29236 }
29237 $yadj = ($f['rel_y'] - $f['Y']) - $last_col_bottom + $this->y0;
29238 $f['Y'] += $yadj;
29239 unset($f['col']);
29240 unset($f['rel_y']);
29241 $this->internallink[$key] = $f;
29242 }
29243 }
29244
29245 $last_col = -1;
29246 $trans_on = false;
29247 foreach($this->columnbuffer AS $key=>$s) {
29248 if (isset($s['rel_y'])) { // only process position sensitive data
29249 // Set ratio to expand y values or heights
29250 if (isset($this->ColDetails[$s['newcol']]['max_bottom']) && $this->ColDetails[$s['newcol']]['max_bottom'] && $this->ColDetails[$s['newcol']]['max_bottom']!=$this->y0) {
29251 $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['newcol']]['max_bottom'] - ($this->y0));
29252 }
29253 else { $ratio = 1; }
29254 if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) {
29255 //Start Transformation
29256 $this->pages[$this->page] .= $this->StartTransform(true)."\n";
29257 $this->pages[$this->page] .= $this->transformScale(100, $ratio*100, $x='', $this->y0, true)."\n";
29258 $trans_on = true;
29259 }
29260 }
29261 // Now output the adjusted values
29262 $this->pages[$this->page] .= $s['s']."\n";
29263 if (isset($s['rel_y']) && ($ratio > 1) && ($ratio <= $this->max_colH_correction)) { // only process position sensitive data
29264 //Stop Transformation
29265 $this->pages[$this->page] .= $this->StopTransform(true)."\n";
29266 $trans_on = false;
29267 }
29268 }
29269 if ($trans_on) { $this->pages[$this->page] .= $this->StopTransform(true)."\n"; }
29270 }
29271 else { // if NOT $this->colvAlign == 'J'
29272 // Now output the adjusted values
29273 foreach($this->columnbuffer AS $s) {
29274 $this->pages[$this->page] .= $s['s']."\n";
29275 }
29276 }
29277 if ($lowest_bottom_y > 0) { $this->y = $lowest_bottom_y ; }
29278 }
29279
29280 // Columns not ended but new page -> align columns (can leave the columns alone - just tidy up the height)
29281 else if ($this->colvAlign == 'J' && $this->ColumnAdjust && !$this->keepColumns) {
29282 // calculate the lowest bottom margin
29283 $lowest_bottom_y = 0;
29284 foreach($this->columnbuffer AS $key=>$s) {
29285 // Only process output data
29286 $t = $s['s'];
29287 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)) ||
29288 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) l/',$t)) ||
29289 (preg_match('/q \d+\.\d\d+ 0 0 \d+\.\d\d+ \d+\.\d\d+ (\d+\.\d\d+) cm \/(I|FO)\d+ Do Q/',$t)) ||
29290 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) m/',$t)) ||
29291 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ c/',$t)) ) {
29292
29293 $clb = $s['y'] + $s['h'];
29294 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; }
29295 if ($clb > $lowest_bottom_y) { $lowest_bottom_y = $clb; }
29296 $this->columnbuffer[$key]['rel_y'] = $s['y']; // Marks position sensitive data to process later
29297 if ($t == 'ACROFORM') { $this->columnbuffer[$key]['s'] = ''; }
29298 }
29299 }
29300 // Adjust column length equal
29301 foreach($this->columnbuffer AS $key=>$s) {
29302 // Set ratio to expand y values or heights
29303 if (isset($this->ColDetails[$s['col']]['max_bottom']) && $this->ColDetails[$s['col']]['max_bottom']) {
29304 $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['col']]['max_bottom'] - ($this->y0));
29305 }
29306 else { $ratio = 1; }
29307 if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) {
29308 $yadj = ($s['y'] - $this->y0) * ($ratio - 1);
29309
29310 // Adjust LINKS
29311 if (isset($s['rel_y'])) { // only process position sensitive data
29312 // otherwise triggers for all entries in column buffer (.e.g. formatting) and makes below adjustments more than once
29313 if (isset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29314 $ref = $this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29315 $this->PageLinks[$this->page][$ref][1] -= ($yadj*_MPDFK); // y value
29316 $this->PageLinks[$this->page][$ref][3] *= $ratio; // height
29317 unset($this->columnLinks[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29318 }
29319 // Adjust FORM FIELDS
29320 if (isset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29321 $ref = $this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29322 $this->form->forms[$ref]['x'] += ($xadj);
29323 $this->form->forms[$ref]['y'] += ($yadj);
29324 unset($this->columnForms[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29325 }
29326 /*-- ANNOTATIONS --*/
29327 if (isset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])])) {
29328 $ref = $this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])];
29329 $this->PageAnnots[$this->page][$ref]['y'] += ($yadj);
29330 unset($this->columnAnnots[$s['col']][INTVAL($s['x'])][INTVAL($s['y'])]);
29331 }
29332 /*-- END ANNOTATIONS --*/
29333 }
29334 }
29335 }
29336
29337 /*-- BOOKMARKS --*/
29338
29339 // Adjust Bookmarks
29340 foreach($this->col_BMoutlines AS $v) {
29341 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$this->y0,'p'=>$v['p']);
29342 }
29343 /*-- END BOOKMARKS --*/
29344
29345 /*-- INDEX --*/
29346
29347 // Adjust Reference (index)
29348 foreach($this->col_Reference AS $v) {
29349 $Present=0;
29350 //Search the reference (AND Ref/PageNo) in the array
29351 for ($i=0;$i<count($this->Reference);$i++){
29352 if ($this->Reference[$i]['t']==$v['t']){
29353 $Present=1;
29354 if (!in_array($v['op'],$this->Reference[$i]['p'])) {
29355 $this->Reference[$i]['p'][] = $v['op'];
29356 }
29357 }
29358 }
29359 if ($Present==0) {
29360 $this->Reference[]=array('t'=>$v['t'],'p'=>array($v['op']));
29361 }
29362 }
29363 /*-- END INDEX --*/
29364
29365 /*-- TOC --*/
29366
29367 // Adjust ToC
29368 foreach($this->col_toc AS $v) {
29369 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$v['p'],'link'=>$v['link'],'toc_id'=>$v['toc_id']);
29370 $this->links[$v['link']][1] = $this->y0;
29371 }
29372 /*-- END TOC --*/
29373 $trans_on = false;
29374 foreach($this->columnbuffer AS $key=>$s) {
29375 if (isset($s['rel_y'])) { // only process position sensitive data
29376 // Set ratio to expand y values or heights
29377 if ($this->ColDetails[$s['col']]['max_bottom']) {
29378 $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['col']]['max_bottom'] - ($this->y0));
29379 }
29380 else { $ratio = 1; }
29381 if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) {
29382 //Start Transformation
29383 $this->pages[$this->page] .= $this->StartTransform(true)."\n";
29384 $this->pages[$this->page] .= $this->transformScale(100, $ratio*100, $x='', $this->y0, true)."\n";
29385 $trans_on = true;
29386 }
29387 }
29388 // Now output the adjusted values
29389 $this->pages[$this->page] .= $s['s']."\n";
29390 if (isset($s['rel_y']) && ($ratio > 1) && ($ratio <= $this->max_colH_correction)) {
29391 //Stop Transformation
29392 $this->pages[$this->page] .= $this->StopTransform(true)."\n";
29393 $trans_on = false; // mPDF 5.1.001
29394 }
29395 }
29396 if ($trans_on) { $this->pages[$this->page] .= $this->StopTransform(true)."\n"; }
29397
29398 if ($lowest_bottom_y > 0) { $this->y = $lowest_bottom_y ; }
29399 }
29400
29401
29402 // Just reproduce the page as it was
29403 else {
29404 // If page has not ended but height adjustment was disabled by custom column-break - adjust y
29405 $lowest_bottom_y = 0;
29406 if (!$this->ColActive && (!$this->ColumnAdjust || $this->keepColumns)) {
29407 // calculate the lowest bottom margin
29408 foreach($this->columnbuffer AS $key=>$s) {
29409 // Only process output data
29410 $t = $s['s'];
29411 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)) ||
29412 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) l/',$t)) ||
29413 (preg_match('/q \d+\.\d\d+ 0 0 \d+\.\d\d+ \d+\.\d\d+ (\d+\.\d\d+) cm \/(I|FO)\d+ Do Q/',$t)) ||
29414 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) m/',$t)) ||
29415 (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ c/',$t)) ) {
29416
29417 $clb = $s['y'] + $s['h'];
29418 if ($clb > $this->ColDetails[$s['col']]['max_bottom']) { $this->ColDetails[$s['col']]['max_bottom'] = $clb; }
29419 if ($clb > $lowest_bottom_y) { $lowest_bottom_y = $clb; }
29420 }
29421 }
29422 }
29423 foreach($this->columnbuffer AS $key=>$s) {
29424 if ($s['s'] != 'ACROFORM')
29425 $this->pages[$this->page] .= $s['s']."\n";
29426 }
29427 if ($lowest_bottom_y > 0) { $this->y = $lowest_bottom_y ; }
29428 /*-- INDEX --*/
29429
29430 // Output Reference (index)
29431 foreach($this->col_Reference AS $v) {
29432 $Present=0;
29433 for ($i=0;$i<count($this->Reference);$i++){
29434 if ($this->Reference[$i]['t']==$v['t']){
29435 $Present=1;
29436 if (!in_array($v['op'],$this->Reference[$i]['p'])) {
29437 $this->Reference[$i]['p'][] = $v['op'];
29438 }
29439 }
29440 }
29441 if ($Present==0) {
29442 $this->Reference[]=array('t'=>$v['t'],'p'=>array($v['op']));
29443 }
29444 }
29445 /*-- END INDEX --*/
29446 /*-- BOOKMARKS --*/
29447 // Output Bookmarks
29448 foreach($this->col_BMoutlines AS $v) {
29449 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$v['p']);
29450 }
29451 /*-- END BOOKMARKS --*/
29452 /*-- TOC --*/
29453 // Output ToC
29454 foreach($this->col_toc AS $v) {
29455 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$v['p'],'link'=>$v['link'],'toc_id'=>$v['toc_id']);
29456 }
29457 /*-- END TOC --*/
29458 }
29459 foreach($this->internallink AS $key => $f) {
29460 if (isset($this->internallink[$key]['col'])) unset($this->internallink[$key]['col']);
29461 if (isset($this->internallink[$key]['rel_y'])) unset($this->internallink[$key]['rel_y']);
29462 }
29463
29464 $this->columnbuffer = array();
29465 $this->ColDetails = array();
29466 $this->columnLinks = array();
29467 $this->columnAnnots = array();
29468 $this->columnForms = array();
29469
29470 $this->col_Reference = array();
29471 $this->col_BMoutlines = array();
29472 $this->col_toc = array();
29473 $this->breakpoints = array();
29474 }
29475
29476 // mPDF 5.7+
29477 function columnAdjustPregReplace($type, $xadj, $yadj, $pattern, $subject) {
29478 preg_match($pattern, $subject, $matches);
29479 if (!isset($matches[3])) { $matches[3] = 0; }
29480 if (!isset($matches[4])) { $matches[4] = 0; }
29481 if (!isset($matches[5])) { $matches[5] = 0; }
29482 if (!isset($matches[6])) { $matches[6] = 0; }
29483 return str_replace($matches[0], $this->columnAdjustAdd($type, _MPDFK, $xadj, $yadj, $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]), $subject);
29484 }
29485
29486 /*-- END COLUMNS --*/
29487
29488
29489 //==================================================================
29490 /*-- TABLES --*/
29491 function printcellbuffer() {
29492 if (count($this->cellBorderBuffer )) {
29493 sort($this->cellBorderBuffer);
29494 foreach($this->cellBorderBuffer AS $cbb) {
29495 $cba = unpack("A16dom/nbord/A1side/ns/dbw/a6ca/A10style/dx/dy/dw/dh/dmbl/dmbr/dmrt/dmrb/dmtl/dmtr/dmlt/dmlb/dcpd/dover/", $cbb);
29496 $side = $cba['side'];
29497 $details = array();
29498 $details[$side]['dom'] = (float) $cba['dom'];
29499 $details[$side]['s'] = $cba['s'];
29500 $details[$side]['w'] = $cba['bw'];
29501 $details[$side]['c'] = $cba['ca'];
29502 $details[$side]['style'] = trim($cba['style']);
29503 $details['mbw']['BL'] = $cba['mbl'];
29504 $details['mbw']['BR'] = $cba['mbr'];
29505 $details['mbw']['RT'] = $cba['mrt'];
29506 $details['mbw']['RB'] = $cba['mrb'];
29507 $details['mbw']['TL'] = $cba['mtl'];
29508 $details['mbw']['TR'] = $cba['mtr'];
29509 $details['mbw']['LT'] = $cba['mlt'];
29510 $details['mbw']['LB'] = $cba['mlb'];
29511 $details['cellposdom'] = $cba['cpd'];
29512 $details['p'] = $side;
29513 if ($cba['over']==1) { $details[$side]['overlay'] = true; }
29514 else { $details[$side]['overlay'] = false; }
29515 $this->_tableRect($cba['x'],$cba['y'],$cba['w'],$cba['h'],$cba['bord'],$details, false, false);
29516
29517 }
29518 $this->cellBorderBuffer = array();
29519 }
29520 }
29521 //==================================================================
29522 function printtablebuffer() {
29523
29524 if (!$this->table_rotate) {
29525 $this->pages[$this->page] .= $this->tablebuffer;
29526 foreach($this->tbrot_Links AS $p => $l) {
29527 foreach($l AS $v) {
29528 $this->PageLinks[$p][] = $v;
29529 }
29530 }
29531 $this->tbrot_Links = array();
29532 /*-- ANNOTATIONS --*/
29533 foreach($this->tbrot_Annots AS $p => $l) {
29534 foreach($l AS $v) {
29535 $this->PageAnnots[$p][] = $v;
29536 }
29537 }
29538 $this->tbrot_Annots = array();
29539 /*-- END ANNOTATIONS --*/
29540
29541 /*-- INDEX --*/
29542 // Output Reference (index)
29543 foreach($this->tbrot_Reference AS $v) {
29544 $Present=0;
29545 for ($i=0;$i<count($this->Reference);$i++){
29546 if ($this->Reference[$i]['t']==$v['t']){
29547 $Present=1;
29548 if (!in_array($v['op'],$this->Reference[$i]['p'])) {
29549 $this->Reference[$i]['p'][] = $v['op'];
29550 }
29551 }
29552 }
29553 if ($Present==0) {
29554 $this->Reference[]=array('t'=>$v['t'],'p'=>array($v['op']));
29555 }
29556 }
29557 $this->tbrot_Reference = array();
29558 /*-- END INDEX --*/
29559
29560 /*-- BOOKMARKS --*/
29561 // Output Bookmarks
29562 foreach($this->tbrot_BMoutlines AS $v) {
29563 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$v['p']);
29564 }
29565 $this->tbrot_BMoutlines = array();
29566 /*-- END BOOKMARKS --*/
29567
29568 /*-- TOC --*/
29569 // Output ToC
29570 foreach($this->tbrot_toc AS $v) {
29571 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$v['p'],'link'=>$v['link'],'toc_id'=>$v['toc_id']);
29572 }
29573 $this->tbrot_toc = array();
29574 /*-- END TOC --*/
29575
29576 return;
29577 }
29578 // else if rotated
29579 $lm = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_left'];
29580 $pw = $this->blk[$this->blklvl]['inner_width'];
29581 //Start Transformation
29582 $this->pages[$this->page] .= $this->StartTransform(true)."\n";
29583
29584 if ($this->table_rotate > 1) { // clockwise
29585 if ($this->tbrot_align == 'L') {
29586 $xadj = $this->tbrot_h ; // align L (as is)
29587 }
29588 else if ($this->tbrot_align == 'R') {
29589 $xadj = $lm-$this->tbrot_x0+($pw) ; // align R
29590 }
29591 else {
29592 $xadj = $lm-$this->tbrot_x0+(($pw + $this->tbrot_h)/2) ; // align C
29593 }
29594 $yadj = 0;
29595 }
29596 else { // anti-clockwise
29597 if ($this->tbrot_align == 'L') {
29598 $xadj = 0 ; // align L (as is)
29599 }
29600 else if ($this->tbrot_align == 'R') {
29601 $xadj = $lm-$this->tbrot_x0+($pw - $this->tbrot_h) ; // align R
29602 }
29603 else {
29604 $xadj = $lm-$this->tbrot_x0+(($pw - $this->tbrot_h)/2) ; // align C
29605 }
29606 $yadj = $this->tbrot_w;
29607 }
29608
29609
29610 $this->pages[$this->page] .= $this->transformTranslate($xadj, $yadj , true)."\n";
29611 $this->pages[$this->page] .= $this->transformRotate($this->table_rotate, $this->tbrot_x0 , $this->tbrot_y0 , true)."\n";
29612
29613 // Now output the adjusted values
29614 $this->pages[$this->page] .= $this->tablebuffer;
29615
29616
29617 foreach($this->tbrot_Links AS $p => $l) {
29618 foreach($l AS $v) {
29619 $w = $v[2]/_MPDFK;
29620 $h = $v[3]/_MPDFK;
29621 $ax = ($v[0]/_MPDFK) - $this->tbrot_x0;
29622 $ay = (($this->hPt-$v[1])/_MPDFK) - $this->tbrot_y0;
29623 if ($this->table_rotate > 1) { // clockwise
29624 $bx = $this->tbrot_x0+$xadj-$ay-$h;
29625 $by = $this->tbrot_y0+$yadj+$ax;
29626 }
29627 else {
29628 $bx = $this->tbrot_x0+$xadj+$ay;
29629 $by = $this->tbrot_y0+$yadj-$ax-$w;
29630 }
29631 $v[0] = $bx*_MPDFK;
29632 $v[1] = ($this->h-$by)*_MPDFK;
29633 $v[2] = $h*_MPDFK; // swap width and height
29634 $v[3] = $w*_MPDFK;
29635 $this->PageLinks[$p][] = $v;
29636 }
29637 }
29638 $this->tbrot_Links = array();
29639 foreach($this->internallink AS $key => $f) {
29640 if (is_array($f) && isset($f['tbrot'])) {
29641 $f['Y'] = $this->tbrot_y0;
29642 $f['PAGE'] = $this->page;
29643 unset($f['tbrot']);
29644 $this->internallink[$key] = $f;
29645 }
29646 }
29647 /*-- ANNOTATIONS --*/
29648 foreach($this->tbrot_Annots AS $p => $l) {
29649 foreach($l AS $v) {
29650 $ax = abs($v['x']) - $this->tbrot_x0; // abs because -ve values are internally set and held for reference if annotMargin set
29651 $ay = $v['y'] - $this->tbrot_y0;
29652 if ($this->table_rotate > 1) { // clockwise
29653 $bx = $this->tbrot_x0+$xadj-$ay;
29654 $by = $this->tbrot_y0+$yadj+$ax;
29655 }
29656 else {
29657 $bx = $this->tbrot_x0+$xadj+$ay;
29658 $by = $this->tbrot_y0+$yadj-$ax;
29659 }
29660 if ($v['x'] < 0) {
29661 $v['x'] = -$bx;
29662 }
29663 else {
29664 $v['x'] = $bx;
29665 }
29666 $v['y'] = ($by);
29667 $this->PageAnnots[$p][] = $v;
29668 }
29669 }
29670 $this->tbrot_Annots = array();
29671 /*-- END ANNOTATIONS --*/
29672
29673
29674 /*-- BOOKMARKS --*/
29675
29676 // Adjust Bookmarks
29677 foreach($this->tbrot_BMoutlines AS $v) {
29678 $v['y'] = $this->tbrot_y0;
29679 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$this->page);
29680 }
29681 /*-- END BOOKMARKS --*/
29682
29683 /*-- INDEX --*/
29684
29685 // Adjust Reference (index)
29686 foreach($this->tbrot_Reference AS $v) {
29687 $Present=0;
29688 //Search the reference (AND Ref/PageNo) in the array
29689 for ($i=0;$i<count($this->Reference);$i++){
29690 if ($this->Reference[$i]['t']==$v['t']){
29691 $Present=1;
29692 if (!in_array($this->page,$this->Reference[$i]['p'])) {
29693 $this->Reference[$i]['p'][] = $this->page;
29694 }
29695 }
29696 }
29697 if ($Present==0) {
29698 $this->Reference[]=array('t'=>$v['t'],'p'=>array($this->page));
29699 }
29700 }
29701 /*-- END INDEX --*/
29702
29703 /*-- TOC --*/
29704
29705 // Adjust ToC - uses document page number
29706 foreach($this->tbrot_toc AS $v) {
29707 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$this->page,'link'=>$v['link'],'toc_id'=>$v['toc_id']);
29708 $this->links[$v['link']][1] = $this->tbrot_y0;
29709 }
29710 /*-- END TOC --*/
29711
29712
29713
29714 $this->tbrot_Reference = array();
29715 $this->tbrot_BMoutlines = array();
29716 $this->tbrot_toc = array();
29717
29718 //Stop Transformation
29719 $this->pages[$this->page] .= $this->StopTransform(true)."\n";
29720
29721
29722 $this->y = $this->tbrot_y0 + $this->tbrot_w;
29723 $this->x = $this->lMargin;
29724
29725 $this->tablebuffer = '';
29726 }
29727
29728 //==================================================================
29729 // Keep-with-table This buffers contents of h1-6 to keep on page with table
29730 function printkwtbuffer() {
29731 if (!$this->kwt_moved) {
29732 foreach($this->kwt_buffer AS $s) { $this->pages[$this->page] .= $s['s']."\n"; }
29733 foreach($this->kwt_Links AS $p => $l) {
29734 foreach($l AS $v) {
29735 $this->PageLinks[$p][] = $v;
29736 }
29737 }
29738 $this->kwt_Links = array();
29739 /*-- ANNOTATIONS --*/
29740 foreach($this->kwt_Annots AS $p => $l) {
29741 foreach($l AS $v) {
29742 $this->PageAnnots[$p][] = $v;
29743 }
29744 }
29745 $this->kwt_Annots = array();
29746 /*-- END ANNOTATIONS --*/
29747
29748 /*-- INDEX --*/
29749 // Output Reference (index)
29750 foreach($this->kwt_Reference AS $v) {
29751 $Present=0;
29752 for ($i=0;$i<count($this->Reference);$i++){
29753 if ($this->Reference[$i]['t']==$v['t']){
29754 $Present=1;
29755 if (!in_array($v['op'],$this->Reference[$i]['p'])) {
29756 $this->Reference[$i]['p'][] = $v['op'];
29757 }
29758 }
29759 }
29760 if ($Present==0) {
29761 $this->Reference[]=array('t'=>$v['t'],'p'=>array($v['op']));
29762 }
29763 }
29764 $this->kwt_Reference = array();
29765 /*-- END INDEX --*/
29766
29767 /*-- BOOKMARKS --*/
29768 // Output Bookmarks
29769 foreach($this->kwt_BMoutlines AS $v) {
29770 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$v['p']);
29771 }
29772 $this->kwt_BMoutlines = array();
29773 /*-- END BOOKMARKS --*/
29774
29775 /*-- TOC --*/
29776 // Output ToC
29777 foreach($this->kwt_toc AS $v) {
29778 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$v['p'],'link'=>$v['link'],'toc_id'=>$v['toc_id']);
29779 }
29780 $this->kwt_toc = array();
29781 /*-- END TOC --*/
29782
29783 return;
29784 }
29785
29786 //Start Transformation
29787 $this->pages[$this->page] .= $this->StartTransform(true)."\n";
29788 $xadj = $this->lMargin - $this->kwt_x0 ;
29789 //$yadj = $this->y - $this->kwt_y0 ;
29790 $yadj = $this->tMargin - $this->kwt_y0 ;
29791
29792 $this->pages[$this->page] .= $this->transformTranslate($xadj, $yadj , true)."\n";
29793
29794 // Now output the adjusted values
29795 foreach($this->kwt_buffer AS $s) { $this->pages[$this->page] .= $s['s']."\n"; }
29796
29797 // Adjust hyperLinks
29798 foreach($this->kwt_Links AS $p => $l) {
29799 foreach($l AS $v) {
29800 $bx = $this->kwt_x0+$xadj;
29801 $by = $this->kwt_y0+$yadj;
29802 $v[0] = $bx*_MPDFK;
29803 $v[1] = ($this->h-$by)*_MPDFK;
29804 $this->PageLinks[$p][] = $v;
29805 }
29806 }
29807 foreach($this->internallink AS $key => $f) {
29808 if (is_array($f) && isset($f['kwt'])) {
29809 $f['Y'] += $yadj;
29810 $f['PAGE'] = $this->page;
29811 unset($f['kwt']);
29812 $this->internallink[$key] = $f;
29813 }
29814 }
29815 /*-- ANNOTATIONS --*/
29816 foreach($this->kwt_Annots AS $p => $l) {
29817 foreach($l AS $v) {
29818 $bx = $this->kwt_x0+$xadj;
29819 $by = $this->kwt_y0+$yadj;
29820 if ($v['x'] < 0) {
29821 $v['x'] = -$bx;
29822 }
29823 else {
29824 $v['x'] = $bx;
29825 }
29826 $v['y'] = $by;
29827 $this->PageAnnots[$p][] = $v;
29828 }
29829 }
29830 /*-- END ANNOTATIONS --*/
29831
29832 /*-- BOOKMARKS --*/
29833
29834 // Adjust Bookmarks
29835 foreach($this->kwt_BMoutlines AS $v) {
29836 if ($v['y'] != 0) { $v['y'] += $yadj; }
29837 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$this->page);
29838 }
29839 /*-- END BOOKMARKS --*/
29840
29841 /*-- INDEX --*/
29842
29843 // Adjust Reference (index)
29844 foreach($this->kwt_Reference AS $v) {
29845 $Present=0;
29846 //Search the reference (AND Ref/PageNo) in the array
29847 for ($i=0;$i<count($this->Reference);$i++){
29848 if ($this->Reference[$i]['t']==$v['t']){
29849 $Present=1;
29850 if (!in_array($this->page,$this->Reference[$i]['p'])) {
29851 $this->Reference[$i]['p'][] = $this->page;
29852 }
29853 }
29854 }
29855 if ($Present==0) {
29856 $this->Reference[]=array('t'=>$v['t'],'p'=>array($this->page));
29857 }
29858 }
29859 /*-- END INDEX --*/
29860
29861 /*-- TOC --*/
29862
29863 // Adjust ToC
29864 foreach($this->kwt_toc AS $v) {
29865 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$this->page,'link'=>$v['link'],'toc_id'=>$v['toc_id']);
29866 $this->links[$v['link']][0] = $this->page;
29867 $this->links[$v['link']][1] += $yadj;
29868 }
29869 /*-- END TOC --*/
29870
29871
29872 $this->kwt_Links = array();
29873 $this->kwt_Annots = array();
29874
29875 $this->kwt_Reference = array();
29876 $this->kwt_BMoutlines = array();
29877 $this->kwt_toc = array();
29878 //Stop Transformation
29879 $this->pages[$this->page] .= $this->StopTransform(true)."\n";
29880
29881 $this->kwt_buffer = array();
29882
29883 $this->y += $this->kwt_height;
29884 }
29885
29886 /*-- END TABLES --*/
29887
29888
29889 //==================================================================
29890
29891 function printfloatbuffer() {
29892 if (count($this->floatbuffer)) {
29893 $this->objectbuffer = $this->floatbuffer;
29894 $this->printobjectbuffer(false);
29895 $this->objectbuffer = array();
29896 $this->floatbuffer = array();
29897 $this->floatmargins = array();
29898 }
29899 }
29900 //==================================================================
29901
29902 function printdivbuffer() {
29903 $p1 = $this->blk[$this->blklvl]['startpage'];
29904 $p2 = $this->page;
29905 $bottom[$p1] = $this->ktBlock[$p1]['bottom_margin'];
29906 $bottom[$p2] = $this->y; // $this->ktBlock[$p2]['bottom_margin'];
29907 $top[$p1] = $this->kt_y00;
29908
29909 $top2 = $this->h;
29910 foreach($this->divbuffer AS $key=>$s) {
29911 if ($s['page'] == $p2) {
29912 $top2 = MIN($s['y'], $top2);
29913 }
29914 }
29915 $top[$p2] = $top2;
29916 $height[$p1] = ($bottom[$p1] - $top[$p1]);
29917 $height[$p2] = ($bottom[$p2] - $top[$p2]);
29918 $xadj[$p1] = $this->MarginCorrection;
29919 $yadj[$p1] = -($top[$p1] - $top[$p2]);
29920 $xadj[$p2] = 0;
29921 $yadj[$p2] = $height[$p1];
29922
29923 // Output without any transformation
29924 if ($this->ColActive || !$this->keep_block_together || $this->blk[$this->blklvl]['startpage'] == $this->page || ($this->page - $this->blk[$this->blklvl]['startpage']) > 1 || ($height[$p1]+$height[$p2]) > $this->h) {
29925 foreach($this->divbuffer AS $s) { $this->pages[$s['page']] .= $s['s']."\n"; }
29926 foreach($this->ktLinks AS $p => $l) {
29927 foreach($l AS $v) {
29928 $this->PageLinks[$p][] = $v;
29929 }
29930 }
29931 foreach($this->ktForms AS $key => $f) {
29932 $this->form->forms[$f['n']] = $f;
29933 }
29934 /*-- ANNOTATIONS --*/
29935 foreach($this->ktAnnots AS $p => $l) {
29936 foreach($l AS $v) {
29937 $this->PageAnnots[$p][] = $v;
29938 }
29939 }
29940 /*-- END ANNOTATIONS --*/
29941 /*-- INDEX --*/
29942 // Adjust Reference (index)
29943 foreach($this->ktReference AS $v) {
29944 $Present=0;
29945 //Search the reference (AND Ref/PageNo) in the array
29946 for ($i=0;$i<count($this->Reference);$i++){
29947 if ($this->Reference[$i]['t']==$v['t']){
29948 $Present=1;
29949 if (!in_array($p2,$this->Reference[$i]['p'])) {
29950 $this->Reference[$i]['p'][] = $p2;
29951 }
29952 }
29953 }
29954 //If not found, add it
29955 if ($Present==0) {
29956 $this->Reference[]=array('t'=>$v['t'],'p'=>array($p2));
29957 }
29958 }
29959 /*-- END INDEX --*/
29960
29961 /*-- BOOKMARKS --*/
29962 // Adjust Bookmarks
29963 foreach($this->ktBMoutlines AS $v) {
29964 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$v['p']);
29965 }
29966 /*-- END BOOKMARKS --*/
29967
29968 /*-- TOC --*/
29969 // Adjust ToC
29970 foreach($this->_kttoc AS $v) {
29971 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$v['p'],'link'=>$v['link'],'toc_id'=>$v['toc_id']);
29972 }
29973 /*-- END TOC --*/
29974
29975 $this->divbuffer = array();
29976 $this->ktLinks = array();
29977 $this->ktAnnots = array();
29978 $this->ktForms = array();
29979 $this->ktBlock = array();
29980 $this->ktReference = array();
29981 $this->ktBMoutlines = array();
29982 $this->_kttoc = array();
29983 $this->keep_block_together = 0;
29984 return;
29985 }
29986 else {
29987 // Output with transformation
29988 // mPDF 5.6.17
29989 $np = '';
29990 $lastpage = -1;
29991 foreach($this->divbuffer AS $key=>$s) {
29992 // callback function
29993 $t = $s['s'];
29994 $p = $s['page'];
29995 if ($p != $lastpage) {
29996 $q = '';
29997 if ($lastpage != -1) { $q = ' Q'."\n"; }
29998 $t = $q . $this->StartTransform(true)."\n" . $this->transformTranslate($xadj[$p], $yadj[$p] , true)."\n" . $t;
29999 $lastpage = $p;
30000 }
30001 $np .= $t."\n";
30002 }
30003 if ($lastpage != -1) { $np .= ' Q'."\n"; }
30004
30005 $this->pages[$this->page] .= $np;
30006
30007 // Adjust hyperLinks
30008 foreach($this->ktLinks AS $p => $l) {
30009 foreach($l AS $v) {
30010 $v[0] += ($xadj[$p]*_MPDFK);
30011 $v[1] -= ($yadj[$p]*_MPDFK);
30012 $this->PageLinks[$p2][] = $v;
30013 }
30014 }
30015 foreach($this->ktForms AS $key => $f) {
30016 $p = $f['page'];
30017 $f['x'] += ($xadj[$p]);
30018 $f['y'] += ($yadj[$p]);
30019 $f['page'] = $p2;
30020 $this->form->forms[$f['n']] = $f;
30021 }
30022 foreach($this->internallink AS $key => $f) {
30023 if (is_array($f) && isset($f['kt'])) {
30024 $f['Y'] += ($yadj[$f['PAGE']]);
30025 $f['PAGE'] = $p2;
30026 unset($f['kt']);
30027 $this->internallink[$key] = $f;
30028 }
30029 }
30030 /*-- ANNOTATIONS --*/
30031 foreach($this->ktAnnots AS $p => $l) {
30032 foreach($l AS $v) {
30033 if ($v['x']>0) { $v['x'] += $xadj[$p]; }
30034 else if ($v['x']<0) { $v['x'] -= $xadj[$p]; }
30035 $v['y'] += $yadj[$p];
30036 $this->PageAnnots[$p2][] = $v;
30037 }
30038 }
30039 /*-- END ANNOTATIONS --*/
30040
30041 /*-- BOOKMARKS --*/
30042 // Adjust Bookmarks
30043 foreach($this->ktBMoutlines AS $v) {
30044 if ($v['y'] != 0) { $v['y'] += ($yadj[$v['p']]); }
30045 $this->BMoutlines[]=array('t'=>$v['t'],'l'=>$v['l'],'y'=>$v['y'],'p'=>$p2);
30046 }
30047 /*-- END BOOKMARKS --*/
30048
30049 /*-- INDEX --*/
30050 // Adjust Reference (index)
30051 foreach($this->ktReference AS $v) {
30052 $Present=0;
30053 //Search the reference (AND Ref/PageNo) in the array
30054 for ($i=0;$i<count($this->Reference);$i++){
30055 if ($this->Reference[$i]['t']==$v['t']){
30056 $Present=1;
30057 if (!in_array($p2,$this->Reference[$i]['p'])) {
30058 $this->Reference[$i]['p'][] = $p2;
30059 }
30060 }
30061 }
30062 //If not found, add it
30063 if ($Present==0) {
30064 $this->Reference[]=array('t'=>$v['t'],'p'=>array($p2));
30065 }
30066 }
30067 /*-- END INDEX --*/
30068
30069 /*-- TOC --*/
30070 // Adjust ToC
30071 foreach($this->_kttoc AS $v) {
30072 $this->tocontents->_toc[]=array('t'=>$v['t'],'l'=>$v['l'],'p'=>$p2,'link'=>$v['link'],'toc_id'=>$v['toc_id']);
30073 $this->links[$v['link']][0] = $p2;
30074 $this->links[$v['link']][1] += $yadj[$v['p']];
30075 }
30076 /*-- END TOC --*/
30077
30078 $this->y = $top[$p2] + $height[$p1] + $height[$p2];
30079 $this->x = $this->lMargin;
30080
30081 $this->divbuffer = array();
30082 $this->ktLinks = array();
30083 $this->ktAnnots = array();
30084 $this->ktForms = array();
30085 $this->ktBlock = array();
30086 $this->ktReference = array();
30087 $this->ktBMoutlines = array();
30088 $this->_kttoc = array();
30089 $this->keep_block_together = 0;
30090 }
30091 }
30092
30093
30094 //==================================================================
30095 // Added ELLIPSES and CIRCLES
30096 function Circle($x,$y,$r,$style='S') {
30097 $this->Ellipse($x,$y,$r,$r,$style);
30098 }
30099
30100 function Ellipse($x,$y,$rx,$ry,$style='S') {
30101 if($style=='F') { $op='f'; }
30102 elseif($style=='FD' or $style=='DF') { $op='B'; }
30103 else { $op='S'; }
30104 $lx=4/3*(M_SQRT2-1)*$rx;
30105 $ly=4/3*(M_SQRT2-1)*$ry;
30106 $h=$this->h;
30107 $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));
30108 $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));
30109 $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));
30110 $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));
30111 }
30112
30113 /*-- DIRECTW --*/
30114 // Added adaptation of shaded_box = AUTOSIZE-TEXT
30115 function AutosizeText($text,$w,$font,$style,$szfont=72) {
30116 $text = $this->purify_utf8_text($text);
30117 if ($this->text_input_as_HTML) {
30118 $text = $this->all_entities_to_utf8($text);
30119 }
30120 if ($this->usingCoreFont) { $text = mb_convert_encoding($text,$this->mb_enc,'UTF-8'); }
30121 $text = ' '.$text.' ';
30122 $width = $this->ConvertSize($w);
30123 $loop = 0;
30124 while ( $loop == 0 ) {
30125 $this->SetFont($font,$style,$szfont);
30126 $sz = $this->GetStringWidth( $text );
30127 if ( $sz > $w ) { $szfont --; }
30128 else { $loop ++; }
30129 }
30130 $this->SetFont($font,$style,$szfont);
30131 $this->Cell($w, 0, $text, 0, 0, "C");
30132 }
30133 /*-- END DIRECTW --*/
30134
30135
30136
30137
30138
30139 // ====================================================
30140 // ====================================================
30141 /*-- RTL --*/
30142 function reverse_letters($str) {
30143 $str = strtr($str, '{}[]()', '}{][)(');
30144 return $this->mb_strrev($str, $this->mb_enc);
30145 }
30146
30147 // mPDF 5.7+
30148 function reverse_letters_preg_callback($matches) {
30149 return $this->reverse_letters($matches[1]);
30150 }
30151
30152 function magic_reverse_dir(&$chunk, $join=true, $dir) {
30153 if ($this->usingCoreFont) { return 0; }
30154 if ($this->biDirectional) {
30155 // mPDF 5.4.05 Include PUA for non-indexed Arabic glyphs
30156 $pregRTLchars = $this->pregRTLchars;
30157 if ($this->CurrentFont['unAGlyphs']) { $pregRTLchars .= "\x{F500}-\x{F7FF}"; }
30158
30159 // Change Arabic + Persian. to Presentation Forms
30160 if ($join) {
30161 $chunk = preg_replace_callback("/([".$pregRTLchars."]+)/u", array($this, 'arabJoinPregCallback'), $chunk ); // mPDF 5.7+
30162 }
30163 $contains_rtl = false;
30164 $all_rtl = true;
30165 $initSpace = false;
30166 $endSpace = false;
30167 $nonDirchars = "\x{A0}\"\'\(\)\{\}\[\].,:\\/-="; // mPDF 5.6.32
30168 // mPDF 5.6.43
30169 $bdo=array();
30170 preg_match_all('/([\x{202A}\x{202B}])(.*?)([\x{202C}])/u',$chunk,$m);
30171 if (count($m[0])) {
30172 for($i=0;$i<count($m[0]);$i++) {
30173 if ($m[1][$i]=="\xe2\x80\xab") { // Right-to-Left Embedding [RLE] U+202B &#8235;
30174 $mark = code2utf(0xf800+$i);
30175 $bdo[$i] = $this->reverse_letters($m[2][$i]);
30176 }
30177 else if ($m[1][$i]=="\xe2\x80\xaa") { // Left-to-Right Embedding [LRE] U+202A &#8234;
30178 $mark = code2utf(0xf880+$i);
30179 $bdo[$i] = $m[2][$i];
30180 }
30181 $chunk = preg_replace('/'.preg_quote($m[0][$i],'/').'/u',$mark,$chunk);
30182 }
30183 $pregRTLchars .= "\x{F800}-\x{F87F}";
30184 }
30185 if (preg_match("/[".$pregRTLchars."]/u",$chunk)) { // Chunk contains RTL characters
30186 if (preg_match("/^[ ]/",$chunk)) { $initSpace = true; $chunk = preg_replace("/^[ ]/",'',$chunk); }
30187 if (preg_match("/[ ]$/",$chunk)) { $endSpace = true; $chunk = preg_replace("/[ ]$/",'',$chunk); }
30188
30189 if (preg_match("/[^".$pregRTLchars.$nonDirchars." ]/u",$chunk)) { // Chunk also contains LTR characters
30190 $all_rtl = false;
30191 if ($dir == 'rtl') {
30192 $chunk = preg_replace("/([^".$pregRTLchars.$nonDirchars."][".$nonDirchars."]*) ([".$nonDirchars."]*[^".$pregRTLchars.$nonDirchars."])/u","\\1\x07\\2",$chunk);
30193 }
30194 $chunk = preg_replace("/([".$pregRTLchars."][".$nonDirchars."]*) ([".$nonDirchars."]*[".$pregRTLchars."])/u","\\1\x07\\2",$chunk);
30195 $bits = explode(' ',$chunk);
30196 foreach($bits AS $bitkey=>$bit) {
30197 $bit = preg_replace("/\x07/"," ",$bit);
30198 if (preg_match("/^[".$pregRTLchars.$nonDirchars." ]*$/u",$bit)) {
30199 $bits[$bitkey] = $this->reverse_letters($bit);
30200 }
30201 else if (preg_match("/[".$pregRTLchars."]/u",$bit)) {
30202 if ($dir == 'rtl') {
30203 $bit = preg_replace("/([^".$pregRTLchars.$nonDirchars." ])([".$nonDirchars."]*[".$pregRTLchars."])/u","\\1\x07\\2",$bit );
30204 $bit = preg_replace("/([".$pregRTLchars."][".$nonDirchars."]*)([^".$pregRTLchars.$nonDirchars." ])/u","\\1\x07\\2",$bit );
30205 }
30206 else {
30207 $bit = preg_replace("/([^".$pregRTLchars." ][".$nonDirchars."]*)([".$pregRTLchars." ])/u","\\1\x07\\2",$bit );
30208 $bit = preg_replace("/([".$pregRTLchars." ])([".$nonDirchars."]*[^".$pregRTLchars." ])/u","\\1\x07\\2",$bit );
30209 }
30210 $sbits = explode("\x07",$bit );
30211 foreach($sbits AS $sbitkey=>$sbit) {
30212 $sbit = preg_replace("/\x07/","",$sbit);
30213 if (preg_match("/^[".$pregRTLchars.$nonDirchars." ]*$/u",$sbit)) {
30214 $sbits[$sbitkey] = $this->reverse_letters($sbit);
30215 }
30216 else if (preg_match("/[".$pregRTLchars."]/u",$sbit) && $dir=='rtl') {
30217 $sbits[$sbitkey] = $this->reverse_letters($sbit);
30218 }
30219 else {
30220 // Reverse numerals only to RTL
30221 $sbit = preg_replace_callback("/([\x{0660}-\x{066C}0-9]+[\x{0660}-\x{066C}0-9\.,:\/]*[\x{0660}-\x{066C}0-9]+)/u", array($this, 'reverse_letters_preg_callback'), $sbit ); // mPDF 5.7+
30222 $sbits[$sbitkey] = $sbit;
30223 }
30224 }
30225 if ($dir == 'rtl') { $sbits = array_reverse($sbits,false); }
30226 $bits[$bitkey] = implode('',$sbits);
30227 }
30228 else if (preg_match("/[".$pregRTLchars."]/u",$bit) && $dir=='rtl') {
30229 $bits[$bitkey] = $this->reverse_letters($bit);
30230 }
30231 else {
30232 // Reverse numerals only to RTL
30233 $bit = preg_replace("/([\x{0660}-\x{066C}0-9]+[\x{0660}-\x{066C}0-9\.,:\/]*[\x{0660}-\x{066C}0-9]+)/ue", '$this->reverse_letters(\'\\1\')', $bit ); // mPDF 5.6.32 // mPDF 5.6.46
30234 $bit = preg_replace_callback("/([\x{0660}-\x{066C}0-9]+[\x{0660}-\x{066C}0-9\.,:\/]*[\x{0660}-\x{066C}0-9]+)/u", array($this, 'reverse_letters_preg_callback'), $bit ); // mPDF 5.7+
30235 $bits[$bitkey] = $bit;
30236 }
30237 }
30238 if ($dir == 'rtl') { $bits = array_reverse($bits,false); }
30239 $chunk = implode(' ',$bits);
30240 }
30241 else { $chunk = $this->reverse_letters($chunk); }
30242 $contains_rtl = true;
30243
30244 // Un-Reverse numerals back to ltr
30245 $chunk = preg_replace_callback("/([\x{0660}-\x{066C}0-9]+[\x{0660}-\x{066C}0-9\.,:\/]*[\x{0660}-\x{066C}0-9]+)/u", array($this, 'reverse_letters_preg_callback'), $chunk ); // mPDF 5.7+
30246 if ($dir == 'rtl') {
30247 if ($endSpace) { $chunk = ' '.$chunk; }
30248 if ($initSpace) { $chunk .= ' '; }
30249 }
30250 else {
30251 if ($initSpace) { $chunk = ' '.$chunk; }
30252 if ($endSpace) { $chunk .= ' '; }
30253 }
30254 }
30255 else { $all_rtl = false; }
30256
30257 // mPDF 5.6.43
30258 if (count($bdo)) {
30259 for($i=0;$i<count($bdo);$i++) {
30260 $chunk = preg_replace('/[\x{'.dechex(intval(0xf800+$i)).'}\x{'.dechex(intval(0xf880+$i)).'}]/u',$bdo[$i],$chunk);
30261 }
30262 }
30263
30264 if ($all_rtl) { return 2; }
30265 else if ($contains_rtl) { return 1; }
30266 else { return 0; }
30267 }
30268 return 0;
30269 }
30270 /*-- END RTL --*/
30271
30272 //
30273 // ****************************
30274 // ****************************
30275
30276
30277 function SetSubstitutions() {
30278 $subsarray = array();
30279 @include(_MPDF_PATH.'includes/subs_win-1252.php');
30280 $this->substitute = array();
30281 foreach($subsarray AS $key => $val) {
30282 $this->substitute[code2utf($key)] = $val;
30283 }
30284 }
30285
30286
30287 function SubstituteChars($html) {
30288 // only substitute characters between tags
30289 if (count($this->substitute)) {
30290 $a=preg_split('/(<.*?>)/ms',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
30291 $html = '';
30292 foreach($a as $i => $e) {
30293 if($i%2==0) {
30294 $e = strtr($e, $this->substitute);
30295 }
30296 $html .= $e;
30297 }
30298 }
30299 return $html;
30300 }
30301
30302
30303 function SubstituteCharsSIP(&$writehtml_a, &$writehtml_i, &$writehtml_e) {
30304 if (preg_match("/^(.*?)([\x{20000}-\x{2FFFF}]+)(.*)/u", $writehtml_e, $m)) {
30305 if (isset($this->CurrentFont['sipext']) && $this->CurrentFont['sipext']) {
30306 $font = $this->CurrentFont['sipext'];
30307 if (!in_array($font, $this->available_unifonts)) { return 0; }
30308 $writehtml_a[$writehtml_i] = $writehtml_e = $m[1];
30309 array_splice($writehtml_a, $writehtml_i+1, 0, array('span style="font-family: '.$font.'"', $m[2], '/span', $m[3]));
30310 $this->subPos = $writehtml_i;
30311 return 4;
30312 }
30313 }
30314 return 0;
30315 }
30316
30317 // If core font is selected in document which is not onlyCoreFonts - substitute with non-core font
30318 function SubstituteCharsNonCore(&$writehtml_a, &$writehtml_i, &$writehtml_e) {
30319 if (mb_convert_encoding(mb_convert_encoding($writehtml_e, $this->mb_enc, "UTF-8"), "UTF-8", $this->mb_enc) == $writehtml_e) {
30320 return 0;
30321 }
30322 $cw = &$this->CurrentFont['cw'];
30323 $unicode = $this->UTF8StringToArray($writehtml_e, false);
30324 $start = -1;
30325 $end = 0;
30326 $flag = 0;
30327 $ftype = '';
30328 $u = array();
30329 if (!$this->subArrMB) {
30330 include(_MPDF_PATH.'includes/subs_core.php');
30331 $this->subArrMB['a'] = $aarr;
30332 $this->subArrMB['s'] = $sarr;
30333 $this->subArrMB['z'] = $zarr;
30334 }
30335 foreach($unicode AS $c => $char) {
30336 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)) {
30337 if ($flag==0) { $start=$c; }
30338 $flag=1;
30339 $u[] = $char;
30340 }
30341 else if ($flag>0) { $end=$c-1; break; }
30342 }
30343 if ($flag>0 && !$end) { $end=count($unicode)-1; }
30344 if ($start==-1) { return 0; }
30345 // TRY IN BACKUP SUBS FONT
30346 if (!is_array($this->backupSubsFont)) { $this->backupSubsFont = array("$this->backupSubsFont"); }
30347 foreach($this->backupSubsFont AS $bsfctr=>$bsf) {
30348 if ($this->fonttrans[$bsf] == 'chelvetica' || $this->fonttrans[$bsf] == 'ctimes' || $this->fonttrans[$bsf] == 'ccourier') { continue; }
30349 $font = $bsf;
30350 unset($cw);
30351 $cw = '';
30352 if (isset($this->fonts[$font])) { $cw = &$this->fonts[$font]['cw']; }
30353 else if (file_exists(_MPDF_TTFONTDATAPATH.$font.'.cw.dat')) { $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat'); }
30354 else {
30355
30356 $prevFontFamily = $this->FontFamily;
30357 $prevFontStyle = $this->currentfontstyle;
30358 $prevFontSizePt = $this->FontSizePt;
30359 $this->SetFont($bsf, '', '', false);
30360 $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat');
30361 $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false);
30362 }
30363 if (!$cw) { continue; }
30364 $l = 0;
30365 foreach($u AS $char) {
30366 if ($char == 173 || $this->_charDefined($cw,$char) || ($char>1536 && $char<1791) || ($char>2304 && $char<3455 )) {
30367 $l++;
30368 }
30369 else {
30370 if ($l==0 && $bsfctr == (count($this->backupSubsFont)-1)) { // Not found even in last backup font
30371 $cont = mb_substr($writehtml_e, $start+1);
30372 $writehtml_e = mb_substr($writehtml_e, 0, $start+1, 'UTF-8');
30373 array_splice($writehtml_a, $writehtml_i+1, 0, array('', $cont));
30374 $this->subPos = $writehtml_i+1;
30375 return 2;
30376 }
30377 else { break; }
30378 }
30379 }
30380 if ($l > 0) {
30381 $patt = mb_substr($writehtml_e, $start, $l, 'UTF-8');
30382 if (preg_match("/(.*?)(".preg_quote($patt,'/').")(.*)/u", $writehtml_e, $m)) {
30383 $writehtml_e = $m[1];
30384 array_splice($writehtml_a, $writehtml_i+1, 0, array('span style="font-family: '.$font.'"', $m[2], '/span', $m[3]));
30385 $this->subPos = $writehtml_i+3;
30386 return 4;
30387 }
30388 }
30389 }
30390
30391 unset($cw);
30392 return 0;
30393 }
30394
30395
30396 function SubstituteCharsMB(&$writehtml_a, &$writehtml_i, &$writehtml_e) {
30397 $cw = &$this->CurrentFont['cw'];
30398 $unicode = $this->UTF8StringToArray($writehtml_e, false);
30399 $start = -1;
30400 $end = 0;
30401 $flag = 0;
30402 $ftype = '';
30403 $u = array();
30404 foreach($unicode AS $c => $char) {
30405 if (($flag == 0 || $flag==2) && (!$this->_charDefined($cw,$char) || ($flag==2 && $char==32)) && $this->checkSIP && $char > 131071) { // Unicode Plane 2 (SIP)
30406 if (in_array($this->FontFamily ,$this->available_CJK_fonts)) { return 0; }
30407 if ($flag==0) { $start=$c; }
30408 $flag=2;
30409 $u[] = $char;
30410 }
30411 //else if (($flag == 0 || $flag==1) && $char != 173 && !$this->_charDefined($cw,$char) && ($char<1423 || ($char>3583 && $char < 11263))) {
30412 else if (($flag == 0 || $flag==1) && $char != 173 && (!$this->_charDefined($cw,$char) || ($flag==1 && $char==32)) && ($char<1536 || ($char>1791 && $char < 2304) || $char>3455)) {
30413 if ($flag==0) { $start=$c; }
30414 $flag=1;
30415 $u[] = $char;
30416 }
30417 else if ($flag>0) { $end=$c-1; break; }
30418 }
30419 if ($flag>0 && !$end) { $end=count($unicode)-1; }
30420 if ($start==-1) { return 0; }
30421 if ($flag == 2) { // SIP
30422 // Check if current CJK font has a ext-B related font
30423 if (isset($this->CurrentFont['sipext']) && $this->CurrentFont['sipext']) {
30424 $font = $this->CurrentFont['sipext'];
30425 unset($cw);
30426 $cw = '';
30427 if (isset($this->fonts[$font])) { $cw = &$this->fonts[$font]['cw']; }
30428 else if (file_exists(_MPDF_TTFONTDATAPATH.$font.'.cw.dat')) { $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat'); }
30429 else {
30430 $prevFontFamily = $this->FontFamily;
30431 $prevFontStyle = $this->currentfontstyle;
30432 $prevFontSizePt = $this->FontSizePt;
30433 $this->SetFont($font, '', '', false);
30434 $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat');
30435 $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false);
30436 }
30437 if (!$cw) { return 0; }
30438 $l = 0;
30439 foreach($u AS $char) {
30440 if ($this->_charDefined($cw,$char) || $char > 131071) {
30441 $l++;
30442 }
30443 else { break; }
30444 }
30445 if ($l > 0) {
30446 $patt = mb_substr($writehtml_e, $start, $l);
30447 if (preg_match("/(.*?)(".preg_quote($patt,'/').")(.*)/u", $writehtml_e, $m)) {
30448 $writehtml_e = $m[1];
30449 array_splice($writehtml_a, $writehtml_i+1, 0, array('span style="font-family: '.$font.'"', $m[2], '/span', $m[3]));
30450 $this->subPos = $writehtml_i+3;
30451 return 4;
30452 }
30453 }
30454 }
30455 // Check Backup SIP font (defined in config_fonts.php)
30456 if (isset($this->backupSIPFont) && $this->backupSIPFont) {
30457 if ($this->currentfontfamily != $this->backupSIPFont) { $font = $this->backupSIPFont; }
30458 else { unset($cw); return 0; }
30459 unset($cw);
30460 $cw = '';
30461 if (isset($this->fonts[$font])) { $cw = &$this->fonts[$font]['cw']; }
30462 else if (file_exists(_MPDF_TTFONTDATAPATH.$font.'.cw.dat')) { $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat'); }
30463 else {
30464 $prevFontFamily = $this->FontFamily;
30465 $prevFontStyle = $this->currentfontstyle;
30466 $prevFontSizePt = $this->FontSizePt;
30467 $this->SetFont($this->backupSIPFont, '', '', false);
30468 $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat');
30469 $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false);
30470 }
30471 if (!$cw) { return 0; }
30472 $l = 0;
30473 foreach($u AS $char) {
30474 if ($this->_charDefined($cw,$char) || $char > 131071) {
30475 $l++;
30476 }
30477 else { break; }
30478 }
30479 if ($l > 0) {
30480 $patt = mb_substr($writehtml_e, $start, $l);
30481 if (preg_match("/(.*?)(".preg_quote($patt,'/').")(.*)/u", $writehtml_e, $m)) {
30482 $writehtml_e = $m[1];
30483 array_splice($writehtml_a, $writehtml_i+1, 0, array('span style="font-family: '.$font.'"', $m[2], '/span', $m[3]));
30484 $this->subPos = $writehtml_i+3;
30485 return 4;
30486 }
30487 }
30488 }
30489 return 0;
30490 }
30491
30492
30493 // FIRST TRY CORE FONTS
30494 if (!$this->PDFA && !$this->PDFX) {
30495 $repl = array();
30496 if (!$this->subArrMB) {
30497 include(_MPDF_PATH.'includes/subs_core.php');
30498 $this->subArrMB['a'] = $aarr;
30499 $this->subArrMB['s'] = $sarr;
30500 $this->subArrMB['z'] = $zarr;
30501 }
30502 if (isset($this->subArrMB['a'][$u[0]])) {
30503 $font = 'tta'; $ftype = 'C';
30504 foreach($u AS $char) {
30505 if ($this->subArrMB['a'][$char]) { $repl[] = $this->subArrMB['a'][$char]; }
30506 else { break; }
30507 }
30508 }
30509 else if (isset($this->subArrMB['z'][$u[0]])) {
30510 $font = 'ttz'; $ftype = 'C';
30511 foreach($u AS $char) {
30512 if ($this->subArrMB['z'][$char]) { $repl[] = $this->subArrMB['z'][$char]; }
30513 else { break; }
30514 }
30515 }
30516 else if (isset($this->subArrMB['s'][$u[0]])) {
30517 $font = 'tts'; $ftype = 'C';
30518 foreach($u AS $char) {
30519 if ($this->subArrMB['s'][$char]) { $repl[] = $this->subArrMB['s'][$char]; }
30520 else { break; }
30521 }
30522 }
30523 if ($ftype=='C') {
30524 $patt = mb_substr($writehtml_e, $start, count($repl));
30525 if (preg_match("/(.*?)(".preg_quote($patt,'/').")(.*)/u", $writehtml_e, $m)) {
30526 $writehtml_e = $m[1];
30527 array_splice($writehtml_a, $writehtml_i+1, 0, array($font, implode('|', $repl), '/'.$font, $m[3])); // e.g. <tts>
30528 $this->subPos = $writehtml_i+3;
30529 return 4;
30530 }
30531 return 0;
30532 }
30533 }
30534
30535 // FIND IN DEFAULT FONT - removed mPDF 5.0
30536
30537 // LASTLY TRY IN BACKUP SUBS FONT
30538 if (!is_array($this->backupSubsFont)) { $this->backupSubsFont = array("$this->backupSubsFont"); }
30539 foreach($this->backupSubsFont AS $bsfctr=>$bsf) {
30540 if ($this->currentfontfamily != $bsf) { $font = $bsf; }
30541 else { continue; }
30542 unset($cw);
30543 $cw = '';
30544 if (isset($this->fonts[$font])) { $cw = &$this->fonts[$font]['cw']; }
30545 else if (file_exists(_MPDF_TTFONTDATAPATH.$font.'.cw.dat')) { $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat'); }
30546 else {
30547 $prevFontFamily = $this->FontFamily;
30548 $prevFontStyle = $this->currentfontstyle;
30549 $prevFontSizePt = $this->FontSizePt;
30550 $this->SetFont($bsf, '', '', false);
30551 $cw = @file_get_contents(_MPDF_TTFONTDATAPATH.$font.'.cw.dat');
30552 $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false);
30553 }
30554 if (!$cw) { continue; }
30555 $l = 0;
30556 foreach($u AS $char) {
30557 if ($char == 173 || $this->_charDefined($cw,$char) || ($char>1536 && $char<1791) || ($char>2304 && $char<3455 )) { // Arabic and Indic
30558 $l++;
30559 }
30560 else {
30561 if ($l==0 && $bsfctr == (count($this->backupSubsFont)-1)) { // Not found even in last backup font
30562 $cont = mb_substr($writehtml_e, $start+1);
30563 $writehtml_e = mb_substr($writehtml_e, 0, $start+1);
30564 array_splice($writehtml_a, $writehtml_i+1, 0, array('', $cont));
30565 $this->subPos = $writehtml_i+1;
30566 return 2;
30567 }
30568 else { break; }
30569 }
30570 }
30571 if ($l > 0) {
30572 $patt = mb_substr($writehtml_e, $start, $l);
30573 if (preg_match("/(.*?)(".preg_quote($patt,'/').")(.*)/u", $writehtml_e, $m)) {
30574 $writehtml_e = $m[1];
30575 array_splice($writehtml_a, $writehtml_i+1, 0, array('span style="font-family: '.$font.'"', $m[2], '/span', $m[3]));
30576 $this->subPos = $writehtml_i+3;
30577 return 4;
30578 }
30579 }
30580 }
30581
30582 unset($cw);
30583 return 0;
30584 }
30585
30586
30587 function setHiEntitySubstitutions() {
30588 $entarr = array (
30589 'nbsp' => '160', 'iexcl' => '161', 'cent' => '162', 'pound' => '163', 'curren' => '164', 'yen' => '165', 'brvbar' => '166', 'sect' => '167',
30590 'uml' => '168', 'copy' => '169', 'ordf' => '170', 'laquo' => '171', 'not' => '172', 'shy' => '173', 'reg' => '174', 'macr' => '175',
30591 'deg' => '176', 'plusmn' => '177', 'sup2' => '178', 'sup3' => '179', 'acute' => '180', 'micro' => '181', 'para' => '182', 'middot' => '183',
30592 'cedil' => '184', 'sup1' => '185', 'ordm' => '186', 'raquo' => '187', 'frac14' => '188', 'frac12' => '189', 'frac34' => '190',
30593 'iquest' => '191', 'Agrave' => '192', 'Aacute' => '193', 'Acirc' => '194', 'Atilde' => '195', 'Auml' => '196', 'Aring' => '197',
30594 'AElig' => '198', 'Ccedil' => '199', 'Egrave' => '200', 'Eacute' => '201', 'Ecirc' => '202', 'Euml' => '203', 'Igrave' => '204',
30595 'Iacute' => '205', 'Icirc' => '206', 'Iuml' => '207', 'ETH' => '208', 'Ntilde' => '209', 'Ograve' => '210', 'Oacute' => '211',
30596 'Ocirc' => '212', 'Otilde' => '213', 'Ouml' => '214', 'times' => '215', 'Oslash' => '216', 'Ugrave' => '217', 'Uacute' => '218',
30597 'Ucirc' => '219', 'Uuml' => '220', 'Yacute' => '221', 'THORN' => '222', 'szlig' => '223', 'agrave' => '224', 'aacute' => '225',
30598 'acirc' => '226', 'atilde' => '227', 'auml' => '228', 'aring' => '229', 'aelig' => '230', 'ccedil' => '231', 'egrave' => '232',
30599 'eacute' => '233', 'ecirc' => '234', 'euml' => '235', 'igrave' => '236', 'iacute' => '237', 'icirc' => '238', 'iuml' => '239',
30600 'eth' => '240', 'ntilde' => '241', 'ograve' => '242', 'oacute' => '243', 'ocirc' => '244', 'otilde' => '245', 'ouml' => '246',
30601 'divide' => '247', 'oslash' => '248', 'ugrave' => '249', 'uacute' => '250', 'ucirc' => '251', 'uuml' => '252', 'yacute' => '253',
30602 'thorn' => '254', 'yuml' => '255', 'OElig' => '338', 'oelig' => '339', 'Scaron' => '352', 'scaron' => '353', 'Yuml' => '376',
30603 'fnof' => '402', 'circ' => '710', 'tilde' => '732', 'Alpha' => '913', 'Beta' => '914', 'Gamma' => '915', 'Delta' => '916',
30604 'Epsilon' => '917', 'Zeta' => '918', 'Eta' => '919', 'Theta' => '920', 'Iota' => '921', 'Kappa' => '922', 'Lambda' => '923',
30605 'Mu' => '924', 'Nu' => '925', 'Xi' => '926', 'Omicron' => '927', 'Pi' => '928', 'Rho' => '929', 'Sigma' => '931', 'Tau' => '932',
30606 'Upsilon' => '933', 'Phi' => '934', 'Chi' => '935', 'Psi' => '936', 'Omega' => '937', 'alpha' => '945', 'beta' => '946', 'gamma' => '947',
30607 'delta' => '948', 'epsilon' => '949', 'zeta' => '950', 'eta' => '951', 'theta' => '952', 'iota' => '953', 'kappa' => '954',
30608 'lambda' => '955', 'mu' => '956', 'nu' => '957', 'xi' => '958', 'omicron' => '959', 'pi' => '960', 'rho' => '961', 'sigmaf' => '962',
30609 'sigma' => '963', 'tau' => '964', 'upsilon' => '965', 'phi' => '966', 'chi' => '967', 'psi' => '968', 'omega' => '969',
30610 'thetasym' => '977', 'upsih' => '978', 'piv' => '982', 'ensp' => '8194', 'emsp' => '8195', 'thinsp' => '8201', 'zwnj' => '8204',
30611 'zwj' => '8205', 'lrm' => '8206', 'rlm' => '8207', 'ndash' => '8211', 'mdash' => '8212', 'lsquo' => '8216', 'rsquo' => '8217',
30612 'sbquo' => '8218', 'ldquo' => '8220', 'rdquo' => '8221', 'bdquo' => '8222', 'dagger' => '8224', 'Dagger' => '8225', 'bull' => '8226',
30613 'hellip' => '8230', 'permil' => '8240', 'prime' => '8242', 'Prime' => '8243', 'lsaquo' => '8249', 'rsaquo' => '8250', 'oline' => '8254',
30614 'frasl' => '8260', 'euro' => '8364', 'image' => '8465', 'weierp' => '8472', 'real' => '8476', 'trade' => '8482', 'alefsym' => '8501',
30615 'larr' => '8592', 'uarr' => '8593', 'rarr' => '8594', 'darr' => '8595', 'harr' => '8596', 'crarr' => '8629', 'lArr' => '8656',
30616 'uArr' => '8657', 'rArr' => '8658', 'dArr' => '8659', 'hArr' => '8660', 'forall' => '8704', 'part' => '8706', 'exist' => '8707',
30617 'empty' => '8709', 'nabla' => '8711', 'isin' => '8712', 'notin' => '8713', 'ni' => '8715', 'prod' => '8719', 'sum' => '8721',
30618 'minus' => '8722', 'lowast' => '8727', 'radic' => '8730', 'prop' => '8733', 'infin' => '8734', 'ang' => '8736', 'and' => '8743',
30619 'or' => '8744', 'cap' => '8745', 'cup' => '8746', 'int' => '8747', 'there4' => '8756', 'sim' => '8764', 'cong' => '8773',
30620 'asymp' => '8776', 'ne' => '8800', 'equiv' => '8801', 'le' => '8804', 'ge' => '8805', 'sub' => '8834', 'sup' => '8835', 'nsub' => '8836',
30621 'sube' => '8838', 'supe' => '8839', 'oplus' => '8853', 'otimes' => '8855', 'perp' => '8869', 'sdot' => '8901', 'lceil' => '8968',
30622 'rceil' => '8969', 'lfloor' => '8970', 'rfloor' => '8971', 'lang' => '9001', 'rang' => '9002', 'loz' => '9674', 'spades' => '9824',
30623 'clubs' => '9827', 'hearts' => '9829', 'diams' => '9830',
30624 );
30625 foreach($entarr AS $key => $val) {
30626 $this->entsearch[] = '&'.$key.';';
30627 $this->entsubstitute[] = code2utf($val);
30628 }
30629 }
30630
30631 function SubstituteHiEntities($html) {
30632 // converts html_entities > ASCII 127 to unicode
30633 // Leaves in particular &lt; to distinguish from tag marker
30634 if (count($this->entsearch)) {
30635 $html = str_replace($this->entsearch,$this->entsubstitute,$html);
30636 }
30637 return $html;
30638 }
30639
30640
30641 // Edited v1.2 Pass by reference; option to continue if invalid UTF-8 chars
30642 function is_utf8(&$string) {
30643 if ($string === mb_convert_encoding(mb_convert_encoding($string, "UTF-32", "UTF-8"), "UTF-8", "UTF-32")) {
30644 return true;
30645 }
30646 else {
30647 if ($this->ignore_invalid_utf8) {
30648 $string = mb_convert_encoding(mb_convert_encoding($string, "UTF-32", "UTF-8"), "UTF-8", "UTF-32") ;
30649 return true;
30650 }
30651 else {
30652 return false;
30653 }
30654 }
30655 }
30656
30657
30658 function purify_utf8($html,$lo=true) {
30659 // For HTML
30660 // Checks string is valid UTF-8 encoded
30661 // converts html_entities > ASCII 127 to UTF-8
30662 // Only exception - leaves low ASCII entities e.g. &lt; &amp; etc.
30663 // Leaves in particular &lt; to distinguish from tag marker
30664 if (!$this->is_utf8($html)) {
30665 echo "<p><b>HTML contains invalid UTF-8 character(s)</b></p>";
30666 while (mb_convert_encoding(mb_convert_encoding($html, "UTF-32", "UTF-8"), "UTF-8", "UTF-32") != $html) {
30667 $a = iconv('UTF-8', 'UTF-8', $html);
30668 echo ($a);
30669 $pos = $start = strlen($a);
30670 $err = '';
30671 while ( ord(substr($html,$pos,1)) > 128 ) {
30672 $err .= '[[#'.ord(substr($html,$pos,1)).']]';
30673 $pos++;
30674 }
30675 echo '<span style="color:red; font-weight:bold">'.$err.'</span>';
30676 $html = substr($html, $pos);
30677 }
30678 echo $html;
30679 $this->Error("");
30680 }
30681 $html = preg_replace("/\r/", "", $html );
30682
30683 // converts html_entities > ASCII 127 to UTF-8
30684 // Leaves in particular &lt; to distinguish from tag marker
30685 $html = $this->SubstituteHiEntities($html);
30686
30687 // converts all &#nnn; or &#xHHH; to UTF-8 multibyte
30688 // If $lo==true then includes ASCII < 128
30689 $html = strcode2utf($html,$lo);
30690 return ($html);
30691 }
30692
30693 function purify_utf8_text($txt) {
30694 // For TEXT
30695 // Make sure UTF-8 string of characters
30696 if (!$this->is_utf8($txt)) { $this->Error("Text contains invalid UTF-8 character(s)"); }
30697
30698 $txt = preg_replace("/\r/", "", $txt );
30699
30700 return ($txt);
30701 }
30702 function all_entities_to_utf8($txt) {
30703 // converts txt_entities > ASCII 127 to UTF-8
30704 // Leaves in particular &lt; to distinguish from tag marker
30705 $txt = $this->SubstituteHiEntities($txt);
30706
30707 // converts all &#nnn; or &#xHHH; to UTF-8 multibyte
30708 $txt = strcode2utf($txt);
30709
30710 $txt = $this->lesser_entity_decode($txt);
30711 return ($txt);
30712 }
30713
30714
30715 // ====================================================
30716 /*-- BARCODES --*/
30717 // UPC/EAN barcode
30718 // EAN13, EAN8, UPCA, UPCE, ISBN, ISSN
30719 // Accepts 12 or 13 digits with or without - hyphens
30720 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) {
30721 if (empty($code)) {
30722 return;
30723 }
30724 $codestr = $code;
30725 $code = preg_replace('/\-/','',$code);
30726
30727 if (!class_exists('PDFBarcode', false)) {
30728 include(_MPDF_PATH.'classes/barcode.php');
30729 }
30730 $this->barcode = new PDFBarcode();
30731 if ($btype == 'ISSN' || $btype == 'ISBN') {
30732 $arrcode = $this->barcode->getBarcodeArray($code, 'EAN13');
30733 }
30734 else { $arrcode = $this->barcode->getBarcodeArray($code, $btype); }
30735
30736 if ($arrcode === false) { $this->Error('Error in barcode string: '.$codestr); }
30737 if((($btype=='EAN13' || $btype=='ISBN' || $btype=='ISSN') && strlen($code) == 12) || ($btype=='UPCA' && strlen($code) == 11)
30738 || ($btype=='UPCE' && strlen($code) == 11) || ($btype=='EAN8' && strlen($code) == 7)) {
30739 $code .= $arrcode['checkdigit'];
30740 if (stristr($codestr,'-')) { $codestr .= '-' . $arrcode['checkdigit']; }
30741 else { $codestr .= $arrcode['checkdigit']; }
30742 }
30743 if ($btype == 'ISBN') { $codestr = 'ISBN '.$codestr; }
30744 if ($btype == 'ISSN') { $codestr = 'ISSN '.$codestr; }
30745
30746 if (empty($x)) {
30747 $x = $this->x;
30748 }
30749 if (empty($y)) {
30750 $y = $this->y;
30751 }
30752 // set foreground color
30753 $prevDrawColor = $this->DrawColor;
30754 $prevTextColor = $this->TextColor;
30755 $prevFillColor = $this->FillColor;
30756 $lw = $this->LineWidth;
30757 $this->SetLineWidth(0.01);
30758
30759 $size /= $k; // in case resized in a table
30760
30761 $xres = $arrcode['nom-X'] * $size;
30762 $llm = $arrcode['lightmL'] * $arrcode['nom-X'] * $size; // Left Light margin
30763 $rlm = $arrcode['lightmR'] * $arrcode['nom-X'] * $size; // Right Light margin
30764
30765 $bcw = ($arrcode["maxw"] * $xres); // Barcode width = Should always be 31.35mm * $size
30766
30767 $fbw = $bcw + $llm + $rlm; // Full barcode width incl. light margins
30768 $ow = $fbw + $paddingL + $paddingR; // Full overall width incl. user-defined padding
30769
30770 $fbwi = $fbw - 2; // Full barcode width incl. light margins - 2mm - for isbn string
30771
30772 // cf. http://www.gs1uk.org/downloads/bar_code/Bar coding getting it right.pdf
30773 $num_height = 3 * $size; // Height of numerals
30774 $fbh = $arrcode['nom-H'] * $size * $height; // Full barcode height incl. numerals
30775 $bch = $fbh - (1.5 * $size); // Barcode height of bars (3mm for numerals)
30776
30777 if (($btype=='EAN13' && $showtext) || $btype == 'ISSN' || $btype == 'ISBN') { // Add height for ISBN string + margin from top of bars
30778 $tisbnm = 1.5 * $size; // Top margin between isbn (if shown) & bars
30779 $codestr_fontsize = 2.1 * $size;
30780 $paddingT += $codestr_fontsize + $tisbnm ;
30781 }
30782 $oh = $fbh + $paddingT + $paddingB; // Full overall height incl. user-defined padding
30783
30784 // PRINT border background color
30785 $xpos = $x;
30786 $ypos = $y;
30787 if ($col) {
30788 $this->SetDColor($col);
30789 $this->SetTColor($col);
30790 }
30791 else {
30792 $this->SetDColor($this->ConvertColor(0));
30793 $this->SetTColor($this->ConvertColor(0));
30794 }
30795 if ($bgcol) {
30796 $this->SetFColor($bgcol);
30797 }
30798 else { $this->SetFColor($this->ConvertColor(255)); }
30799 if (!$bgcol && !$col) { // fn. called directly - not via HTML
30800 if ($border) { $fillb = 'DF'; } else { $fillb = 'F'; }
30801 $this->Rect($xpos, $ypos, $ow, $oh, $fillb);
30802 }
30803
30804
30805 // PRINT BARS
30806 $xpos = $x + $paddingL + $llm ;
30807 $ypos = $y + $paddingT;
30808 if ($col) { $this->SetFColor($col); }
30809 else { $this->SetFColor($this->ConvertColor(0)); }
30810 if ($arrcode !== false) {
30811 foreach ($arrcode["bcode"] AS $v) {
30812 $bw = ($v["w"] * $xres);
30813 if ($v["t"]) {
30814 // draw a vertical bar
30815 $this->Rect($xpos, $ypos, $bw, $bch, 'F');
30816 }
30817 $xpos += $bw;
30818 }
30819 }
30820
30821
30822 // print text
30823 $prevFontFamily = $this->FontFamily;
30824 $prevFontStyle = $this->FontStyle;
30825 $prevFontSizePt = $this->FontSizePt;
30826
30827 // ISBN string
30828 if (($btype=='EAN13' && $showtext) || $btype=='ISBN' || $btype=='ISSN') {
30829 if ($this->onlyCoreFonts) {
30830 $this->SetFont('chelvetica');
30831 }
30832 else {
30833 $this->SetFont('sans');
30834 }
30835
30836 if ($bgcol) { $this->SetFColor($bgcol); }
30837 else { $this->SetFColor($this->ConvertColor(255)); }
30838 $this->x = $x + $paddingL + 1; // 1mm left margin (cf. $fbwi above)
30839 // max width is $fbwi
30840 $loop = 0;
30841 while ( $loop == 0 ) {
30842 $this->SetFontSize($codestr_fontsize*1.4*_MPDFK, false); // don't write
30843 $sz = $this->GetStringWidth( $codestr );
30844 if ($sz > $fbwi)
30845 $codestr_fontsize -= 0.1;
30846 else
30847 $loop ++;
30848 }
30849 $this->SetFont('','',$codestr_fontsize*1.4*_MPDFK, true, true); // * 1.4 because font height is only 7/10 of given mm
30850 // WORD SPACING
30851 if ($fbwi > $sz) {
30852 $xtra = $fbwi - $sz;
30853 $charspacing = $xtra / (strlen($codestr)-1);
30854 if ($charspacing) { $this->_out(sprintf('BT %.3F Tc ET',$charspacing*_MPDFK)); }
30855 }
30856 $this->y = $y + $paddingT - ($codestr_fontsize ) - $tisbnm ;
30857 $this->Cell($fbw , $codestr_fontsize, $codestr);
30858 if ($charspacing) { $this->_out('BT 0 Tc ET'); }
30859 }
30860
30861
30862 // Bottom NUMERALS
30863 if ($this->onlyCoreFonts) {
30864 $this->SetFont('mono');
30865 }
30866 else {
30867 if (in_array('ocrb',$this->available_unifonts)) { $this->SetFont('ocrb'); }
30868 else { $this->SetFont('mono'); }
30869 }
30870 if (isset($this->CurrentFont['desc']['CapHeight'])) { $fh = (1000/$this->CurrentFont['desc']['CapHeight']); }
30871 else if (isset($this->CurrentFont['desc']['Ascent'])) { $fh = (1000/$this->CurrentFont['desc']['Ascent']); }
30872 else { $fh = 1.2; }
30873
30874 $charRO = '';
30875 if ($btype=='EAN13' || $btype=='ISBN' || $btype=='ISSN') {
30876 $outerfontsize = 3; // Inner fontsize = 3
30877 $outerp = $xres * 4;
30878 $innerp = $xres * 2.5;
30879 $textw = ($bcw*0.5) - $outerp - $innerp;
30880 $chars = 6; // number of numerals in each half
30881 $charLO = substr($code,0,1); // Left Outer
30882 $charLI = substr($code,1,6); // Left Inner
30883 $charRI = substr($code,7,6); // Right Inner
30884 if (!$supplement) $charRO = '>'; // Right Outer
30885 }
30886 else if ($btype=='UPCA') {
30887 $outerfontsize = 2.3; // Inner fontsize = 3
30888 $outerp = $xres * 10;
30889 $innerp = $xres * 2.5;
30890 $textw = ($bcw*0.5) - $outerp - $innerp;
30891 $chars = 5;
30892 $charLO = substr($code,0,1); // Left Outer
30893 $charLI = substr($code,1,5); // Left Inner
30894 $charRI = substr($code,6,5); // Right Inner
30895 $charRO = substr($code,11,1); // Right Outer
30896 }
30897 else if ($btype=='UPCE') {
30898 $outerfontsize = 2.3; // Inner fontsize = 3
30899 $outerp = $xres * 4;
30900 $innerp = 0;
30901 $textw = ($bcw*0.5) - $outerp - $innerp;
30902 $chars = 3;
30903 $upce_code = $arrcode['code'];
30904 $charLO = substr($code,0,1); // Left Outer
30905 $charLI = substr($upce_code,0,3); // Left Inner
30906 $charRI = substr($upce_code,3,3); // Right Inner
30907 $charRO = substr($code,11,1); // Right Outer
30908 }
30909 else if ($btype=='EAN8') {
30910 $outerfontsize = 3; // Inner fontsize = 3
30911 $outerp = $xres * 4;
30912 $innerp = $xres * 2.5;
30913 $textw = ($bcw*0.5) - $outerp - $innerp;
30914 $chars = 4;
30915 $charLO = '<'; // Left Outer
30916 $charLI = substr($code,0,4); // Left Inner
30917 $charRI = substr($code,4,4); // Right Inner
30918 if (!$supplement) $charRO = '>'; // Right Outer
30919 }
30920
30921 $this->SetFontSize(($outerfontsize/3)*3*$fh*$size*_MPDFK); // 3mm numerals (FontSize is larger to account for space above/below characters)
30922
30923 if (!$this->usingCoreFont) { $cw = $this->_getCharWidth($this->CurrentFont['cw'],32)*3*$fh*$size/1000; } // character width at 3mm
30924 else { $cw = $this->_getCharWidth($this->CurrentFont['cw'],48)*3*$fh*$size/1000; } // 48 == char "0"
30925
30926 // Outer left character
30927 $y_text = $y + $paddingT + $bch - ($num_height/2);
30928 $y_text_outer = $y + $paddingT + $bch - ($num_height*($outerfontsize/3)/2);
30929
30930 $this->x = $x + $paddingL - ($cw*($outerfontsize/3)*0.1); // 0.1 is correction as char does not fill full width;
30931 $this->y = $y_text_outer;
30932 $this->Cell($cw, $num_height, $charLO );
30933
30934 // WORD SPACING for inner chars
30935 $xtra = $textw - ($cw*$chars);
30936 $charspacing = $xtra / ($chars-1);
30937 if ($charspacing) { $this->_out(sprintf('BT %.3F Tc ET',$charspacing*_MPDFK)); }
30938
30939 if ($bgcol) { $this->SetFColor($bgcol); }
30940 else { $this->SetFColor($this->ConvertColor(255)); }
30941
30942 $this->SetFontSize(3*$fh*$size*_MPDFK); // 3mm numerals (FontSize is larger to account for space above/below characters)
30943
30944 // Inner left half characters
30945 $this->x = $x + $paddingL + $llm + $outerp;
30946 $this->y = $y_text;
30947 $this->Cell($textw, $num_height, $charLI , 0, 0, '', 1);
30948
30949 // Inner right half characters
30950 $this->x = $x + $paddingL + $llm + ($bcw*0.5) + $innerp;
30951 $this->y = $y_text;
30952 $this->Cell($textw, $num_height, $charRI , 0, 0, '', 1);
30953
30954 if ($charspacing) { $this->_out('BT 0 Tc ET'); }
30955
30956 // Outer Right character
30957 $this->SetFontSize(($outerfontsize/3)*3*$fh*$size*_MPDFK); // 3mm numerals (FontSize is larger to account for space above/below characters)
30958
30959 $this->x = $x + $paddingL + $llm + $bcw + $rlm - ($cw*($outerfontsize/3)*0.9); // 0.9 is correction as char does not fill full width
30960 $this->y = $y_text_outer;
30961 $this->Cell($cw*($outerfontsize/3), $num_height, $charRO , 0, 0, 'R');
30962
30963 if ($supplement) { // EAN-2 or -5 Supplement
30964 // PRINT BARS
30965 $supparrcode = $this->barcode->getBarcodeArray($supplement_code, 'EAN'.$supplement);
30966 if ($supparrcode === false) { $this->Error('Error in barcode string (supplement): '.$codestr.' '.$supplement_code); }
30967 if(strlen($supplement_code) != $supplement) {
30968 $this->Error('Barcode supplement incorrect: '.$supplement_code);
30969 }
30970 $llm = $fbw - (($arrcode['lightmR'] - $supparrcode['sepM']) * $arrcode['nom-X'] * $size); // Left Light margin
30971 $rlm = $arrcode['lightmR'] * $arrcode['nom-X'] * $size; // Right Light margin
30972
30973 $bcw = ($supparrcode["maxw"] * $xres); // Barcode width = Should always be 31.35mm * $size
30974
30975 $fbw = $bcw + $llm + $rlm; // Full barcode width incl. light margins
30976 $ow = $fbw + $paddingL + $paddingR; // Full overall width incl. user-defined padding
30977 $bch = $fbh - (1.5 * $size) - ($num_height + 0.5); // Barcode height of bars (3mm for numerals)
30978
30979 $xpos = $x + $paddingL + $llm ;
30980 $ypos = $y + $paddingT + $num_height + 0.5;
30981 if ($col) { $this->SetFColor($col); }
30982 else { $this->SetFColor($this->ConvertColor(0)); }
30983 if ($supparrcode !== false) {
30984 foreach ($supparrcode["bcode"] AS $v) {
30985 $bw = ($v["w"] * $xres);
30986 if ($v["t"]) {
30987 // draw a vertical bar
30988 $this->Rect($xpos, $ypos, $bw, $bch, 'F');
30989 }
30990 $xpos += $bw;
30991 }
30992 }
30993
30994 // Characters
30995 if ($bgcol) { $this->SetFColor($bgcol); }
30996 else { $this->SetFColor($this->ConvertColor(255)); }
30997 $this->SetFontSize(3*$fh*$size*_MPDFK); // 3mm numerals (FontSize is larger to account for space above/below characters)
30998 $this->x = $x + $paddingL + $llm;
30999 $this->y = $y + $paddingT;
31000 $this->Cell($bcw, $num_height, $supplement_code, 0, 0, 'C');
31001
31002 // Outer Right character (light margin)
31003 $this->SetFontSize(($outerfontsize/3)*3*$fh*$size*_MPDFK); // 3mm numerals (FontSize is larger to account for space above/below characters)
31004 $this->x = $x + $paddingL + $llm + $bcw + $rlm - ($cw*0.9); // 0.9 is correction as char does not fill full width
31005 $this->y = $y + $paddingT;
31006 $this->Cell($cw*($outerfontsize/3), $num_height, '>', 0, 0, 'R');
31007 }
31008
31009
31010
31011 // Restore **************
31012 $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt);
31013 $this->DrawColor = $prevDrawColor;
31014 $this->TextColor = $prevTextColor;
31015 $this->FillColor = $prevFillColor;
31016 $this->SetLineWidth($lw);
31017 $this->SetY($y);
31018 }
31019
31020
31021
31022 // ====================================================
31023 // POSTAL and OTHER barcodes
31024 function WriteBarcode2($code, $x='', $y='', $size=1, $height=1, $bgcol=false, $col=false, $btype='IMB', $print_ratio='', $k=1) {
31025 if (empty($code)) { return; }
31026 if (!class_exists('PDFBarcode', false)) {
31027 include(_MPDF_PATH.'classes/barcode.php');
31028 }
31029 $this->barcode = new PDFBarcode();
31030 $arrcode = $this->barcode->getBarcodeArray($code, $btype, $print_ratio);
31031
31032 if ($arrcode === false) { $this->Error('Error in barcode string: '.$code); }
31033 if (empty($x)) { $x = $this->x; }
31034 if (empty($y)) { $y = $this->y; }
31035 $prevDrawColor = $this->DrawColor;
31036 $prevTextColor = $this->TextColor;
31037 $prevFillColor = $this->FillColor;
31038 $lw = $this->LineWidth;
31039 $this->SetLineWidth(0.01);
31040 $size /= $k; // in case resized in a table
31041 $xres = $arrcode['nom-X'] * $size;
31042
31043 if ($btype == 'IMB' || $btype == 'RM4SCC' || $btype == 'KIX' || $btype == 'POSTNET' || $btype == 'PLANET') {
31044 $llm = $arrcode['quietL'] / $k; // Left Quiet margin
31045 $rlm = $arrcode['quietR'] / $k; // Right Quiet margin
31046 $tlm = $blm = $arrcode['quietTB'] / $k;
31047 $height=1; // Overrides
31048 }
31049 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'))) {
31050 $llm = $arrcode['lightmL'] * $xres; // Left Quiet margin
31051 $rlm = $arrcode['lightmR'] * $xres; // Right Quiet margin
31052 $tlm = $blm = $arrcode['lightTB'] * $xres * $height;
31053 }
31054
31055
31056 $bcw = ($arrcode["maxw"] * $xres);
31057 $fbw = $bcw + $llm + $rlm; // Full barcode width incl. light margins
31058
31059 $bch = ($arrcode["nom-H"] * $size * $height);
31060 $fbh = $bch + $tlm + $blm; // Full barcode height
31061
31062 // PRINT border background color
31063 $xpos = $x;
31064 $ypos = $y;
31065 if ($col) {
31066 $this->SetDColor($col);
31067 $this->SetTColor($col);
31068 }
31069 else {
31070 $this->SetDColor($this->ConvertColor(0));
31071 $this->SetTColor($this->ConvertColor(0));
31072 }
31073 if ($bgcol) {
31074 $this->SetFColor($bgcol);
31075 }
31076 else { $this->SetFColor($this->ConvertColor(255)); }
31077
31078 // PRINT BARS
31079 if ($col) { $this->SetFColor($col); }
31080 else { $this->SetFColor($this->ConvertColor(0)); }
31081 $xpos = $x + $llm ;
31082
31083 if ($arrcode !== false) {
31084 foreach ($arrcode["bcode"] AS $v) {
31085 $bw = ($v["w"] * $xres);
31086 if ($v["t"]) {
31087 $ypos = $y + $tlm + ($bch * $v['p'] / $arrcode['maxh']);
31088 $this->Rect($xpos, $ypos, $bw, ($v['h'] * $bch / $arrcode['maxh']), 'F');
31089 }
31090 $xpos += $bw;
31091 }
31092 }
31093
31094 // PRINT BEARER BARS
31095 if ($btype == 'I25B' || $btype == 'I25B+') {
31096 $this->Rect($x, $y, $fbw, ($arrcode['lightTB'] * $xres * $height), 'F');
31097 $this->Rect($x, $y+$tlm+$bch, $fbw, ($arrcode['lightTB'] * $xres * $height), 'F');
31098 }
31099
31100 // Restore **************
31101 $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt);
31102 $this->DrawColor = $prevDrawColor;
31103 $this->TextColor = $prevTextColor;
31104 $this->FillColor = $prevFillColor;
31105 $this->SetLineWidth($lw);
31106 $this->SetY($y);
31107 }
31108
31109 /*-- END BARCODES --*/
31110
31111 // ====================================================
31112 // ====================================================
31113
31114 function StartTransform($returnstring=false) {
31115 if ($returnstring) { return('q'); }
31116 else { $this->_out('q'); }
31117 }
31118 function StopTransform($returnstring=false) {
31119 if ($returnstring) { return('Q'); }
31120 else { $this->_out('Q'); }
31121 }
31122 function transformScale($s_x, $s_y, $x='', $y='', $returnstring=false) {
31123 if ($x === '') {
31124 $x=$this->x;
31125 }
31126 if ($y === '') {
31127 $y=$this->y;
31128 }
31129 if (($s_x == 0) OR ($s_y == 0)) {
31130 $this->Error('Please do not use values equal to zero for scaling');
31131 }
31132 $y = ($this->h - $y) * _MPDFK;
31133 $x *= _MPDFK;
31134 //calculate elements of transformation matrix
31135 $s_x /= 100;
31136 $s_y /= 100;
31137 $tm[0] = $s_x;
31138 $tm[1] = 0;
31139 $tm[2] = 0;
31140 $tm[3] = $s_y;
31141 $tm[4] = $x * (1 - $s_x);
31142 $tm[5] = $y * (1 - $s_y);
31143 //scale the coordinate system
31144 if ($returnstring) { return($this->_transform($tm, true)); }
31145 else { $this->_transform($tm); }
31146 }
31147 function transformTranslate($t_x, $t_y, $returnstring=false) {
31148 //calculate elements of transformation matrix
31149 $tm[0] = 1;
31150 $tm[1] = 0;
31151 $tm[2] = 0;
31152 $tm[3] = 1;
31153 $tm[4] = $t_x * _MPDFK;
31154 $tm[5] = -$t_y * _MPDFK;
31155 //translate the coordinate system
31156 if ($returnstring) { return($this->_transform($tm, true)); }
31157 else { $this->_transform($tm); }
31158 }
31159 function transformRotate($angle, $x='', $y='', $returnstring=false) {
31160 if ($x === '') {
31161 $x=$this->x;
31162 }
31163 if ($y === '') {
31164 $y=$this->y;
31165 }
31166 $angle = -$angle;
31167 $y = ($this->h - $y) * _MPDFK;
31168 $x *= _MPDFK;
31169 //calculate elements of transformation matrix
31170 $tm[0] = cos(deg2rad($angle));
31171 $tm[1] = sin(deg2rad($angle));
31172 $tm[2] = -$tm[1];
31173 $tm[3] = $tm[0];
31174 $tm[4] = $x + $tm[1] * $y - $tm[0] * $x;
31175 $tm[5] = $y - $tm[0] * $y - $tm[1] * $x;
31176 //rotate the coordinate system around ($x,$y)
31177 if ($returnstring) { return($this->_transform($tm, true)); }
31178 else { $this->_transform($tm); }
31179 }
31180 function _transform($tm, $returnstring=false) {
31181 if ($returnstring) { return(sprintf('%.4F %.4F %.4F %.4F %.4F %.4F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5])); }
31182 else { $this->_out(sprintf('%.4F %.4F %.4F %.4F %.4F %.4F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5])); }
31183 }
31184
31185
31186
31187 /*-- INDIC --*/
31188 // INDIC ============================
31189 // This conversion can only be done when font is set
31190 function ConvertIndic(&$str) {
31191 if (preg_match('/^ind_([a-z]{2})_/',$this->currentfontfamily, $m)) {
31192 if (!class_exists('indic', false)) { include(_MPDF_PATH.'classes/indic.php'); }
31193 if (empty($this->indic)) { $this->indic = new indic($this); }
31194 $earr = $this->UTF8StringToArray($str, false);
31195 $str = $this->indic->substituteIndic($earr, $m[1], $this->currentfontfamily);
31196 }
31197 }
31198 /*-- END INDIC --*/
31199
31200 // AUTOFONT =========================
31201 function AutoFont($html) {
31202 if ($this->onlyCoreFonts) { return $html; }
31203 $this->useLang = true;
31204 if ($this->autoFontGroupSize == 1) { $extra = $this->pregASCIIchars1; }
31205 else if ($this->autoFontGroupSize == 3) { $extra = $this->pregASCIIchars3; }
31206 else { $extra = $this->pregASCIIchars2; }
31207 $n = '';
31208 $a=preg_split('/<(.*?)>/ms',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
31209 foreach($a as $i => $e) {
31210 if($i%2==0) {
31211 $e = strcode2utf($e);
31212 $e = $this->lesser_entity_decode($e);
31213
31214 // Use U=FFF0 and U+FFF1 to mark start and end of span tags to prevent nesting occurring
31215 // "\xef\xbf\xb0" ##lthtmltag## "\xef\xbf\xb1" ##gthtmltag##
31216
31217 /*-- CJK-FONTS --*/
31218 if ($this->autoFontGroups & AUTOFONT_CJK) {
31219 $e = preg_replace_callback("/([".$this->pregCJKchars .$extra."]*[".$this->pregCJKchars ."][".$this->pregCJKchars .$extra."]*)/u", array($this, 'replaceCJKPregCallback'), $e ); // mPDF 5.7+
31220 }
31221 /*-- END CJK-FONTS --*/
31222
31223 /*-- RTL --*/
31224 if ($this->autoFontGroups & AUTOFONT_RTL) {
31225 // HEBREW
31226 $e = preg_replace("/([".$this->pregHEBchars .$extra."]*[".$this->pregHEBchars ."][".$this->pregHEBchars .$extra."]*)/u", "\xef\xbf\xb0span lang=\"he\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31227 // All Arabic
31228 $e = preg_replace_callback("/([".$this->pregARABICchars .$extra."]*[".$this->pregARABICchars ."][".$this->pregARABICchars .$extra."]*)/u", array($this, 'replaceArabicPregCallback'), $e ); // mPDF 5.7+
31229 }
31230 /*-- END RTL --*/
31231
31232 /*-- INDIC --*/
31233 // INDIC
31234 if ($this->autoFontGroups & AUTOFONT_INDIC) {
31235 // Bengali
31236 $e = preg_replace("/([".$this->pregBNchars .$this->pregINDextra."]*[".$this->pregBNchars ."][".$this->pregBNchars .$this->pregINDextra."]*)/u", "\xef\xbf\xb0span lang=\"bn\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31237 // Devanagari (= script for Hindi, Nepali + Sindhi)
31238 $e = preg_replace("/([".$this->pregHIchars .$this->pregINDextra."]*[".$this->pregHIchars ."][".$this->pregHIchars .$this->pregINDextra."]*)/u", "\xef\xbf\xb0span lang=\"hi\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31239 // Gujarati
31240 $e = preg_replace("/([".$this->pregGUchars .$this->pregINDextra."]*[".$this->pregGUchars ."][".$this->pregGUchars .$this->pregINDextra."]*)/u", "\xef\xbf\xb0span lang=\"gu\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31241 // Malayalam
31242 $e = preg_replace("/([".$this->pregMLchars .$this->pregINDextra."]*[".$this->pregMLchars ."][".$this->pregMLchars .$this->pregINDextra."]*)/u", "\xef\xbf\xb0span lang=\"ml\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31243 // Kannada
31244 $e = preg_replace("/([".$this->pregKNchars .$this->pregINDextra."]*[".$this->pregKNchars ."][".$this->pregKNchars .$this->pregINDextra."]*)/u", "\xef\xbf\xb0span lang=\"kn\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31245 // Oriya
31246 $e = preg_replace("/([".$this->pregORchars .$this->pregINDextra."]*[".$this->pregORchars ."][".$this->pregORchars .$this->pregINDextra."]*)/u", "\xef\xbf\xb0span lang=\"or\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31247 // Punjabi ?= Gurmuhki
31248 $e = preg_replace("/([".$this->pregPAchars .$this->pregINDextra."]*[".$this->pregPAchars ."][".$this->pregPAchars .$this->pregINDextra."]*)/u", "\xef\xbf\xb0span lang=\"pa\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31249 // Tamil
31250 $e = preg_replace("/([".$this->pregTAchars .$this->pregINDextra."]*[".$this->pregTAchars ."][".$this->pregTAchars .$this->pregINDextra."]*)/u", "\xef\xbf\xb0span lang=\"ta\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31251 // Telugu
31252 $e = preg_replace("/([".$this->pregTEchars .$this->pregINDextra."]*[".$this->pregTEchars ."][".$this->pregTEchars .$this->pregINDextra."]*)/u", "\xef\xbf\xb0span lang=\"te\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31253 }
31254 /*-- END INDIC --*/
31255
31256
31257 if ($this->autoFontGroups & AUTOFONT_THAIVIET) {
31258 // THAI
31259 $e = preg_replace("/([\x{0E00}-\x{0E7F}".$extra."]*[\x{0E00}-\x{0E7F}][\x{0E00}-\x{0E7F}".$extra."]*)/u", "\xef\xbf\xb0span lang=\"th\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31260 // Vietnamese
31261 $e = preg_replace("/([".$this->pregVIETchars .$this->pregVIETPluschars ."]*[".$this->pregVIETchars ."][".$this->pregVIETchars .$this->pregVIETPluschars ."]*)/u", "\xef\xbf\xb0span lang=\"vi\"\xef\xbf\xb1\\1\xef\xbf\xb0/span\xef\xbf\xb1", $e);
31262 }
31263
31264 $e = preg_replace('/[&]/','&amp;',$e);
31265 $e = preg_replace('/[<]/','&lt;',$e);
31266 $e = preg_replace('/[>]/','&gt;',$e);
31267 $e = preg_replace("/(\xef\xbf\xb0span lang=\"([a-z\-A-Z]{2,5})\"\xef\xbf\xb1)\s+/",' \\1',$e);
31268 $e = preg_replace("/[ ]+(\xef\xbf\xb0\/span\xef\xbf\xb1)/",'\\1 ',$e);
31269
31270 $e = preg_replace("/\xef\xbf\xb0span lang=\"([a-z\-A-Z]{2,5})\"\xef\xbf\xb1/","\xef\xbf\xb0span lang=\"\\1\" class=\"lang_\\1\"\xef\xbf\xb1",$e);
31271
31272 $e = preg_replace("/\xef\xbf\xb0/",'<',$e);
31273 $e = preg_replace("/\xef\xbf\xb1/",'>',$e);
31274
31275 $a[$i] = $e;
31276 }
31277 else {
31278 $a[$i] = '<'.$e.'>';
31279 }
31280 }
31281 $n = implode('',$a);
31282 return $n;
31283 }
31284
31285
31286 /*-- CJK-FONTS --*/
31287 function replaceCJK($str) {
31288 // Use U=FFF0 and U+FFF1 to mark start and end of span tags to prevent nesting occurring
31289 // "\xef\xbf\xb0" ##lthtmltag## "\xef\xbf\xb1" ##gthtmltag##
31290 if (preg_match("/[".$this->pregUHCchars."]/u", $str)) {
31291 return "\xef\xbf\xb0span lang=\"ko\"\xef\xbf\xb1" . $str ."\xef\xbf\xb0/span\xef\xbf\xb1";
31292 }
31293 else if (preg_match("/[".$this->pregSJISchars."]/u", $str)) {
31294 return "\xef\xbf\xb0span lang=\"ja\"\xef\xbf\xb1" . $str ."\xef\xbf\xb0/span\xef\xbf\xb1";
31295 }
31296 // if in Unicode Plane 2, probably HKCS (incl in BIG5) if not Japanese
31297 else if (preg_match("/[\x{20000}-\x{2FFFF}]/u", $str)) {
31298 return "\xef\xbf\xb0span lang=\"zh-HK\"\xef\xbf\xb1" . $str ."\xef\xbf\xb0/span\xef\xbf\xb1";
31299 }
31300 else{
31301 return "\xef\xbf\xb0span lang=\"zh-CN\"\xef\xbf\xb1" . $str ."\xef\xbf\xb0/span\xef\xbf\xb1";
31302 }
31303 return $str;
31304 }
31305
31306 // mPDF 5.7+
31307 function replaceCJKPregCallback($matches) {
31308 return $this->replaceCJK(stripslashes($matches[1]));
31309 }
31310 /*-- END CJK-FONTS --*/
31311
31312 /*-- RTL --*/
31313 function replaceArabic($str) {
31314 // PASHTO, SINDHI, URDU, ARABIC, PERSIAN
31315 $persian = "\x{067E}\x{0686}\x{0698}\x{06AF}";
31316
31317 $urdu = "\x{0679}\x{0688}\x{0691}\x{06BA}\x{06BE}\x{06C1}\x{06D2}";
31318 $pashto = "\x{067C}\x{0681}\x{0685}\x{0689}\x{0693}\x{0696}\x{069A}\x{06BC}\x{06D0}"; // ? and U+06AB, U+06CD
31319 $sindhi = "\x{067A}\x{067B}\x{067D}\x{067F}\x{0680}\x{0684}\x{068D}\x{068A}\x{068F}\x{068C}\x{0687}\x{0683}\x{0699}\x{06AA}\x{06A6}\x{06BB}\x{06B1}\x{06B3}";
31320 // Use U=FFF0 and U+FFF1 to mark start and end of span tags to prevent nesting occurring
31321 // "\xef\xbf\xb0" ##lthtmltag## "\xef\xbf\xb1" ##gthtmltag##
31322
31323 if (preg_match("/[".$this->pregNonARABICchars ."]/u", $str) ) {
31324 if (preg_match("/[".$sindhi ."]/u", $str) ) {
31325 return "\xef\xbf\xb0span lang=\"sd\"\xef\xbf\xb1".$str."\xef\xbf\xb0/span\xef\xbf\xb1";
31326 }
31327 else if (preg_match("/[".$urdu ."]/u", $str) ) {
31328 return "\xef\xbf\xb0span lang=\"ur\"\xef\xbf\xb1".$str."\xef\xbf\xb0/span\xef\xbf\xb1";
31329 }
31330 else if (preg_match("/[".$pashto ."]/u", $str) ) {
31331 return "\xef\xbf\xb0span lang=\"ps\"\xef\xbf\xb1".$str."\xef\xbf\xb0/span\xef\xbf\xb1";
31332 }
31333 else if (preg_match("/[".$persian ."]/u", $str) ) {
31334 return "\xef\xbf\xb0span lang=\"fa\"\xef\xbf\xb1".$str."\xef\xbf\xb0/span\xef\xbf\xb1";
31335 }
31336 else {
31337 return "\xef\xbf\xb0span lang=\"ar\"\xef\xbf\xb1".$str."\xef\xbf\xb0/span\xef\xbf\xb1";
31338 }
31339 }
31340 if (preg_match("/[".$persian ."]/u", $str) ) {
31341 return "\xef\xbf\xb0span lang=\"fa\"\xef\xbf\xb1".$str."\xef\xbf\xb0/span\xef\xbf\xb1";
31342 }
31343 else {
31344 return "\xef\xbf\xb0span lang=\"ar\"\xef\xbf\xb1".$str."\xef\xbf\xb0/span\xef\xbf\xb1";
31345 }
31346 return $str;
31347 }
31348
31349 // mPDF 5.7+
31350 function replaceArabicPregCallback($matches) {
31351 return $this->replaceArabic(stripslashes($matches[1]));
31352 }
31353
31354 // ARABIC ===========================
31355 // mPDF 5.4.08
31356 function InitArabic() {
31357
31358 // JOIN TO FOLLOWING LETTER IN LOGICAL ORDER (i.e. AS INITIAL)
31359 $this->arabPrevLink = "";
31360 // U+060c; U+061b; U+061f; U+0626; U+0628;
31361 $this->arabPrevLink .= "\xd8\x8c\xd8\x9b\xd8\x9f\xd8\xa6\xd8\xa8";
31362 // U+062a; U+062b; U+062c; U+062d; U+062e;
31363 $this->arabPrevLink .= "\xd8\xaa\xd8\xab\xd8\xac\xd8\xad\xd8\xae";
31364 // U+0633; U+0634; U+0635; U+0636; U+0637; U+0638; U+0639; U+063a;
31365 $this->arabPrevLink .= "\xd8\xb3\xd8\xb4\xd8\xb5\xd8\xb6\xd8\xb7\xd8\xb8\xd8\xb9\xd8\xba";
31366 // U+0640; U+0641; U+0642; U+0643; U+0644; U+0645; U+0646; U+0647; U+0649; U+064a;
31367 $this->arabPrevLink .= "\xd9\x80\xd9\x81\xd9\x82\xd9\x83\xd9\x84\xd9\x85\xd9\x86\xd9\x87\xd9\x89\xd9\x8a";
31368 // U+0678; U+0679; U+067a; U+067b; U+067c; U+067d; U+067e; U+067f;
31369 $this->arabPrevLink .= "\xd9\xb8\xd9\xb9\xd9\xba\xd9\xbb\xd9\xbc\xd9\xbd\xd9\xbe\xd9\xbf";
31370 // U+0680; U+0681; U+0682; U+0683; U+0684; U+0685; U+0686; U+0687;
31371 $this->arabPrevLink .= "\xda\x80\xda\x81\xda\x82\xda\x83\xda\x84\xda\x85\xda\x86\xda\x87";
31372 // U+069a; U+069b; U+069c; U+069d; U+069e; U+069f;
31373 $this->arabPrevLink .= "\xda\x9a\xda\x9b\xda\x9c\xda\x9d\xda\x9e\xda\x9f";
31374 // U+06a0; U+06a1; U+06a2; U+06a3; U+06a4; U+06a5; U+06a6; U+06A7; U+06A8;
31375 $this->arabPrevLink .= "\xda\xa0\xda\xa1\xda\xa2\xda\xa3\xda\xa4\xda\xa5\xda\xa6\xda\xa7\xda\xa8";
31376 // U+06a9; U+06aa; U+06ab; U+06ac; U+06ad; U+06ae; U+06af;
31377 $this->arabPrevLink .= "\xda\xa9\xda\xaa\xda\xab\xda\xac\xda\xad\xda\xae\xda\xaf";
31378 // U+06b0; U+06b1; U+06b2; U+06b3; U+06b4; U+06b5; U+06b6; U+06b7; U+06b8; U+06b9;
31379 $this->arabPrevLink .= "\xda\xb0\xda\xb1\xda\xb2\xda\xb3\xda\xb4\xda\xb5\xda\xb6\xda\xb7\xda\xb8\xda\xb9";
31380 // U+06ba; U+06bb; U+06bc; U+06be; U+06bf;
31381 $this->arabPrevLink .= "\xda\xba\xda\xbb\xda\xbc\xda\xbe\xda\xbf";
31382 // U+06c1; U+06cc; U+06ce; U+06d0; U+06d1;
31383 $this->arabPrevLink .= "\xdb\x81\xdb\x8c\xdb\x8e\xdb\x90\xdb\x91";
31384
31385
31386
31387
31388 // JOIN TO PREVIOUS LETTER IN LOGICAL ORDER (i.e. AS FINAL FORM)
31389 $this->arabNextLink = "";
31390 // U+0622; U+0623; U+0624; U+0625; U+0626; U+0627; U+0628; U+0629;
31391 $this->arabNextLink .= "\xd8\xa2\xd8\xa3\xd8\xa4\xd8\xa5\xd8\xa6\xd8\xa7\xd8\xa8\xd8\xa9";
31392 // U+062A; U+062B; U+062C; U+062D; U+062E; U+062F;
31393 $this->arabNextLink .= "\xd8\xaa\xd8\xab\xd8\xac\xd8\xad\xd8\xae\xd8\xaf";
31394 // U+0630; U+0631; U+0632; U+0633; U+0634; U+0635; U+0636; U+0637; U+0638; U+0639; U+063A;
31395 $this->arabNextLink .= "\xd8\xb0\xd8\xb1\xd8\xb2\xd8\xb3\xd8\xb4\xd8\xb5\xd8\xb6\xd8\xb7\xd8\xb8\xd8\xb9\xd8\xba";
31396 // U+0640; U+0641; U+0642; U+0643; U+0644; U+0645; U+0646; U+0647; U+0648; U+0649; U+064A;
31397 $this->arabNextLink .= "\xd9\x80\xd9\x81\xd9\x82\xd9\x83\xd9\x84\xd9\x85\xd9\x86\xd9\x87\xd9\x88\xd9\x89\xd9\x8a";
31398 // U+0671; U+0672; U+0675; U+0676; U+0677; U+0678; U+0679;
31399 $this->arabNextLink .= "\xd9\xb1\xd9\xb2\xd9\xb5\xd9\xb6\xd9\xb7\xd9\xb8\xd9\xb9";
31400 // U+067A; U+067B; U+067C; U+067D; U+067E; U+067F;
31401 $this->arabNextLink .= "\xd9\xba\xd9\xbb\xd9\xbc\xd9\xbd\xd9\xbe\xd9\xbf";
31402 // U+0680; U+0681; U+0682; U+0683; U+0684; U+0685; U+0686; U+0687; U+0688; U+0689;
31403 $this->arabNextLink .= "\xda\x80\xda\x81\xda\x82\xda\x83\xda\x84\xda\x85\xda\x86\xda\x87\xda\x88\xda\x89";
31404 // U+068A; U+068B; U+068C; U+068D; U+068F;U+068F;
31405 $this->arabNextLink .= "\xda\x8a\xda\x8b\xda\x8c\xda\x8d\xda\x8e\xda\x8f";
31406 // U+0690; U+0691; U+0692; U+0693; U+0694; U+0695; U+0696; U+0697; U+0698; U+0699;
31407 $this->arabNextLink .= "\xda\x90\xda\x91\xda\x92\xda\x93\xda\x94\xda\x95\xda\x96\xda\x97\xda\x98\xda\x99";
31408 // U+069A; U+069B; U+069C; U+069D; U+069E; U+069F;
31409 $this->arabNextLink .= "\xda\x9a\xda\x9b\xda\x9c\xda\x9d\xda\x9e\xda\x9f";
31410 // U+06A0; U+06A1; U+06A2; U+06A3; U+06A4; U+06A5; U+06A6; U+06A7; U+06A8; U+06A9;
31411 $this->arabNextLink .= "\xda\xa0\xda\xa1\xda\xa2\xda\xa3\xda\xa4\xda\xa5\xda\xa6\xda\xa7\xda\xa8\xda\xa9";
31412 // U+06AA; U+06AB; U+06AC; U+06AD; U+06AE; U+06AF;
31413 $this->arabNextLink .= "\xda\xaa\xda\xab\xda\xac\xda\xad\xda\xae\xda\xaf";
31414 // U+06B0; U+06B1; U+06B2; U+06B3; U+06B4; U+06B5; U+06B6; U+06B7; U+06B8; U+06B9;
31415 $this->arabNextLink .= "\xda\xb0\xda\xb1\xda\xb2\xda\xb3\xda\xb4\xda\xb5\xda\xb6\xda\xb7\xda\xb8\xda\xb9";
31416 // U+06BA; U+06BB; U+06BC; U+06BE; U+06BF;
31417 $this->arabNextLink .= "\xda\xba\xda\xbb\xda\xbc\xda\xbe\xda\xbf";
31418 // U+06C0; U+06C1; U+06C2; U+06C3; U+06C4; U+06C5; U+06C6; U+06C7; U+06C8; U+06C9;
31419 $this->arabNextLink .= "\xdb\x80\xdb\x81\xdb\x82\xdb\x83\xdb\x84\xdb\x85\xdb\x86\xdb\x87\xdb\x88\xdb\x89";
31420 // U+06CA; U+06CB; U+06CC; U+06CD; U+06CE; U+06CF;
31421 $this->arabNextLink .= "\xdb\x8a\xdb\x8b\xdb\x8c\xdb\x8d\xdb\x8e\xdb\x8f";
31422 // U+06D0; U+06d1; U+06D2; U+06D3;
31423 $this->arabNextLink .= "\xdb\x90\xdb\x91\xdb\x92\xdb\x93";
31424
31425
31426 // VOWELS ++
31427
31428 // U+064b U+064c; U+064d; U+064e; U+064f; U+0650; U+0651; U+0652;
31429 $this->arabVowels = "\xd9\x8b\xd9\x8c\xd9\x8d\xd9\x8e\xd9\x8f\xd9\x90\xd9\x91\xd9\x92";
31430
31431 // Added chars that may not be vowels but should not interrupt joining
31432 // U+0670; U+0653;
31433 $this->arabVowels .= "\xd9\xb0\xd9\x93";
31434 // ? should also add - U+615, 616, 617-61A, 653-65E, 6D6-6DC, 6DF-6E4, 6E7, 6E8, 6EA-6ED
31435
31436
31437
31438 // ISOLATED FORM :: FINAL :: INITIAL :: MEDIAL
31439 // FB** - FE** = Arabic presentation Forms
31440 // F5** F6** F7** = Private use area used by unAGlyphs in mPDF
31441 $this->arabGlyphs = array(
31442 "\xd8\x8c"=>array("\xd8\x8c", "\xd8\x8c", "\xd8\x8c", "\xd8\x8c"), /* 060C, 060C, 060C, 060C */
31443 "\xd8\x9b"=>array("\xd8\x9b", "\xd8\x9b", "\xd8\x9b", "\xd8\x9b"), /* 061B, 061B, 061B, 061B */
31444 "\xd8\x9f"=>array("\xd8\x9f", "\xd8\x9f", "\xd8\x9f", "\xd8\x9f"), /* 061F, 061F, 061F, 061F */
31445 "\xd8\xa1"=>array("\xd8\xa1", "\xd8\xa1", "\xd8\xa1", "\xd8\xa1"), /* 0621, 0621, 0621, 0621 */
31446 "\xd8\xa2"=>array("\xd8\xa2", "\xef\xba\x82", "\xd8\xa2", "\xef\xba\x82"), /* 0622, FE82, 0622, FE82 */
31447 "\xd8\xa3"=>array("\xd8\xa3", "\xef\xba\x84", "\xd8\xa3", "\xef\xba\x84"), /* 0623, FE84, 0623, FE84 */
31448 "\xd8\xa4"=>array("\xd8\xa4", "\xef\xba\x86", "\xd8\xa4", "\xef\xba\x86"), /* 0624, FE86, 0624, FE86 */
31449 "\xd8\xa5"=>array("\xd8\xa5", "\xef\xba\x88", "\xd8\xa5", "\xef\xba\x88"), /* 0625, FE88, 0625, FE88 */
31450 "\xd8\xa6"=>array("\xd8\xa6", "\xef\xba\x8a", "\xef\xba\x8b", "\xef\xba\x8c"), /* 0626, FE8A, FE8B, FE8C */
31451 "\xd8\xa7"=>array("\xd8\xa7", "\xef\xba\x8e", "\xd8\xa7", "\xef\xba\x8e"), /* 0627, FE8E, 0627, FE8E */
31452 "\xd8\xa8"=>array("\xd8\xa8", "\xef\xba\x90", "\xef\xba\x91", "\xef\xba\x92"), /* 0628, FE90, FE91, FE92 */
31453 "\xd8\xa9"=>array("\xd8\xa9", "\xef\xba\x94", "\xd8\xa9", "\xef\xba\x94"), /* 0629, FE94, 0629, FE94 */
31454 "\xd8\xaa"=>array("\xd8\xaa", "\xef\xba\x96", "\xef\xba\x97", "\xef\xba\x98"), /* 062A, FE96, FE97, FE98 */
31455 "\xd8\xab"=>array("\xd8\xab", "\xef\xba\x9a", "\xef\xba\x9b", "\xef\xba\x9c"), /* 062B, FE9A, FE9B, FE9C */
31456 "\xd8\xac"=>array("\xd8\xac", "\xef\xba\x9e", "\xef\xba\x9f", "\xef\xba\xa0"), /* 062C, FE9E, FE9F, FEA0 */
31457 "\xd8\xad"=>array("\xd8\xad", "\xef\xba\xa2", "\xef\xba\xa3", "\xef\xba\xa4"), /* 062D, FEA2, FEA3, FEA4 */
31458 "\xd8\xae"=>array("\xd8\xae", "\xef\xba\xa6", "\xef\xba\xa7", "\xef\xba\xa8"), /* 062E, FEA6, FEA7, FEA8 */
31459 "\xd8\xaf"=>array("\xd8\xaf", "\xef\xba\xaa", "\xd8\xaf", "\xef\xba\xaa"), /* 062F, FEAA, 062F, FEAA */
31460 "\xd8\xb0"=>array("\xd8\xb0", "\xef\xba\xac", "\xd8\xb0", "\xef\xba\xac"), /* 0630, FEAC, 0630, FEAC */
31461 "\xd8\xb1"=>array("\xd8\xb1", "\xef\xba\xae", "\xd8\xb1", "\xef\xba\xae"), /* 0631, FEAE, 0631, FEAE */
31462 "\xd8\xb2"=>array("\xd8\xb2", "\xef\xba\xb0", "\xd8\xb2", "\xef\xba\xb0"), /* 0632, FEB0, 0632, FEB0 */
31463 "\xd8\xb3"=>array("\xd8\xb3", "\xef\xba\xb2", "\xef\xba\xb3", "\xef\xba\xb4"), /* 0633, FEB2, FEB3, FEB4 */
31464 "\xd8\xb4"=>array("\xd8\xb4", "\xef\xba\xb6", "\xef\xba\xb7", "\xef\xba\xb8"), /* 0634, FEB6, FEB7, FEB8 */
31465 "\xd8\xb5"=>array("\xd8\xb5", "\xef\xba\xba", "\xef\xba\xbb", "\xef\xba\xbc"), /* 0635, FEBA, FEBB, FEBC */
31466 "\xd8\xb6"=>array("\xd8\xb6", "\xef\xba\xbe", "\xef\xba\xbf", "\xef\xbb\x80"), /* 0636, FEBE, FEBF, FEC0 */
31467 "\xd8\xb7"=>array("\xd8\xb7", "\xef\xbb\x82", "\xef\xbb\x83", "\xef\xbb\x84"), /* 0637, FEC2, FEC3, FEC4 */
31468 "\xd8\xb8"=>array("\xd8\xb8", "\xef\xbb\x86", "\xef\xbb\x87", "\xef\xbb\x88"), /* 0638, FEC6, FEC7, FEC8 */
31469 "\xd8\xb9"=>array("\xd8\xb9", "\xef\xbb\x8a", "\xef\xbb\x8b", "\xef\xbb\x8c"), /* 0639, FECA, FECB, FECC */
31470 "\xd8\xba"=>array("\xd8\xba", "\xef\xbb\x8e", "\xef\xbb\x8f", "\xef\xbb\x90"), /* 063A, FECE, FECF, FED0 */
31471 "\xd9\x80"=>array("\xd9\x80", "\xd9\x80", "\xd9\x80", "\xd9\x80"), /* 0640, 0640, 0640, 0640 */
31472 "\xd9\x81"=>array("\xd9\x81", "\xef\xbb\x92", "\xef\xbb\x93", "\xef\xbb\x94"), /* 0641, FED2, FED3, FED4 */
31473 "\xd9\x82"=>array("\xd9\x82", "\xef\xbb\x96", "\xef\xbb\x97", "\xef\xbb\x98"), /* 0642, FED6, FED7, FED8 */
31474 "\xd9\x83"=>array("\xd9\x83", "\xef\xbb\x9a", "\xef\xbb\x9b", "\xef\xbb\x9c"), /* 0643, FEDA, FEDB, FEDC */
31475 "\xd9\x84"=>array("\xd9\x84", "\xef\xbb\x9e", "\xef\xbb\x9f", "\xef\xbb\xa0"), /* 0644, FEDE, FEDF, FEE0 */
31476 "\xd9\x85"=>array("\xd9\x85", "\xef\xbb\xa2", "\xef\xbb\xa3", "\xef\xbb\xa4"), /* 0645, FEE2, FEE3, FEE4 */
31477 "\xd9\x86"=>array("\xd9\x86", "\xef\xbb\xa6", "\xef\xbb\xa7", "\xef\xbb\xa8"), /* 0646, FEE6, FEE7, FEE8 */
31478 "\xd9\x87"=>array("\xd9\x87", "\xef\xbb\xaa", "\xef\xbb\xab", "\xef\xbb\xac"), /* 0647, FEEA, FEEB, FEEC */
31479 "\xd9\x88"=>array("\xd9\x88", "\xef\xbb\xae", "\xd9\x88", "\xef\xbb\xae"), /* 0648, FEEE, 0648, FEEE */
31480
31481 /* 0649 Alef Maksura should only appear at end of word (in Arabic) So Initial and medial are shown as isolated/final */
31482 "\xd9\x89"=>array("\xd9\x89", "\xef\xbb\xb0", "\xd9\x89", "\xef\xbb\xb0"), /* 0649, FEF0, 0649, FEF0 */
31483
31484 /* 0649 Alef Maksura Initial and Medial forms as given in Unicode FBE8 and FBE9 for Uighur Kazakh (not in some fonts) */
31485 "\xd9\x89"=>array("\xd9\x89", "\xef\xbb\xb0", "\xef\xaf\xa8", "\xef\xaf\xa9"), /* 0649, FEF0, FBE8, FBE9 not in most fonts */
31486
31487 "\xd9\x8a"=>array("\xd9\x8a", "\xef\xbb\xb2", "\xef\xbb\xb3", "\xef\xbb\xb4"), /* 064A, FEF2, FEF3, FEF4 */
31488 "\xd9\x8b"=>array("\xd9\x8b", "\xd9\x8b", "\xd9\x8b", "\xd9\x8b"), /* 064B, 064B, 064B, 064B */
31489 "\xd9\x8c"=>array("\xd9\x8c", "\xd9\x8c", "\xd9\x8c", "\xd9\x8c"), /* 064C, 064C, 064C, 064C */
31490 "\xd9\x8d"=>array("\xd9\x8d", "\xd9\x8d", "\xd9\x8d", "\xd9\x8d"), /* 064D, 064D, 064D, 064D */
31491 "\xd9\x8e"=>array("\xd9\x8e", "\xd9\x8e", "\xd9\x8e", "\xd9\x8e"), /* 064E, 064E, 064E, 064E */
31492 "\xd9\x8f"=>array("\xd9\x8f", "\xd9\x8f", "\xd9\x8f", "\xd9\x8f"), /* 064F, 064F, 064F, 064F */
31493 "\xd9\x90"=>array("\xd9\x90", "\xd9\x90", "\xd9\x90", "\xd9\x90"), /* 0650, 0650, 0650, 0650 */
31494 "\xd9\x91"=>array("\xd9\x91", "\xd9\x91", "\xd9\x91", "\xd9\x91"), /* 0651, 0651, 0651, 0651 */
31495 "\xd9\x92"=>array("\xd9\x92", "\xd9\x92", "\xd9\x92", "\xd9\x92"), /* 0652, 0652, 0652, 0652 */
31496 "\xd9\xb1"=>array("\xd9\xb1", "\xef\xad\x91", "\xd9\xb1", "\xef\xad\x91"), /* 0671, FB51, 0671, FB51 */
31497 "\xd9\xb2"=>array("\xd9\xb2", "\xef\x95\xb2", "\xd9\xb2", "\xef\x95\xb2"), /* 0672, F572, 0672, F572 */
31498 "\xd9\xb5"=>array("\xd9\xb5", "\xef\x95\xb5", "\xd9\xb5", "\xef\x95\xb5"), /* 0675, F575, 0675, F575 */
31499 "\xd9\xb8"=>array("\xd9\xb8", "\xef\x95\xb8", "\xef\xba\x8b", "\xef\xba\x8c"), /* 0678, F578, FE8B, FE8C ( as 0626 ) */
31500 "\xd9\xb9"=>array("\xd9\xb9", "\xef\xad\xa7", "\xef\xad\xa8", "\xef\xad\xa9"), /* 0679, FB67, FB68, FB69 */
31501 "\xd9\xba"=>array("\xd9\xba", "\xef\xad\x9f", "\xef\xad\xa0", "\xef\xad\xa1"), /* 067A, FB5F, FB60, FB61 */
31502 "\xd9\xbb"=>array("\xd9\xbb", "\xef\xad\x93", "\xef\xad\x94", "\xef\xad\x95"), /* 067B, FB53, FB54, FB55 */
31503 "\xd9\xbc"=>array("\xd9\xbc", "\xef\x95\xbc", "\xef\x99\xbc", "\xef\x9d\xbc"), /* 067C, F57C, F67C, F77C */
31504 "\xd9\xbd"=>array("\xd9\xbd", "\xef\x95\xbd", "\xef\x99\xbd", "\xef\x9d\xbd"), /* 067D, F57D, F67D, F77D */
31505 "\xd9\xbe"=>array("\xd9\xbe", "\xef\xad\x97", "\xef\xad\x98", "\xef\xad\x99"), /* 067E, FB57, FB58, FB59 */
31506 "\xd9\xbf"=>array("\xd9\xbf", "\xef\xad\xa3", "\xef\xad\xa4", "\xef\xad\xa5"), /* 067F, FB63, FB64, FB65 */
31507 "\xda\x80"=>array("\xda\x80", "\xef\xad\x9b", "\xef\xad\x9c", "\xef\xad\x9d"), /* 0680, FB5B, FB5C, FB5D */
31508 "\xda\x81"=>array("\xda\x81", "\xef\x96\x81", "\xef\x9a\x81", "\xef\x9e\x81"), /* 0681, F581, F681, F781 */
31509 "\xda\x82"=>array("\xda\x82", "\xef\x96\x82", "\xef\x9a\x82", "\xef\x9e\x82"), /* 0682, F582, F682, F782 */
31510 "\xda\x83"=>array("\xda\x83", "\xef\xad\xb7", "\xef\xad\xb8", "\xef\xad\xb9"), /* 0683, FB77, FB78, FB79 */
31511 "\xda\x84"=>array("\xda\x84", "\xef\xad\xb3", "\xef\xad\xb4", "\xef\xad\xb5"), /* 0684, FB73, FB74, FB75 */
31512 "\xda\x85"=>array("\xda\x85", "\xef\x96\x85", "\xef\x9a\x85", "\xef\x9e\x85"), /* 0685, F585, F685, F785 */
31513 "\xda\x86"=>array("\xda\x86", "\xef\xad\xbb", "\xef\xad\xbc", "\xef\xad\xbd"), /* 0686, FB7B, FB7C, FB7D */
31514 "\xda\x87"=>array("\xda\x87", "\xef\xad\xbf", "\xef\xae\x80", "\xef\xae\x81"), /* 0687, FB7F, FB80, FB81 */
31515 "\xda\x88"=>array("\xda\x88", "\xef\xae\x89", "\xda\x88", "\xda\x88"), /* 0688, FB89, 0688, 0688 */
31516 "\xda\x89"=>array("\xda\x89", "\xef\x96\x89", "\xda\x89", "\xda\x89"), /* 0689, F589, 0689, 0689 */
31517 "\xda\x91"=>array("\xda\x91", "\xef\xae\x8d", "\xda\x91", "\xef\xae\x8d"), /* 0691, FB8D, 0691, FB8D */
31518 "\xda\x93"=>array("\xda\x93", "\xef\x96\x93", "\xda\x93", "\xda\x93"), /* 0693, F593, 0693, 0693 */
31519 "\xda\x96"=>array("\xda\x96", "\xef\x96\x96", "\xda\x96", "\xda\x96"), /* 0696, F596, 0696, 0696 */
31520 "\xda\x98"=>array("\xda\x98", "\xef\xae\x8b", "\xda\x98", "\xef\xae\x8b"), /* 0698, FB8B, 0698, FB8B */
31521 "\xda\x9a"=>array("\xda\x9a", "\xef\x96\x9a", "\xef\x9a\x9a", "\xef\x9e\x9a"), /* 069A, F59A, F69A, F79A */
31522 "\xda\x9b"=>array("\xda\x9b", "\xef\x96\x9b", "\xef\x9a\x9b", "\xef\x9e\x9b"), /* 069B, F59B, F69B, F79B */
31523 "\xda\x9c"=>array("\xda\x9c", "\xef\x96\x9c", "\xef\x9a\x9c", "\xef\x9e\x9c"), /* 069C, F59C, F69C, F79C */
31524 "\xda\x9d"=>array("\xda\x9d", "\xef\x96\x9d", "\xef\x9a\x9d", "\xef\x9e\x9d"), /* 069D, F59D, F69D, F79D */
31525 "\xda\x9e"=>array("\xda\x9e", "\xef\x96\x9e", "\xef\x9a\x9e", "\xef\x9e\x9e"), /* 069E, F59E, F69E, F79E */
31526 "\xda\xa0"=>array("\xda\xa0", "\xef\x96\xa0", "\xef\x9a\xa0", "\xef\x9e\xa0"), /* 06A0, F5A0, F6A0, F7A0 */
31527 "\xda\xa1"=>array("\xda\xa1", "\xef\x96\xa1", "\xef\x9a\xa1", "\xef\x9e\xa1"), /* 06A1, F5A1, F6A1, F7A1 */
31528 "\xda\xa2"=>array("\xda\xa2", "\xef\x96\xa2", "\xef\x9a\xa2", "\xef\x9e\xa2"), /* 06A2, F5A2, F6A2, F7A2 */
31529 "\xda\xa3"=>array("\xda\xa3", "\xef\x96\xa3", "\xef\x9a\xa3", "\xef\x9e\xa3"), /* 06A3, F5A3, F6A3, F7A3 */
31530 "\xda\xa4"=>array("\xda\xa4", "\xef\xad\xab", "\xef\xad\xac", "\xef\xad\xad"), /* 06A4, FB6B, FB6C, FB6D */
31531 "\xda\xa5"=>array("\xda\xa5", "\xef\x96\xa5", "\xef\x9a\xa5", "\xef\x9e\xa5"), /* 06A5, F5A5, F6A5, F7A5 */
31532 "\xda\xa6"=>array("\xda\xa6", "\xef\xad\xaf", "\xef\xad\xb0", "\xef\xad\xb1"), /* 06A6, FB6F, FB70, FB71 */
31533 "\xda\xa9"=>array("\xda\xa9", "\xef\xae\x8f", "\xef\xae\x90", "\xef\xae\x91"), /* 06A9, FB8F, FB90, FB91 */
31534 "\xda\xaa"=>array("\xda\xaa", "\xef\x96\xaa", "\xef\x9a\xaa", "\xef\x9e\xaa"), /* 06AA, F5AA, F6AA, F7AA */
31535 "\xda\xab"=>array("\xda\xab", "\xef\x96\xab", "\xef\x9a\xab", "\xef\x9e\xab"), /* 06AB, F5AB, F6AB, F7AB */
31536 "\xda\xac"=>array("\xda\xac", "\xef\x96\xac", "\xef\x9a\xac", "\xef\x9e\xac"), /* 06AC, F5AC, F6AC, F7AC */
31537 "\xda\xad"=>array("\xda\xad", "\xef\xaf\x94", "\xef\xaf\x95", "\xef\xaf\x96"), /* 06AD, FBD4, FBD5, FBD6 */
31538 "\xda\xae"=>array("\xda\xae", "\xef\x96\xae", "\xef\x9a\xae", "\xef\x9e\xae"), /* 06AE, F5AE, F6AE, F7AE */
31539 "\xda\xaf"=>array("\xda\xaf", "\xef\xae\x93", "\xef\xae\x94", "\xef\xae\x95"), /* 06Af, FB93, FB94, FB95 */
31540 "\xda\xb0"=>array("\xda\xb0", "\xef\x96\xb0", "\xef\x9a\xb0", "\xef\x9e\xb0"), /* 06B0, F5B0, F6B0, F7B0 */
31541 "\xda\xb1"=>array("\xda\xb1", "\xef\xae\x9b", "\xef\xae\x9c", "\xef\xae\x9d"), /* 06B1, FB9B, FB9C, FB9D */
31542 "\xda\xb2"=>array("\xda\xb2", "\xef\x96\xb2", "\xef\x9a\xb2", "\xef\x9e\xb2"), /* 06B2, F5B2, F6B2, F7B2 */
31543 "\xda\xb3"=>array("\xda\xb3", "\xef\xae\x97", "\xef\xae\x98", "\xef\xae\x99"), /* 06B3, FB97, FB98, FB99 */
31544 "\xda\xb4"=>array("\xda\xb4", "\xef\x96\xb4", "\xef\x9a\xb4", "\xef\x9e\xb4"), /* 06B4, F5B4, F6B4, F7B4 */
31545 "\xda\xb5"=>array("\xda\xb5", "\xef\x96\xb5", "\xef\x9a\xb5", "\xef\x9e\xb5"), /* 06B5, F5B5, F6B5, F7B5 */
31546 "\xda\xb6"=>array("\xda\xb6", "\xef\x96\xb6", "\xef\x9a\xb6", "\xef\x9e\xb6"), /* 06B6, F5B6, F6B6, F7B6 */
31547 "\xda\xb7"=>array("\xda\xb7", "\xef\x96\xb7", "\xef\x9a\xb7", "\xef\x9e\xb7"), /* 06B7, F5B7, F6B7, F7B7 */
31548 "\xda\xb8"=>array("\xda\xb8", "\xef\x96\xb8", "\xef\x9a\xb8", "\xef\x9e\xb8"), /* 06B8, F5B8, F6B8, F7B8 */
31549 "\xda\xb9"=>array("\xda\xb9", "\xef\x96\xb9", "\xef\x9a\xb9", "\xef\x9e\xb9"), /* 06B9, F5B9, F6B9, F7B9 */
31550 "\xda\xba"=>array("\xda\xba", "\xef\xae\x9f", "\xda\xba", "\xda\xba"), /* 06BA, FB9F, 06BA, 06BA */
31551 "\xda\xbb"=>array("\xda\xbb", "\xef\xae\xa1", "\xef\xae\xa2", "\xef\xae\xa3"), /* 06BB, FBA1, FBA2, FBA3 */
31552 "\xda\xbc"=>array("\xda\xbc", "\xef\x96\xbc", "\xef\x9a\xbc", "\xef\x9e\xbc"), /* 06BC, F5BC, F6BC, F7BC */
31553 "\xda\xbe"=>array("\xda\xbe", "\xef\xae\xab", "\xef\xae\xac", "\xef\xae\xad"), /* 06BE, FBAB, FBAC, FBAD */
31554 "\xda\xbf"=>array("\xda\xbf", "\xef\x96\xbf", "\xef\x9a\xbf", "\xef\x9e\xbf"), /* 06BF, F5BF, F6BF, F7BF */
31555 "\xdb\x80"=>array("\xdb\x80", "\xef\xae\xa5", "\xdb\x80", "\xef\xae\xa5"), /* 06C0, FBA5, 06C0, FBA5 */
31556 "\xdb\x81"=>array("\xdb\x81", "\xef\xae\xa7", "\xef\xae\xa8", "\xef\xae\xa9"), /* 06C1, FBA7, FBA8, FBA9 */
31557 "\xdb\x8c"=>array("\xdb\x8c", "\xef\xaf\xbd", "\xef\xaf\xbe", "\xef\xaf\xbf"), /* 06CC, FBFD, FBFE, FBFF */
31558 "\xdb\x8d"=>array("\xdb\x8d", "\xef\x97\x8d", "\xdb\x8d", "\xef\x97\x8d"), /* 06CD, F5CD, 06CD, F5CD */
31559 "\xdb\x8e"=>array("\xdb\x8e", "\xef\x97\x8e", "\xef\x9b\x8e", "\xef\x9f\x8e"), /* 06CE, F5CE, F6CE, F7CE */
31560 "\xdb\x90"=>array("\xdb\x90", "\xef\xaf\xa5", "\xef\xaf\xa6", "\xef\xaf\xa7"), /* 06D0, FBE5, FBE6, FBE7 */
31561 "\xdb\x91"=>array("\xdb\x91", "\xef\x97\x91", "\xef\xad\x98", "\xef\xad\x99"), /* 06D1, F5D1, FB58, FB59 Fudge borrows from 067E */
31562 "\xdb\x92"=>array("\xdb\x92", "\xef\xae\xaf", "\xdb\x92", "\xef\xae\xaf"), /* 06D2, FBAF, 06D2, FBAF */
31563 "\xdb\x93"=>array("\xdb\x93", "\xef\xae\xb1", "\xdb\x93", "\xef\xae\xb1"), /* 06D3, FBB1, 06D3, FBB1 */
31564 );
31565
31566
31567 // LAM with ALEF ligatures (Mandatory ligatures)
31568
31569 // U+0644; U+0622; U+0644; U+0623; U+0644; U+0625; U+0644; U+0627;
31570 $this->arabLigGlyphs = "\xd9\x84\xd8\xa2\xd9\x84\xd8\xa3\xd9\x84\xd8\xa5\xd9\x84\xd8\xa7";
31571 $this->arabLigHex = 'FEF5FEF6FEF5FEF6FEF7FEF8FEF7FEF8FEF9FEFAFEF9FEFAFEFBFEFCFEFBFEFC';
31572
31573 }
31574
31575 // mPDF 5.4.08
31576 function ArabJoin($str) {
31577 if (!$this->arabGlyphs) { $this->InitArabic(); }
31578 $crntChar = null;
31579 $prevChar = null;
31580 $nextChar = null;
31581 $output = array();
31582 $chars = preg_split('//u', $str);
31583 $max = count($chars);
31584 for ($i = $max - 1; $i >= 0; $i--) {
31585 $crntChar = $chars[$i];
31586 if ($i > 0){ $prevChar = $chars[$i - 1]; }
31587 else{ $prevChar = NULL; }
31588 if ($prevChar && mb_strpos($this->arabVowels, $prevChar, 0, 'utf-8') !== false) {
31589 $prevChar = $chars[$i - 2];
31590 if ($prevChar && mb_strpos($this->arabVowels, $prevChar, 0, 'utf-8') !== false) {
31591 $prevChar = $chars[$i - 3];
31592 }
31593 }
31594 if ($crntChar && mb_strpos($this->arabVowels, $crntChar, 0, 'utf-8') !== false) {
31595 // If next_char = nextLink && prev_char = prevLink:
31596 // Added && $prevchar (defined) else error on mb_strpos()
31597 if ($chars[$i + 1] && (mb_strpos($this->arabNextLink, $chars[$i + 1], 0, 'utf-8') !== false) && $prevChar && (mb_strpos($this->arabPrevLink, $prevChar, 0, 'utf-8') !== false)) {
31598 $output[] = $this->get_arab_glyphs($crntChar, 1); // <final> form
31599 }
31600 else {
31601 $output[] = $this->get_arab_glyphs($crntChar, 0); // <isolated> form
31602 }
31603 continue;
31604 }
31605 // NB = &#x622 &#x623; &#x625; &#x627; &#x644;
31606 if (isset($chars[$i + 1]) && in_array($chars[$i + 1], array("\xd8\xa2","\xd8\xa3","\xd8\xa5","\xd8\xa7")) && $crntChar == "\xd9\x84"){
31607 continue;
31608 }
31609 if (ord($crntChar) < 128) {
31610 $output[] = $crntChar;
31611 $nextChar = $crntChar;
31612 continue;
31613 }
31614 $form = 0;
31615 if ($prevChar == "\xd9\x84" && ($crntChar == "\xd8\xa2" || $crntChar == "\xd8\xa3" || $crntChar == "\xd8\xa5" || $crntChar == "\xd8\xa7")) {
31616 if ($chars[$i - 2] && mb_strpos($this->arabPrevLink, $chars[$i - 2], 0, 'utf-8') !== false) {
31617 $form++; // <final> form
31618 }
31619 $pos = mb_strpos($this->arabLigGlyphs, ($prevChar . $crntChar), 0, 'utf-8');
31620 $pos = $pos*8 + $form*4;
31621 $pres = (mb_substr($this->arabLigHex, $pos, 4, 'utf-8'));
31622 // If presentation forms for mandatory ligatures with diacritics not present (even if remapped from e.g. uni0644uni0625)
31623 // try replacing with mandatory ligature Alef/lam isolated/final FEFB/FEFC + diacritic glyph
31624 if (!$this->_charDefined($this->CurrentFont['cw'], hexdec($pres)) && $this->_charDefined($this->CurrentFont['cw'], hexdec('FEFB'))) {
31625 if ($pres=='FEF5') { $output[] = strcode2utf('&#xFEFB;&#x0653;'); }
31626 else if ($pres=='FEF6') { $output[] = strcode2utf('&#xFEFC;&#x0653;'); }
31627 else if ($pres=='FEF7') { $output[] = strcode2utf('&#xFEFB;&#x0654;'); }
31628 else if ($pres=='FEF8') { $output[] = strcode2utf('&#xFEFC;&#x0654;'); }
31629 else if ($pres=='FEF9') { $output[] = strcode2utf('&#xFEFB;&#x0655;'); }
31630 else if ($pres=='FEFA') { $output[] = strcode2utf('&#xFEFC;&#x0655;'); }
31631 }
31632 else {
31633 $output[] = strcode2utf('&#x' . $pres . ';');
31634 }
31635 $nextChar = $prevChar;
31636 continue;
31637 }
31638 if ($prevChar && mb_strpos($this->arabPrevLink, $prevChar, 0, 'utf-8') !== false) {
31639 $form++;
31640 }
31641 if ($nextChar && mb_strpos($this->arabNextLink, $nextChar, 0, 'utf-8') !== false) {
31642 $form += 2;
31643 }
31644 $output[] = $this->get_arab_glyphs($crntChar, $form) ;
31645 $nextChar = $crntChar;
31646 }
31647 $ra = array_reverse($output);
31648 $s = implode($ra);
31649 return $s;
31650 }
31651
31652 // mPDF 5.7+
31653 function arabJoinPregCallback($matches) {
31654 return $this->ArabJoin(stripslashes($matches[1]));
31655 }
31656
31657 // mPDF 5.4.08
31658 function get_arab_glyphs($char, $type) {
31659 if ($type>0 && isset($this->arabGlyphs[$char])) {
31660 // If presentation form specified FB** - FE** = Arabic presentation Forms
31661 if (preg_match("/[\x{FB50}-\x{FEFF}]/u",$this->arabGlyphs[$char][$type])) {
31662 $unicode = $this->UTF8StringToArray($this->arabGlyphs[$char][$type], false);
31663 if ($this->_charDefined($this->CurrentFont['cw'],$unicode[0])) { return $this->arabGlyphs[$char][$type]; }
31664 else if (isset($this->CurrentFont['unAGlyphs'])) {
31665 $uni = $this->UTF8StringToArray($char, false);
31666 $pua = $uni[0] - 1536 + 62464 + 256*$type ;
31667 if ($this->_charDefined($this->CurrentFont['cw'], $pua)) { return strcode2utf('&#x' . dechex($pua) . ';'); }
31668 else return $char;
31669 }
31670 else return $char;
31671 }
31672 // If PUA form specified and unAGlphs font set F5** F6** F7** = Private use area used by unAGlyphs in mPDF
31673 if (preg_match("/[\x{F500}-\x{F7FF}]/u",$this->arabGlyphs[$char][$type]) && isset($this->CurrentFont['unAGlyphs'])) {
31674 $unicode = $this->UTF8StringToArray($this->arabGlyphs[$char][$type], false);
31675 if ($this->_charDefined($this->CurrentFont['cw'],$unicode[0])) { return $this->arabGlyphs[$char][$type]; }
31676 else return $char;
31677 }
31678 return $this->arabGlyphs[$char][$type];
31679 }
31680 else return $char;
31681 }
31682 /*-- END RTL --*/
31683
31684
31685
31686 //===========================
31687 // Functions originally in htmltoolkit - moved mPDF 4.0
31688
31689 // Call-back function Used for usort in fn _tableWrite
31690
31691 function _cmpdom($a, $b) {
31692 return ($a["dom"] < $b["dom"]) ? -1 : 1;
31693 }
31694
31695 function mb_strrev($str, $enc = 'utf-8'){
31696 $ch = array();
31697 $ch = preg_split('//u',$str);
31698 $revch = array_reverse($ch);
31699 return implode('',$revch);
31700 }
31701
31702 /*-- COLUMNS --*/
31703 // Callback function from function printcolumnbuffer in mpdf
31704 function columnAdjustAdd($type,$k,$xadj,$yadj,$a,$b,$c=0,$d=0,$e=0,$f=0) {
31705 if ($type == 'Td') { // xpos,ypos
31706 $a += ($xadj * $k);
31707 $b -= ($yadj * $k);
31708 return 'BT '.sprintf('%.3F %.3F',$a,$b).' Td';
31709 }
31710 else if ($type == 're') { // xpos,ypos,width,height
31711 $a += ($xadj * $k);
31712 $b -= ($yadj * $k);
31713 return sprintf('%.3F %.3F %.3F %.3F',$a,$b,$c,$d).' re';
31714 }
31715 else if ($type == 'l') { // xpos,ypos,x2pos,y2pos
31716 $a += ($xadj * $k);
31717 $b -= ($yadj * $k);
31718 return sprintf('%.3F %.3F l',$a,$b);
31719 }
31720 else if ($type == 'img') { // width,height,xpos,ypos
31721 $c += ($xadj * $k);
31722 $d -= ($yadj * $k);
31723 return sprintf('q %.3F 0 0 %.3F %.3F %.3F',$a,$b,$c,$d).' cm /'.$e;
31724 }
31725 else if ($type == 'draw') { // xpos,ypos
31726 $a += ($xadj * $k);
31727 $b -= ($yadj * $k);
31728 return sprintf('%.3F %.3F m',$a,$b);
31729 }
31730 else if ($type == 'bezier') { // xpos,ypos,x2pos,y2pos,x3pos,y3pos
31731 $a += ($xadj * $k);
31732 $b -= ($yadj * $k);
31733 $c += ($xadj * $k);
31734 $d -= ($yadj * $k);
31735 $e += ($xadj * $k);
31736 $f -= ($yadj * $k);
31737 return sprintf('%.3F %.3F %.3F %.3F %.3F %.3F',$a,$b,$c,$d,$e,$f).' c';
31738 }
31739 }
31740 /*-- END COLUMNS --*/
31741
31742
31743
31744 function ConvertColor($color="#000000"){
31745 $color = trim(strtolower($color));
31746 $c = false;
31747 if ($color=='transparent') { return false; }
31748 else if ($color=='inherit') { return false; }
31749 else if (isset($this->SVGcolors[$color])) $color = $this->SVGcolors[$color];
31750
31751 if (preg_match('/^[\d]+$/',$color)) { $c = (array(1,$color)); } // i.e. integer only
31752 else if ($color[0] == '#') { //case of #nnnnnn or #nnn
31753 $cor = preg_replace('/\s+.*/','',$color); // in case of Background: #CCC url() x-repeat etc.
31754 if (strlen($cor) == 4) { // Turn #RGB into #RRGGBB
31755 $cor = "#" . $cor[1] . $cor[1] . $cor[2] . $cor[2] . $cor[3] . $cor[3];
31756 }
31757 $r = hexdec(substr($cor, 1, 2));
31758 $g = hexdec(substr($cor, 3, 2));
31759 $b = hexdec(substr($cor, 5, 2));
31760 $c = array(3,$r,$g,$b);
31761 }
31762 else if (preg_match('/(rgba|rgb|device-cmyka|cmyka|device-cmyk|cmyk|hsla|hsl|spot)\((.*?)\)/',$color,$m)) { // mPDF 5.6.05
31763 $type= $m[1];
31764 $cores = explode(",", $m[2]);
31765 $ncores = count($cores);
31766 if (stristr($cores[0],'%') ) {
31767 $cores[0] += 0;
31768 if ($type=='rgb' || $type=='rgba') { $cores[0] = intval($cores[0]*255/100); }
31769 }
31770 if ($ncores>1 && stristr($cores[1],'%') ) {
31771 $cores[1] += 0;
31772 if ($type=='rgb' || $type=='rgba') { $cores[1] = intval($cores[1]*255/100); }
31773 if ($type=='hsl' || $type=='hsla') { $cores[1] = $cores[1]/100; }
31774 }
31775 if ($ncores>2 && stristr($cores[2],'%') ) {
31776 $cores[2] += 0;
31777 if ($type=='rgb' || $type=='rgba') { $cores[2] = intval($cores[2]*255/100); }
31778 if ($type=='hsl' || $type=='hsla') { $cores[2] = $cores[2]/100; }
31779 }
31780 if ($ncores>3 && stristr($cores[3],'%') ) {
31781 $cores[3] += 0;
31782 }
31783
31784 if ($type=='rgb') { $c = array(3,$cores[0],$cores[1],$cores[2]); }
31785 else if ($type=='rgba') { $c = array(5,$cores[0],$cores[1],$cores[2],$cores[3]*100); }
31786 else if ($type=='cmyk' || $type=='device-cmyk') { $c = array(4,$cores[0],$cores[1],$cores[2],$cores[3]); } // mPDF 5.6.05
31787 else if ($type=='cmyka' || $type=='device-cmyka') { $c = array(6,$cores[0],$cores[1],$cores[2],$cores[3],$cores[4]*100); } // mPDF 5.6.05
31788 else if ($type=='hsl' || $type=='hsla') {
31789 $conv = $this->hsl2rgb($cores[0]/360,$cores[1],$cores[2]);
31790 if ($type=='hsl') { $c = array(3,$conv[0],$conv[1],$conv[2]); }
31791 else if ($type=='hsla') { $c = array(5,$conv[0],$conv[1],$conv[2],$cores[3]*100); }
31792 }
31793 else if ($type=='spot') {
31794 $name = strtoupper(trim($cores[0]));
31795 // mPDF 5.6.59
31796 if(!isset($this->spotColors[$name])) {
31797 if (isset($cores[5])) { $this->AddSpotColor($cores[0],$cores[2],$cores[3],$cores[4],$cores[5]); }
31798 else { $this->Error('Undefined spot color: '.$name); }
31799 }
31800 $c = array(2,$this->spotColors[$name]['i'],$cores[1]);
31801 }
31802 }
31803
31804
31805 // $this->restrictColorSpace
31806 // 1 - allow GRAYSCALE only [convert CMYK/RGB->gray]
31807 // 2 - allow RGB / SPOT COLOR / Grayscale [convert CMYK->RGB]
31808 // 3 - allow CMYK / SPOT COLOR / Grayscale [convert RGB->CMYK]
31809 if ($this->PDFA || $this->PDFX || $this->restrictColorSpace) {
31810 if ($c[0]==1) { // GRAYSCALE
31811 }
31812 else if ($c[0]==2) { // SPOT COLOR
31813 if (!isset($this->spotColorIDs[$c[1]])) { die('Error: Spot colour has not been defined - '.$this->spotColorIDs[$c[1]]); }
31814 if ($this->PDFA) {
31815 if ($this->PDFA && !$this->PDFAauto) { $this->PDFAXwarnings[] = "Spot color specified '".$this->spotColorIDs[$c[1]]."' (converted to process color)"; }
31816 if ($this->restrictColorSpace!=3) {
31817 $sp = $this->spotColors[$this->spotColorIDs[$c[1]]];
31818 $c = $this->cmyk2rgb(array(4,$sp['c'],$sp['m'],$sp['y'],$sp['k']));
31819 }
31820 }
31821 else if ($this->restrictColorSpace==1) {
31822 $sp = $this->spotColors[$this->spotColorIDs[$c[1]]];
31823 $c = $this->cmyk2gray(array(4,$sp['c'],$sp['m'],$sp['y'],$sp['k']));
31824 }
31825 }
31826 else if ($c[0]==3) { // RGB
31827 if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace==3)) {
31828 if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "RGB color specified '".$color."' (converted to CMYK)"; }
31829 $c = $this->rgb2cmyk($c);
31830 }
31831 else if ($this->restrictColorSpace==1) { $c = $this->rgb2gray($c); }
31832 else if ($this->restrictColorSpace==3) { $c = $this->rgb2cmyk($c); }
31833 }
31834 else if ($c[0]==4) { // CMYK
31835 if ($this->PDFA && $this->restrictColorSpace!=3) {
31836 if ($this->PDFA && !$this->PDFAauto) { $this->PDFAXwarnings[] = "CMYK color specified '".$color."' (converted to RGB)"; }
31837 $c = $this->cmyk2rgb($c);
31838 }
31839 else if ($this->restrictColorSpace==1) { $c = $this->cmyk2gray($c); }
31840 else if ($this->restrictColorSpace==2) { $c = $this->cmyk2rgb($c); }
31841 }
31842 else if ($c[0]==5) { // RGBa
31843 if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace==3)) {
31844 if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "RGB color with transparency specified '".$color."' (converted to CMYK without transparency)"; }
31845 $c = $this->rgb2cmyk($c);
31846 $c = array(4, $c[1], $c[2], $c[3], $c[4]);
31847 }
31848 else if ($this->PDFA && $this->restrictColorSpace!=3) {
31849 if (!$this->PDFAauto) { $this->PDFAXwarnings[] = "RGB color with transparency specified '".$color."' (converted to RGB without transparency)"; }
31850 $c = $this->rgb2cmyk($c);
31851 $c = array(4, $c[1], $c[2], $c[3], $c[4]);
31852 }
31853 else if ($this->restrictColorSpace==1) { $c = $this->rgb2gray($c); }
31854 else if ($this->restrictColorSpace==3) { $c = $this->rgb2cmyk($c); }
31855 }
31856 else if ($c[0]==6) { // CMYKa
31857 if ($this->PDFA && $this->restrictColorSpace!=3) {
31858 if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "CMYK color with transparency specified '".$color."' (converted to RGB without transparency)"; }
31859 $c = $this->cmyk2rgb($c);
31860 $c = array(3, $c[1], $c[2], $c[3]);
31861 }
31862 else if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace==3)) {
31863 if (($this->PDFA && !$this->PDFAauto) || ($this->PDFX && !$this->PDFXauto)) { $this->PDFAXwarnings[] = "CMYK color with transparency specified '".$color."' (converted to CMYK without transparency)"; }
31864 $c = $this->cmyk2rgb($c);
31865 $c = array(3, $c[1], $c[2], $c[3]);
31866 }
31867 else if ($this->restrictColorSpace==1) { $c = $this->cmyk2gray($c); }
31868 else if ($this->restrictColorSpace==2) { $c = $this->cmyk2rgb($c); }
31869 }
31870 }
31871 if (is_array($c)) {
31872 $c = array_pad($c, 6, 0);
31873 $cstr = pack("a1ccccc", $c[0], ($c[1] & 0xFF), ($c[2] & 0xFF), ($c[3] & 0xFF), ($c[4] & 0xFF), ($c[5] & 0xFF) );
31874 }
31875 return $cstr;
31876 }
31877
31878 function rgb2gray($c) {
31879 if (isset($c[4])) { return array(1,(($c[1] * .21) + ($c[2] * .71) + ($c[3] * .07)), ord(1), $c[4]); }
31880 else { return array(1,(($c[1] * .21) + ($c[2] * .71) + ($c[3] * .07))); }
31881 }
31882
31883 function cmyk2gray($c) {
31884 $rgb = $this->cmyk2rgb($c);
31885 return $this->rgb2gray($rgb);
31886 }
31887
31888 function rgb2cmyk($c) {
31889 $cyan = 1 - ($c[1] / 255);
31890 $magenta = 1 - ($c[2] / 255);
31891 $yellow = 1 - ($c[3] / 255);
31892 $min = min($cyan, $magenta, $yellow);
31893
31894 if ($min == 1) {
31895 if ($c[0]==5) { return array (6,100,100,100,100, $c[4]); }
31896 else { return array (4,100,100,100,100); }
31897 // For K-Black
31898 //if ($c[0]==5) { return array (6,0,0,0,100, $c[4]); }
31899 //else { return array (4,0,0,0,100); }
31900 }
31901 $K = $min;
31902 $black = 1 - $K;
31903 if ($c[0]==5) { return array (6,($cyan-$K)*100/$black, ($magenta-$K)*100/$black, ($yellow-$K)*100/$black, $K*100, $c[4]); }
31904 else { return array (4,($cyan-$K)*100/$black, ($magenta-$K)*100/$black, ($yellow-$K)*100/$black, $K*100); }
31905 }
31906
31907
31908 function cmyk2rgb($c) {
31909 $rgb = array();
31910 $colors = 255 - ($c[4]*2.55);
31911 $rgb[0] = intval($colors * (255 - ($c[1]*2.55))/255);
31912 $rgb[1] = intval($colors * (255 - ($c[2]*2.55))/255);
31913 $rgb[2] = intval($colors * (255 - ($c[3]*2.55))/255);
31914 if ($c[0]==6) { return array (5,$rgb[0],$rgb[1],$rgb[2], $c[5]); }
31915 else { return array (3,$rgb[0],$rgb[1],$rgb[2]); }
31916 }
31917
31918 function rgb2hsl($var_r, $var_g, $var_b) {
31919 $var_min = min($var_r,$var_g,$var_b);
31920 $var_max = max($var_r,$var_g,$var_b);
31921 $del_max = $var_max - $var_min;
31922 $l = ($var_max + $var_min) / 2;
31923 if ($del_max == 0) {
31924 $h = 0;
31925 $s = 0;
31926 }
31927 else {
31928 if ($l < 0.5) { $s = $del_max / ($var_max + $var_min); }
31929 else { $s = $del_max / (2 - $var_max - $var_min); }
31930 $del_r = ((($var_max - $var_r) / 6) + ($del_max / 2)) / $del_max;
31931 $del_g = ((($var_max - $var_g) / 6) + ($del_max / 2)) / $del_max;
31932 $del_b = ((($var_max - $var_b) / 6) + ($del_max / 2)) / $del_max;
31933 if ($var_r == $var_max) { $h = $del_b - $del_g; }
31934 elseif ($var_g == $var_max) { $h = (1 / 3) + $del_r - $del_b; }
31935 elseif ($var_b == $var_max) { $h = (2 / 3) + $del_g - $del_r; };
31936 if ($h < 0) { $h += 1; }
31937 if ($h > 1) { $h -= 1; }
31938 }
31939 return array($h,$s,$l);
31940 }
31941
31942
31943 function hsl2rgb($h2,$s2,$l2) {
31944 // Input is HSL value of complementary colour, held in $h2, $s, $l as fractions of 1
31945 // Output is RGB in normal 255 255 255 format, held in $r, $g, $b
31946 // Hue is converted using function hue_2_rgb, shown at the end of this code
31947 if ($s2 == 0) {
31948 $r = $l2 * 255;
31949 $g = $l2 * 255;
31950 $b = $l2 * 255;
31951 }
31952 else {
31953 if ($l2 < 0.5) { $var_2 = $l2 * (1 + $s2); }
31954 else { $var_2 = ($l2 + $s2) - ($s2 * $l2); }
31955 $var_1 = 2 * $l2 - $var_2;
31956 $r = round(255 * $this->hue_2_rgb($var_1,$var_2,$h2 + (1 / 3)));
31957 $g = round(255 * $this->hue_2_rgb($var_1,$var_2,$h2));
31958 $b = round(255 * $this->hue_2_rgb($var_1,$var_2,$h2 - (1 / 3)));
31959 }
31960 return array($r,$g,$b);
31961 }
31962
31963 function hue_2_rgb($v1,$v2,$vh) {
31964 // Function to convert hue to RGB, called from above
31965 if ($vh < 0) { $vh += 1; };
31966 if ($vh > 1) { $vh -= 1; };
31967 if ((6 * $vh) < 1) { return ($v1 + ($v2 - $v1) * 6 * $vh); };
31968 if ((2 * $vh) < 1) { return ($v2); };
31969 if ((3 * $vh) < 2) { return ($v1 + ($v2 - $v1) * ((2 / 3 - $vh) * 6)); };
31970 return ($v1);
31971 }
31972
31973 function _invertColor($cor) {
31974 if ($cor[0]==3 || $cor[0]==5) { // RGB
31975 return array(3, (255-$cor[1]), (255-$cor[2]), (255-$cor[3]));
31976 }
31977 else if ($cor[0]==4 || $cor[0]==6) { // CMYK
31978 return array(4, (100-$cor[1]), (100-$cor[2]), (100-$cor[3]), (100-$cor[4]));
31979 }
31980 else if ($cor[0]==1) { // Grayscale
31981 return array(1, (255-$cor[1]));
31982 }
31983 // Cannot cope with non-RGB colors at present
31984 die('Error in _invertColor - trying to invert non-RGB color');
31985 }
31986
31987 function _colAtoString($cor) {
31988 $s = '';
31989 if ($cor{0}==1) $s = 'rgb('.ord($cor{1}).','.ord($cor{1}).','.ord($cor{1}).')';
31990 else if ($cor{0}==2) $s = 'spot('.ord($cor{1}).','.ord($cor{2}).')'; // SPOT COLOR
31991 else if ($cor{0}==3) $s = 'rgb('.ord($cor{1}).','.ord($cor{2}).','.ord($cor{3}).')';
31992 else if ($cor{0}==4) $s = 'cmyk('.ord($cor{1}).','.ord($cor{2}).','.ord($cor{3}).','.ord($cor{4}).')';
31993 else if ($cor{0}==5) $s = 'rgba('.ord($cor{1}).','.ord($cor{2}).','.ord($cor{3}).','.sprintf('%0.2F',ord($cor{4})/100).')';
31994 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).')';
31995 return $s;
31996 }
31997
31998 function ConvertSize($size=5,$maxsize=0,$fontsize=false,$usefontsize=true){
31999 // usefontsize - setfalse for e.g. margins - will ignore fontsize for % values
32000 // Depends of maxsize value to make % work properly. Usually maxsize == pagewidth
32001 // For text $maxsize = Fontsize
32002 // Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize
32003 //Identify size (remember: we are using 'mm' units here)
32004 $size = trim(strtolower($size));
32005
32006 if ( $size == 'thin' ) $size = 1*(25.4/$this->dpi); //1 pixel width for table borders
32007 elseif ( stristr($size,'px') ) $size *= (25.4/$this->dpi); //pixels
32008 elseif ( stristr($size,'cm') ) $size *= 10; //centimeters
32009 elseif ( stristr($size,'mm') ) $size += 0; //millimeters
32010 elseif ( stristr($size,'pt') ) $size *= 25.4/72; //72 pts/inch
32011 elseif ( stristr($size,'rem') ) { // mPDF 5.6.12
32012 $size += 0; //make "0.83rem" become simply "0.83"
32013 $size *= ($this->default_font_size / _MPDFK);
32014 }
32015 elseif ( stristr($size,'em') ) {
32016 $size += 0; //make "0.83em" become simply "0.83"
32017 if ($fontsize) { $size *= $fontsize; }
32018 else { $size *= $maxsize; }
32019 }
32020 elseif ( stristr($size,'%') ) {
32021 $size += 0; //make "90%" become simply "90"
32022 if ($fontsize && $usefontsize) { $size *= $fontsize/100; }
32023 else { $size *= $maxsize/100; }
32024 }
32025 elseif ( stristr($size,'in') ) $size *= 25.4; //inches
32026 elseif ( stristr($size,'pc') ) $size *= 38.1/9; //PostScript picas
32027 elseif ( stristr($size,'ex') ) { // Approximates "ex" as half of font height
32028 $size += 0; //make "3.5ex" become simply "3.5"
32029 if ($fontsize) { $size *= $fontsize/2; }
32030 else { $size *= $maxsize/2; }
32031 }
32032 elseif ( $size == 'medium' ) $size = 3*(25.4/$this->dpi); //3 pixel width for table borders
32033 elseif ( $size == 'thick' ) $size = 5*(25.4/$this->dpi); //5 pixel width for table borders
32034 elseif ($size == 'xx-small') {
32035 if ($fontsize) { $size *= $fontsize*0.7; }
32036 else { $size *= $maxsize*0.7; }
32037 }
32038 elseif ($size == 'x-small') {
32039 if ($fontsize) { $size *= $fontsize*0.77; }
32040 else { $size *= $maxsize*0.77; }
32041 }
32042 elseif ($size == 'small') {
32043 if ($fontsize) { $size *= $fontsize*0.86; }
32044 else { $size *= $maxsize*0.86; }
32045 }
32046 elseif ($size == 'medium') {
32047 if ($fontsize) { $size *= $fontsize; }
32048 else { $size *= $maxsize; }
32049 }
32050 elseif ($size == 'large') {
32051 if ($fontsize) { $size *= $fontsize*1.2; }
32052 else { $size *= $maxsize*1.2; }
32053 }
32054 elseif ($size == 'x-large') {
32055 if ($fontsize) { $size *= $fontsize*1.5; }
32056 else { $size *= $maxsize*1.5; }
32057 }
32058 elseif ($size == 'xx-large') {
32059 if ($fontsize) { $size *= $fontsize*2; }
32060 else { $size *= $maxsize*2; }
32061 }
32062 else $size *= (25.4/$this->dpi); //nothing == px
32063
32064 return $size;
32065 }
32066
32067
32068 function lesser_entity_decode($html) {
32069 //supports the most used entity codes (only does ascii safe characters)
32070 //$html = str_replace("&nbsp;"," ",$html); // mPDF 5.3.59
32071 $html = str_replace("&lt;","<",$html);
32072 $html = str_replace("&gt;",">",$html);
32073
32074 $html = str_replace("&apos;","'",$html);
32075 $html = str_replace("&quot;",'"',$html);
32076 $html = str_replace("&amp;","&",$html);
32077 return $html;
32078 }
32079
32080 function AdjustHTML($html, $tabSpaces=8) {
32081 //Try to make the html text more manageable (turning it into XHTML)
32082 if (PHP_VERSION_ID < 50307) {
32083 if (strlen($html) > 100000) {
32084 if (PHP_VERSION_ID < 50200) $this->Error("The HTML code is more than 100,000 characters. You should use WriteHTML() with smaller string lengths.");
32085 else ini_set("pcre.backtrack_limit","1000000");
32086 }
32087 }
32088
32089 /*-- ANNOTATIONS --*/
32090 preg_match_all("/(<annotation.*?>)/si", $html, $m);
32091 if (count($m[1])) {
32092 for($i=0;$i<count($m[1]);$i++) {
32093 $sub = preg_replace("/\n/si", "\xbb\xa4\xac", $m[1][$i]);
32094 $html = preg_replace('/'.preg_quote($m[1][$i], '/').'/si', $sub, $html);
32095 }
32096 }
32097 /*-- END ANNOTATIONS --*/
32098
32099 preg_match_all("/(<svg.*?<\/svg>)/si", $html, $svgi);
32100 if (count($svgi[0])) {
32101 for($i=0;$i<count($svgi[0]);$i++) {
32102 $file = _MPDF_TEMP_PATH.'_tempSVG'.RAND(1,10000).'_'.$i.'.svg';
32103 //Save to local file
32104 file_put_contents($file, $svgi[0][$i]);
32105 $html = str_replace($svgi[0][$i], '<img src="'.$file.'" />', $html); // mPDF 5.5.18
32106 }
32107 }
32108
32109 //Remove javascript code from HTML (should not appear in the PDF file)
32110 $html = preg_replace('/<script.*?<\/script>/is','',$html);
32111
32112 //Remove special comments
32113 $html = preg_replace('/<!--mpdf/i','',$html);
32114 $html = preg_replace('/mpdf-->/i','',$html);
32115
32116 //Remove comments from HTML (should not appear in the PDF file)
32117 $html = preg_replace('/<!--.*?-->/s','',$html);
32118
32119 $html = preg_replace('/\f/','',$html); //replace formfeed by nothing
32120 $html = preg_replace('/\r/','',$html); //replace carriage return by nothing
32121
32122 // Well formed XHTML end tags
32123 $html = preg_replace('/<(br|hr)\/>/i',"<\\1 />",$html);
32124 // Get rid of empty <thead></thead>
32125 $html = preg_replace('/<thead>\s*<\/thead>/i','',$html);
32126 $html = preg_replace('/<tfoot>\s*<\/tfoot>/i','',$html);
32127 $html = preg_replace('/<table[^>]*>\s*<\/table>/i','',$html);
32128 $html = preg_replace('/<tr>\s*<\/tr>/i','',$html);
32129
32130 // Remove spaces at end of table cells
32131 $html = preg_replace("/[ \n\r]+<\/t(d|h)/",'</t\\1',$html); // mPDF 5.5.09
32132
32133 $html = preg_replace("/[ ]*<dottab\s*[\/]*>[ ]*/",'<dottab />',$html);
32134
32135 // Concatenates any Substitute characters from symbols/dingbats
32136 $html = str_replace('</tts><tts>','|',$html);
32137 $html = str_replace('</ttz><ttz>','|',$html);
32138 $html = str_replace('</tta><tta>','|',$html);
32139
32140 $html = preg_replace('/<br \/>\s*/is',"<br />",$html);
32141
32142 $html = preg_replace('/<wbr[ \/]*>\s*/is',"&#173;",$html); // mPDF 5.6.04
32143
32144 // Preserve '\n's in content between the tags <pre> and </pre>
32145 if (preg_match('/<pre/',$html)) {
32146 $html_a = preg_split('/(\<\/?pre[^\>]*\>)/', $html, -1, 2);
32147 $h = array();
32148 $c=0;
32149 foreach($html_a AS $s) {
32150 if ($c>1 && preg_match('/^<\/pre/i',$s)) { $c--; $s=preg_replace('/<\/pre/i','</innerpre',$s); }
32151 else if ($c>0 && preg_match('/^<pre/i',$s)) { $c++; $s=preg_replace('/<pre/i','<innerpre',$s); }
32152 else if (preg_match('/^<pre/i',$s)) { $c++; }
32153 else if (preg_match('/^<\/pre/i',$s)) { $c--; }
32154 array_push($h, $s);
32155 }
32156 $html = implode("", $h);
32157 }
32158 $thereispre = preg_match_all('#<pre(.*?)>(.*?)</pre>#si',$html,$temp);
32159 // Preserve '\n's in content between the tags <textarea> and </textarea>
32160 $thereistextarea = preg_match_all('#<textarea(.*?)>(.*?)</textarea>#si',$html,$temp2);
32161 $html = preg_replace('/[\n]/',' ',$html); //replace linefeed by spaces
32162 $html = preg_replace('/[\t]/',' ',$html); //replace tabs by spaces
32163
32164 // Converts < to &lt; when not a tag
32165 $html = preg_replace('/<([^!\/a-zA-Z])/i','&lt;\\1',$html);
32166 $html = preg_replace("/[ ]+/",' ',$html);
32167
32168 $html = preg_replace('/\/li>\s+<\/(u|o)l/i','/li></\\1l',$html);
32169 $html = preg_replace('/\/(u|o)l>\s+<\/li/i','/\\1l></li',$html);
32170 $html = preg_replace('/\/li>\s+<\/(u|o)l/i','/li></\\1l',$html);
32171 $html = preg_replace('/\/li>\s+<li/i','/li><li',$html);
32172 $html = preg_replace('/<(u|o)l([^>]*)>[ ]+/i','<\\1l\\2>',$html);
32173 $html = preg_replace('/[ ]+<(u|o)l/i','<\\1l',$html);
32174
32175 $iterator = 0;
32176 while($thereispre) //Recover <pre attributes>content</pre>
32177 {
32178 $temp[2][$iterator] = preg_replace_callback("/^([^\n\t]*?)\t/m", array($this, 'tabs2spaces_callback'), $temp[2][$iterator]); // mPDF 5.7+
32179 $temp[2][$iterator] = preg_replace('/\t/',str_repeat(" ",$tabSpaces),$temp[2][$iterator]);
32180
32181 $temp[2][$iterator] = preg_replace('/\n/',"<br />",$temp[2][$iterator]);
32182 $temp[2][$iterator] = str_replace('\\',"\\\\",$temp[2][$iterator]);
32183 //$html = preg_replace('#<pre(.*?)>(.*?)</pre>#si','<erp'.$temp[1][$iterator].'>'.$temp[2][$iterator].'</erp>',$html,1);
32184 $html = preg_replace('#<pre(.*?)>(.*?)</pre>#si','<erp'.$temp[1][$iterator].'>'.str_replace('$','\$',$temp[2][$iterator]).'</erp>',$html,1); // mPDF 5.7+
32185 $thereispre--;
32186 $iterator++;
32187 }
32188 $iterator = 0;
32189 while($thereistextarea) //Recover <textarea attributes>content</textarea>
32190 {
32191 $temp2[2][$iterator] = preg_replace('/\t/',str_repeat(" ",$tabSpaces),$temp2[2][$iterator]);
32192 $temp2[2][$iterator] = str_replace('\\',"\\\\",$temp2[2][$iterator]); // mPDF 5.3.88
32193 $html = preg_replace('#<textarea(.*?)>(.*?)</textarea>#si','<aeratxet'.$temp2[1][$iterator].'>'.trim($temp2[2][$iterator]) .'</aeratxet>',$html,1);
32194 $thereistextarea--;
32195 $iterator++;
32196 }
32197 //Restore original tag names
32198 $html = str_replace("<erp","<pre",$html);
32199 $html = str_replace("</erp>","</pre>",$html);
32200 $html = str_replace("<aeratxet","<textarea",$html);
32201 $html = str_replace("</aeratxet>","</textarea>",$html);
32202 $html = str_replace("</innerpre","</pre",$html);
32203 $html = str_replace("<innerpre","<pre",$html);
32204
32205 $html = preg_replace('/<textarea([^>]*)><\/textarea>/si','<textarea\\1> </textarea>',$html);
32206 $html = preg_replace('/(<table[^>]*>)\s*(<caption)(.*?<\/caption>)(.*?<\/table>)/si','\\2 position="top"\\3\\1\\4\\2 position="bottom"\\3',$html); // *TABLES*
32207 $html = preg_replace('/<(h[1-6])([^>]*)(>(?:(?!h[1-6]).)*?<\/\\1>\s*<table)/si','<\\1\\2 keep-with-table="1"\\3',$html); // *TABLES*
32208 $html = preg_replace("/\xbb\xa4\xac/", "\n", $html);
32209
32210 return $html;
32211 }
32212 // mPDF 5.7+
32213 function tabs2spaces_callback($matches) {
32214 return (stripslashes($matches[1]) . str_repeat(' ', $this->tabSpaces - (mb_strlen(stripslashes($matches[1])) % $this->tabSpaces)));
32215 }
32216 // mPDF 5.7+
32217 function date_callback($matches) {
32218 return date($matches[1]);
32219 }
32220
32221 /*-- LISTS --*/
32222 function dec2other($num, $cp) {
32223 $nstr = (string) $num;
32224 $rnum = '';
32225 for ($i=0;$i<strlen($nstr);$i++) {
32226 if ($this->_charDefined($this->CurrentFont['cw'],$cp+intval($nstr[$i]))) { // contains arabic-indic numbers
32227 $rnum .= code2utf($cp+intval($nstr[$i]));
32228 }
32229 else { $rnum .= $nstr[$i]; }
32230 }
32231 return $rnum;
32232 }
32233
32234 function dec2alpha($valor,$toupper="true"){
32235 // returns a string from A-Z to AA-ZZ to AAA-ZZZ
32236 // OBS: A = 65 ASCII TABLE VALUE
32237 if (($valor < 1) || ($valor > 18278)) return "?"; //supports 'only' up to 18278
32238 $c1 = $c2 = $c3 = '';
32239 if ($valor > 702) // 3 letters (up to 18278)
32240 {
32241 $c1 = 65 + floor(($valor-703)/676);
32242 $c2 = 65 + floor((($valor-703)%676)/26);
32243 $c3 = 65 + floor((($valor-703)%676)%26);
32244 }
32245 elseif ($valor > 26) // 2 letters (up to 702)
32246 {
32247 $c1 = (64 + (int)(($valor-1) / 26));
32248 $c2 = (64 + (int)($valor % 26));
32249 if ($c2 == 64) $c2 += 26;
32250 }
32251 else // 1 letter (up to 26)
32252 {
32253 $c1 = (64 + $valor);
32254 }
32255 $alpha = chr($c1);
32256 if ($c2 != '') $alpha .= chr($c2);
32257 if ($c3 != '') $alpha .= chr($c3);
32258 if (!$toupper) $alpha = strtolower($alpha);
32259 return $alpha;
32260 }
32261
32262
32263 function dec2roman($valor,$toupper=true){
32264 //returns a string as a roman numeral
32265 $r1=$r2=$r3=$r4='';
32266 if (($valor >= 5000) || ($valor < 1)) return "?"; //supports 'only' up to 4999
32267 $aux = (int)($valor/1000);
32268 if ($aux!==0)
32269 {
32270 $valor %= 1000;
32271 while($aux!==0)
32272 {
32273 $r1 .= "M";
32274 $aux--;
32275 }
32276 }
32277 $aux = (int)($valor/100);
32278 if ($aux!==0)
32279 {
32280 $valor %= 100;
32281 switch($aux){
32282 case 3: $r2="C";
32283 case 2: $r2.="C";
32284 case 1: $r2.="C"; break;
32285 case 9: $r2="CM"; break;
32286 case 8: $r2="C";
32287 case 7: $r2.="C";
32288 case 6: $r2.="C";
32289 case 5: $r2="D".$r2; break;
32290 case 4: $r2="CD"; break;
32291 default: break;
32292 }
32293 }
32294 $aux = (int)($valor/10);
32295 if ($aux!==0)
32296 {
32297 $valor %= 10;
32298 switch($aux){
32299 case 3: $r3="X";
32300 case 2: $r3.="X";
32301 case 1: $r3.="X"; break;
32302 case 9: $r3="XC"; break;
32303 case 8: $r3="X";
32304 case 7: $r3.="X";
32305 case 6: $r3.="X";
32306 case 5: $r3="L".$r3; break;
32307 case 4: $r3="XL"; break;
32308 default: break;
32309 }
32310 }
32311 switch($valor){
32312 case 3: $r4="I";
32313 case 2: $r4.="I";
32314 case 1: $r4.="I"; break;
32315 case 9: $r4="IX"; break;
32316 case 8: $r4="I";
32317 case 7: $r4.="I";
32318 case 6: $r4.="I";
32319 case 5: $r4="V".$r4; break;
32320 case 4: $r4="IV"; break;
32321 default: break;
32322 }
32323 $roman = $r1.$r2.$r3.$r4;
32324 if (!$toupper) $roman = strtolower($roman);
32325 return $roman;
32326 }
32327 /*-- END LISTS --*/
32328
32329
32330 //===========================
32331 /*-- IMPORTS --*/
32332 function SetImportUse() {
32333 $this->enableImports = true;
32334 ini_set('auto_detect_line_endings',1);
32335 require_once(_MPDF_PATH."mpdfi/pdf_context.php");
32336 require_once(_MPDF_PATH."mpdfi/pdf_parser.php");
32337 require_once(_MPDF_PATH."mpdfi/fpdi_pdf_parser.php");
32338 }
32339
32340 // from mPDFI
32341 function hex2str($hex) {
32342 return pack("H*", str_replace(array("\r","\n"," "),"", $hex));
32343 }
32344
32345 function str2hex($str) {
32346 return current(unpack("H*",$str));
32347 }
32348
32349
32350 function pdf_write_value(&$value) {
32351 switch ($value[0]) {
32352 case PDF_TYPE_NUMERIC :
32353 case PDF_TYPE_TOKEN :
32354 // A numeric value or a token.
32355 // Simply output them
32356 $this->_out($value[1]." ", false);
32357 break;
32358
32359 case PDF_TYPE_ARRAY :
32360 // An array. Output the proper
32361 // structure and move on.
32362 $this->_out("[",false);
32363 for ($i = 0; $i < count($value[1]); $i++) {
32364 $this->pdf_write_value($value[1][$i]);
32365 }
32366 $this->_out("]");
32367 break;
32368
32369 case PDF_TYPE_DICTIONARY :
32370 // A dictionary.
32371 $this->_out("<<",false);
32372 reset ($value[1]);
32373 while (list($k, $v) = each($value[1])) {
32374 $this->_out($k . " ",false);
32375 $this->pdf_write_value($v);
32376 }
32377 $this->_out(">>");
32378 break;
32379
32380 case PDF_TYPE_OBJREF :
32381 // An indirect object reference
32382 // Fill the object stack if needed
32383 $cpfn =& $this->current_parser->filename;
32384 if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) {
32385 $this->_newobj(false,true);
32386 $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value);
32387 $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value);
32388 }
32389 $objid = $this->_don_obj_stack[$cpfn][$value[1]][0];
32390 $this->_out("{$objid} 0 R"); //{$value[2]}
32391 break;
32392
32393 case PDF_TYPE_STRING :
32394 if ($this->encrypted) {
32395 $value[1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[1]);
32396 $value[1] = $this->_escape($value[1]);
32397 }
32398 // A string.
32399 $this->_out('('.$value[1].')');
32400 break;
32401
32402 case PDF_TYPE_STREAM :
32403 // A stream. First, output the
32404 // stream dictionary, then the
32405 // stream data itself.
32406 $this->pdf_write_value($value[1]);
32407 if ($this->encrypted) {
32408 $value[2][1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[2][1]);
32409 }
32410 $this->_out("stream");
32411 $this->_out($value[2][1]);
32412 $this->_out("endstream");
32413 break;
32414
32415 case PDF_TYPE_HEX :
32416 if ($this->encrypted) {
32417 $value[1] = $this->hex2str($value[1]);
32418 $value[1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[1]);
32419 // remake hexstring of encrypted string
32420 $value[1] = $this->str2hex($value[1]);
32421 }
32422 $this->_out("<".$value[1].">");
32423 break;
32424
32425 case PDF_TYPE_NULL :
32426 // The null object.
32427 $this->_out("null");
32428 break;
32429 }
32430 }
32431
32432 // ========== OVERWRITE SEARCH STRING IN A PDF FILE ================
32433 function OverWrite($file_in, $search, $replacement, $dest="D", $file_out="mpdf" ) {
32434 $pdf = file_get_contents($file_in);
32435
32436 if (!is_array($search)) {
32437 $x = $search;
32438 $search = array($x);
32439 }
32440 if (!is_array($replacement)) {
32441 $x = $replacement;
32442 $search = array($x);
32443 }
32444
32445 if (!$this->onlyCoreFonts && !$this->usingCoreFont) {
32446 foreach($search AS $k=>$val) {
32447 $search[$k] = $this->UTF8ToUTF16BE($search[$k] , false);
32448 $search[$k] = $this->_escape($search[$k]);
32449 $replacement[$k] = $this->UTF8ToUTF16BE($replacement[$k], false);
32450 $replacement[$k] = $this->_escape($replacement[$k]);
32451 }
32452 }
32453 else {
32454 foreach($replacement AS $k=>$val) {
32455 $replacement[$k] = mb_convert_encoding($replacement[$k],$this->mb_enc,'utf-8');
32456 $replacement[$k] = $this->_escape($replacement[$k]);
32457 }
32458 }
32459
32460 // Get xref into array
32461 $xref = array();
32462 preg_match("/xref\n0 (\d+)\n(.*?)\ntrailer/s",$pdf,$m);
32463 $xref_objid = $m[1];
32464 preg_match_all('/(\d{10}) (\d{5}) (f|n)/',$m[2],$x);
32465 for($i=0; $i<count($x[0]); $i++) {
32466 $xref[] = array(intval($x[1][$i]), $x[2][$i], $x[3][$i]);
32467 }
32468
32469 $changes = array();
32470 preg_match("/<<\s*\/Type\s*\/Pages\s*\/Kids\s*\[(.*?)\]\s*\/Count/s",$pdf,$m);
32471 preg_match_all("/(\d+) 0 R /s",$m[1],$o);
32472 $objlist = $o[1];
32473 foreach($objlist AS $obj) {
32474 if ($this->compress) {
32475 preg_match("/".($obj+1)." 0 obj\n<<\s*\/Filter\s*\/FlateDecode\s*\/Length (\d+)>>\nstream\n(.*?)\nendstream\n/s",$pdf,$m);
32476 }
32477 else {
32478 preg_match("/".($obj+1)." 0 obj\n<<\s*\/Length (\d+)>>\nstream\n(.*?)\nendstream\n/s",$pdf,$m);
32479 }
32480 $s = $m[2];
32481 if (!$s) { continue; }
32482 $oldlen = $m[1];
32483 if ($this->encrypted) {
32484 $s = $this->_RC4($this->_objectkey($obj+1), $s);
32485 }
32486 if ($this->compress) {
32487 $s = gzuncompress($s);
32488 }
32489 foreach($search AS $k=>$val) {
32490 $s = str_replace($search[$k],$replacement[$k],$s);
32491 }
32492 if ($this->compress) {
32493 $s = gzcompress($s);
32494 }
32495 if ($this->encrypted) {
32496 $s = $this->_RC4($this->_objectkey($obj+1), $s);
32497 }
32498 $newlen = strlen($s);
32499 $changes[($xref[$obj+1][0])] = ($newlen - $oldlen) + (strlen($newlen) - strlen($oldlen ));
32500 if ($this->compress) {
32501 $newstr = ($obj+1) . " 0 obj\n<</Filter /FlateDecode /Length ".$newlen.">>\nstream\n".$s."\nendstream\n";
32502 }
32503 else {
32504 $newstr = ($obj+1) . " 0 obj\n<</Length ".$newlen.">>\nstream\n".$s."\nendstream\n";
32505 }
32506 $pdf = str_replace($m[0],$newstr,$pdf);
32507 }
32508
32509 // Update xref in PDF
32510 krsort($changes);
32511 $newxref = "xref\n0 ".$xref_objid."\n";
32512 foreach($xref AS $v) {
32513 foreach($changes AS $ck => $cv) {
32514 if ($v[0] > $ck) { $v[0] += $cv; }
32515 }
32516 $newxref .= sprintf('%010d',$v[0]) . ' ' . $v[1] . ' ' .$v[2] . " \n";
32517 }
32518 $newxref .= "trailer";
32519 $pdf = preg_replace("/xref\n0 \d+\n.*?\ntrailer/s",$newxref,$pdf);
32520
32521 // Update startxref in PDF
32522 preg_match("/startxref\n(\d+)\n%%EOF/s", $pdf, $m);
32523 $startxref = $m[1];
32524 $startxref += array_sum($changes);
32525 $pdf = preg_replace("/startxref\n(\d+)\n%%EOF/s","startxref\n".$startxref."\n%%EOF",$pdf);
32526
32527 // OUTPUT
32528 switch($dest) {
32529 case 'I':
32530 //Send to standard output
32531 if(isset($_SERVER['SERVER_NAME']))
32532 {
32533 //We send to a browser
32534 Header('Content-Type: application/pdf');
32535 Header('Content-Length: '.strlen($pdf));
32536 Header('Content-disposition: inline; filename='.$file_out);
32537 }
32538 echo $pdf;
32539 break;
32540 case 'F':
32541 //Save to local file
32542 if (!$file_out) { $file_out = 'mpdf.pdf'; }
32543 $f=fopen($file_out,'wb');
32544 if(!$f) die('Unable to create output file: '.$file_out);
32545 fwrite($f,$pdf,strlen($pdf));
32546 fclose($f);
32547 break;
32548 case 'S':
32549 //Return as a string
32550 return $pdf;
32551 case 'D':
32552 default:
32553 //Download file
32554 if(isset($_SERVER['HTTP_USER_AGENT']) and strpos($_SERVER['HTTP_USER_AGENT'],'MSIE'))
32555 Header('Content-Type: application/force-download');
32556 else
32557 Header('Content-Type: application/octet-stream');
32558 Header('Content-Length: '.strlen($pdf));
32559 Header('Content-disposition: attachment; filename='.$file_out);
32560 echo $pdf;
32561 break;
32562 }
32563 }
32564
32565
32566 function GetTemplateSize($tplidx, $_w=0, $_h=0) {
32567 if (!$this->tpls[$tplidx])
32568 return false;
32569 $w = $this->tpls[$tplidx]['box']['w'];
32570 $h = $this->tpls[$tplidx]['box']['h'];
32571 if ($_w == 0 and $_h == 0) {
32572 $_w = $w;
32573 $_h = $h;
32574 }
32575 if($_w==0)
32576 $_w=$_h*$w/$h;
32577 if($_h==0)
32578 $_h=$_w*$h/$w;
32579 return array("w" => $_w, "h" => $_h);
32580 }
32581
32582 // Thumbnails
32583 function Thumbnail($file, $npr=3, $spacing=10) { //$npr = number per row
32584 $w = (($this->pgwidth + $spacing)/$npr) - $spacing;
32585 $oldlinewidth = $this->LineWidth;
32586 $this->SetLineWidth(0.02);
32587 $this->SetDColor($this->ConvertColor(0));
32588 $h = 0;
32589 $maxh = 0;
32590 $x = $_x = $this->lMargin;
32591 $_y = $this->tMargin;
32592 if ($this->y==0) { $y = $_y; } else { $y = $this->y; }
32593 $pagecount = $this->SetSourceFile($file);
32594 for ($n = 1; $n <= $pagecount; $n++) {
32595 $tplidx = $this->ImportPage($n);
32596 $size = $this->useTemplate($tplidx, $x, $y, $w);
32597 $this->Rect($x, $y, $size['w'], $size['h']);
32598 $h = max($h, $size['h']);
32599 $maxh = max($h, $maxh);
32600 if ($n % $npr == 0) {
32601 if (($y + $h + $spacing + $maxh)>$this->PageBreakTrigger && $n != $pagecount) {
32602 $this->AddPage();
32603 $x = $_x;
32604 $y = $_y;
32605 }
32606 else {
32607 $y += $h+$spacing ;
32608 $x = $_x;
32609 $h = 0;
32610 }
32611 }
32612 else {
32613 $x += $w+$spacing ;
32614 }
32615 }
32616 $this->SetLineWidth($oldlinewidth);
32617 }
32618
32619 function SetSourceFile($filename) {
32620 $this->current_filename = $filename;
32621 $fn =& $this->current_filename;
32622 if (!isset($this->parsers[$fn]))
32623 // $this->parsers[$fn] =& new fpdi_pdf_parser($fn,$this);
32624 $this->parsers[$fn] = new fpdi_pdf_parser($fn,$this);
32625 if (!$this->parsers[$fn]->success) {
32626 $this->Error($this->parsers[$fn]->errormsg); // Delete this line to return false on fail
32627 return false;
32628 }
32629 $this->current_parser =& $this->parsers[$fn];
32630 return $this->parsers[$fn]->getPageCount();
32631 }
32632 function ImportPage($pageno=1, $crop_x=null, $crop_y=null, $crop_w=0, $crop_h=0, $boxName='/CropBox') {
32633 $fn =& $this->current_filename;
32634 $parser =& $this->parsers[$fn];
32635 $parser->setPageno($pageno);
32636
32637 $this->tpl++;
32638 $this->tpls[$this->tpl] = array();
32639 $tpl =& $this->tpls[$this->tpl];
32640 $tpl['parser'] =& $parser;
32641 $tpl['resources'] = $parser->getPageResources();
32642 $tpl['buffer'] = $parser->getContent();
32643 if (!in_array($boxName, $parser->availableBoxes))
32644 return $this->Error(sprintf("Unknown box: %s", $boxName));
32645 $pageboxes = $parser->getPageBoxes($pageno);
32646 /**
32647 * MediaBox
32648 * CropBox: Default -> MediaBox
32649 * BleedBox: Default -> CropBox
32650 * TrimBox: Default -> CropBox
32651 * ArtBox: Default -> CropBox
32652 */
32653 if (!isset($pageboxes[$boxName]) && ($boxName == "/BleedBox" || $boxName == "/TrimBox" || $boxName == "/ArtBox"))
32654 $boxName = "/CropBox";
32655 if (!isset($pageboxes[$boxName]) && $boxName == "/CropBox")
32656 $boxName = "/MediaBox";
32657 if (!isset($pageboxes[$boxName]))
32658 return false;
32659 $box = $pageboxes[$boxName];
32660
32661 $tpl['box'] = $box;
32662 // To build an array that can be used by useTemplate()
32663 $this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl],$box);
32664 // An imported page will start at 0,0 everytime. Translation will be set in _putformxobjects()
32665 $tpl['x'] = 0;
32666 $tpl['y'] = 0;
32667 $tpl['w'] = $tpl['box']['w'] ;
32668 $tpl['h'] = $tpl['box']['h'] ;
32669 if ($crop_w) { $tpl['box']['w'] = $crop_w; }
32670 if ($crop_h) { $tpl['box']['h'] = $crop_h; }
32671 if (isset($crop_x)) { $tpl['box']['x'] = $crop_x; }
32672 if (isset($crop_y)) {$tpl['box']['y'] = $tpl['h'] - $crop_y - $crop_h ; }
32673
32674 $page =& $parser->pages[$parser->pageno];
32675 // fix for rotated pages
32676 $rotation = $parser->getPageRotation($pageno);
32677
32678 if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0 && $tpl['box']['w'] == $tpl['w']) {
32679 $steps = $angle / 90;
32680
32681 $_w = $tpl['w'];
32682 $_h = $tpl['h'];
32683 $tpl['w'] = $steps % 2 == 0 ? $_w : $_h;
32684 $tpl['h'] = $steps % 2 == 0 ? $_h : $_w;
32685 if ($steps % 2 != 0) {
32686 $x = $y = ($steps == 1 || $steps == -3) ? $tpl['h'] : $tpl['w'];
32687 } else {
32688 $x = $tpl['w'];
32689 $y = $tpl['h'];
32690 }
32691 $cx=($x/2+$tpl['box']['x'])*_MPDFK;
32692 $cy=($y/2+$tpl['box']['y'])*_MPDFK;
32693 $angle*=-1;
32694 $angle*=M_PI/180;
32695 $c=cos($angle);
32696 $s=sin($angle);
32697 $tpl['box']['w'] = $tpl['w'] ;
32698 $tpl['box']['h'] = $tpl['h'] ;
32699 $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']);
32700 }
32701 return $this->tpl;
32702 }
32703 function UseTemplate($tplidx, $_x=null, $_y=null, $_w=0, $_h=0) {
32704 if (!isset($this->tpls[$tplidx]))
32705 $this->Error("Template does not exist!");
32706 if($this->state==0) { $this->AddPage(); }
32707 $out = 'q 0 J 1 w 0 j 0 G'."\n"; // reset standard values
32708 $x = $this->tpls[$tplidx]['x'];
32709 $y = $this->tpls[$tplidx]['y'];
32710 $w = $this->tpls[$tplidx]['w'];
32711 $h = $this->tpls[$tplidx]['h'];
32712 if ($_x == null) { $_x = $x; }
32713 if ($_y == null) { $_y = $y; }
32714 if ($_x === -1) { $_x = $this->x; }
32715 if ($_y === -1) { $_y = $this->y; }
32716
32717 $wh = $this->getTemplateSize($tplidx,$_w,$_h);
32718 $_w = $wh['w'];
32719 $_h = $wh['h'];
32720 $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";
32721 $out .= $this->tplprefix.$tplidx." Do Q\n";
32722
32723 $s = array("w" => $_w, "h" => $_h);
32724 $out .= "Q\n";
32725 $this->pages[$this->page] = $out . $this->pages[$this->page];
32726 return $s;
32727 }
32728 function SetPageTemplate($tplidx='') {
32729 if (!isset($this->tpls[$tplidx])) {
32730 $this->pageTemplate = '';
32731 return false;
32732 }
32733 $this->pageTemplate = $tplidx;
32734 }
32735 function SetDocTemplate($file='', $continue=0) {
32736 $this->docTemplate = $file;
32737 $this->docTemplateContinue = $continue;
32738 }
32739 /*-- END IMPORTS --*/
32740
32741
32742 /* ---------------------------------------------- */
32743 /* ---------------------------------------------- */
32744 /* ---------------------------------------------- */
32745 /* ---------------------------------------------- */
32746 /* ---------------------------------------------- */
32747
32748 // JAVASCRIPT
32749 function _set_object_javascript ($string) {
32750 $this->_newobj();
32751 $this->_out('<<');
32752 $this->_out('/S /JavaScript ');
32753 $this->_out('/JS '.$this->_textstring($string));
32754 $this->_out('>>');
32755 $this->_out('endobj');
32756 }
32757
32758 function SetJS($script) {
32759 $this->js = $script;
32760 }
32761
32762
32763
32764
32765 }//end of Class
32766
32767
32768
32769
32770 ?>