1<?php
2
3namespace Mpdf\Tag;
4
5use Mpdf\Conversion\DecToAlpha;
6use Mpdf\Conversion\DecToRoman;
7use Mpdf\Utils\Arrays;
8use Mpdf\Utils\UtfString;
9
10abstract class BlockTag extends Tag
11{
12
13	public function open($attr, &$ahtml, &$ihtml)
14	{
15		$tag = $this->getTagName();
16
17		// mPDF 6  Lists
18		$this->mpdf->lastoptionaltag = '';
19
20		// mPDF 6 bidi
21		// Block
22		// If unicode-bidi set on current clock, any embedding levels, isolates, or overrides are closed (not inherited)
23		if (isset($this->mpdf->blk[$this->mpdf->blklvl]['bidicode'])) {
24			$blockpost = $this->mpdf->_setBidiCodes('end', $this->mpdf->blk[$this->mpdf->blklvl]['bidicode']);
25			if ($blockpost) {
26				$this->mpdf->OTLdata = [];
27				if ($this->mpdf->tableLevel) {
28					$this->mpdf->_saveCellTextBuffer($blockpost);
29				} else {
30					$this->mpdf->_saveTextBuffer($blockpost);
31				}
32			}
33		}
34
35
36		$p = $this->cssManager->PreviewBlockCSS($tag, $attr);
37		if (isset($p['DISPLAY']) && strtolower($p['DISPLAY']) === 'none') {
38			$this->mpdf->blklvl++;
39			$this->mpdf->blk[$this->mpdf->blklvl]['hide'] = true;
40			$this->mpdf->blk[$this->mpdf->blklvl]['tag'] = $tag;  // mPDF 6
41			return;
42		}
43		if ($tag === 'CAPTION') {
44			// position is written in AdjstHTML
45			$divpos = 'T';
46			if (isset($attr['POSITION']) && strtolower($attr['POSITION']) === 'bottom') {
47				$divpos = 'B';
48			}
49
50			$cappos = 'T';
51			if (isset($attr['ALIGN']) && strtolower($attr['ALIGN']) === 'bottom') {
52				$cappos = 'B';
53			} elseif (isset($p['CAPTION-SIDE']) && strtolower($p['CAPTION-SIDE']) === 'bottom') {
54				$cappos = 'B';
55			}
56			if (isset($attr['ALIGN'])) {
57				unset($attr['ALIGN']);
58			}
59			if ($cappos != $divpos) {
60				$this->mpdf->blklvl++;
61				$this->mpdf->blk[$this->mpdf->blklvl]['hide'] = true;
62				$this->mpdf->blk[$this->mpdf->blklvl]['tag'] = $tag;  // mPDF 6
63				return;
64			}
65		}
66
67		/* -- FORMS -- */
68		if ($tag === 'FORM') {
69			$this->form->formMethod = 'POST';
70			if (isset($attr['METHOD']) && strtolower($attr['METHOD']) === 'get') {
71				$this->form->formMethod = 'GET';
72			}
73
74			$this->form->formAction = '';
75			if (isset($attr['ACTION'])) {
76				$this->form->formAction = $attr['ACTION'];
77			}
78		}
79		/* -- END FORMS -- */
80
81
82		/* -- CSS-POSITION -- */
83		if ((isset($p['POSITION'])
84				&& (strtolower($p['POSITION']) === 'fixed'
85					|| strtolower($p['POSITION']) === 'absolute'))
86			&& $this->mpdf->blklvl == 0) {
87			if ($this->mpdf->inFixedPosBlock) {
88				throw new \Mpdf\MpdfException('Cannot nest block with position:fixed or position:absolute');
89			}
90			$this->mpdf->inFixedPosBlock = true;
91			return;
92		}
93		/* -- END CSS-POSITION -- */
94		// Start Block
95		$this->mpdf->ignorefollowingspaces = true;
96
97		$lastbottommargin = 0;
98		if ($this->mpdf->blockjustfinished && !count($this->mpdf->textbuffer)
99			&& $this->mpdf->y != $this->mpdf->tMargin
100			&& $this->mpdf->collapseBlockMargins) {
101			$lastbottommargin = $this->mpdf->lastblockbottommargin;
102		}
103		$this->mpdf->lastblockbottommargin = 0;
104		$this->mpdf->blockjustfinished = false;
105
106
107		$this->mpdf->InlineBDF = []; // mPDF 6
108		$this->mpdf->InlineBDFctr = 0; // mPDF 6
109		$this->mpdf->InlineProperties = [];
110		$this->mpdf->divbegin = true;
111
112		$this->mpdf->linebreakjustfinished = false;
113
114		/* -- TABLES -- */
115		if ($this->mpdf->tableLevel) {
116			// If already something on the line
117			if ($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] > 0 && !$this->mpdf->nestedtablejustfinished) {
118				$this->mpdf->_saveCellTextBuffer("\n");
119				if (!isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'])) {
120					$this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'];
121				} elseif ($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] < $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']) {
122					$this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'];
123				}
124				$this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] = 0; // reset
125			}
126			// Cannot set block properties inside table - use Bold to indicate h1-h6
127			if ($tag === 'CENTER' && $this->mpdf->tdbegin) {
128				$this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['a'] = $this->getAlign('center');
129			}
130
131			$this->mpdf->InlineProperties['BLOCKINTABLE'] = $this->mpdf->saveInlineProperties();
132			$properties = $this->cssManager->MergeCSS('', $tag, $attr);
133			if (!empty($properties)) {
134				$this->mpdf->setCSS($properties, 'INLINE');
135			}
136
137			// mPDF 6  Lists
138			if ($tag === 'UL' || $tag === 'OL') {
139				$this->mpdf->listlvl++;
140				if (isset($attr['START'])) {
141					$this->mpdf->listcounter[$this->mpdf->listlvl] = (int) $attr['START'] - 1;
142				} else {
143					$this->mpdf->listcounter[$this->mpdf->listlvl] = 0;
144				}
145				$this->mpdf->listitem = [];
146				if ($tag === 'OL') {
147					$this->mpdf->listtype[$this->mpdf->listlvl] = 'decimal';
148				} elseif ($tag === 'UL') {
149					if ($this->mpdf->listlvl % 3 == 1) {
150						$this->mpdf->listtype[$this->mpdf->listlvl] = 'disc';
151					} elseif ($this->mpdf->listlvl % 3 == 2) {
152						$this->mpdf->listtype[$this->mpdf->listlvl] = 'circle';
153					} else {
154						$this->mpdf->listtype[$this->mpdf->listlvl] = 'square';
155					}
156				}
157			}
158
159			// mPDF 6  Lists - in Tables
160			if ($tag === 'LI') {
161
162				if ($this->mpdf->listlvl == 0) { //in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...)
163					$this->mpdf->listlvl++; // first depth level
164					$this->mpdf->listcounter[$this->mpdf->listlvl] = 0;
165				}
166
167				$this->mpdf->listcounter[$this->mpdf->listlvl]++;
168				$this->mpdf->listitem = [];
169				//if in table - output here as a tabletextbuffer
170				//position:inside OR position:outside (always output in table as position:inside)
171
172				$decToAlpha = new DecToAlpha();
173				$decToRoman = new DecToRoman();
174
175				switch ($this->mpdf->listtype[$this->mpdf->listlvl]) {
176					case 'upper-alpha':
177					case 'upper-latin':
178					case 'A':
179						$blt = $decToAlpha->convert($this->mpdf->listcounter[$this->mpdf->listlvl]) . $this->mpdf->list_number_suffix;
180						break;
181					case 'lower-alpha':
182					case 'lower-latin':
183					case 'a':
184						$blt = $decToAlpha->convert($this->mpdf->listcounter[$this->mpdf->listlvl], false) . $this->mpdf->list_number_suffix;
185						break;
186					case 'upper-roman':
187					case 'I':
188						$blt = $decToRoman->convert($this->mpdf->listcounter[$this->mpdf->listlvl]) . $this->mpdf->list_number_suffix;
189						break;
190					case 'lower-roman':
191					case 'i':
192						$blt = $decToRoman->convert($this->mpdf->listcounter[$this->mpdf->listlvl]) . $this->mpdf->list_number_suffix;
193						break;
194					case 'decimal':
195					case '1':
196						$blt = $this->mpdf->listcounter[$this->mpdf->listlvl] . $this->mpdf->list_number_suffix;
197						break;
198					default:
199						$blt = '-';
200						if ($this->mpdf->listlvl % 3 == 1 && $this->mpdf->_charDefined($this->mpdf->CurrentFont['cw'], 8226)) {
201							$blt = "\xe2\x80\xa2";
202						} // &#8226;
203						elseif ($this->mpdf->listlvl % 3 == 2 && $this->mpdf->_charDefined($this->mpdf->CurrentFont['cw'], 9900)) {
204							$blt = "\xe2\x9a\xac";
205						} // &#9900;
206						elseif ($this->mpdf->listlvl % 3 == 0 && $this->mpdf->_charDefined($this->mpdf->CurrentFont['cw'], 9642)) {
207							$blt = "\xe2\x96\xaa";
208						} // &#9642;
209						break;
210				}
211
212				// change to &nbsp; spaces
213				if ($this->mpdf->usingCoreFont) {
214					$ls = str_repeat(chr(160) . chr(160), ($this->mpdf->listlvl - 1) * 2) . $blt . ' ';
215				} else {
216					$ls = str_repeat("\xc2\xa0\xc2\xa0", ($this->mpdf->listlvl - 1) * 2) . $blt . ' ';
217				}
218				$this->mpdf->_saveCellTextBuffer($ls);
219				$this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] += $this->mpdf->GetStringWidth($ls);
220			}
221
222			return;
223		}
224		/* -- END TABLES -- */
225
226		if ($this->mpdf->lastblocklevelchange == 1) {
227			$blockstate = 1;
228		} // Top margins/padding only
229		elseif ($this->mpdf->lastblocklevelchange < 1) {
230			$blockstate = 0;
231		} // NO margins/padding
232
233		$this->mpdf->printbuffer($this->mpdf->textbuffer, $blockstate);
234		$this->mpdf->textbuffer = [];
235
236		$save_blklvl = $this->mpdf->blklvl;
237		$save_blk = $this->mpdf->blk;
238
239		$this->mpdf->Reset();
240
241		$pagesel = '';
242		/* -- CSS-PAGE -- */
243		if (isset($p['PAGE'])) {
244			$pagesel = $p['PAGE'];
245		}  // mPDF 6 (uses $p - preview of properties so blklvl can be incremented after page-break)
246		/* -- END CSS-PAGE -- */
247
248		// If page-box has changed AND/OR PAGE-BREAK-BEFORE
249		// mPDF 6 (uses $p - preview of properties so blklvl can be imcremented after page-break)
250		if (!$this->mpdf->tableLevel && (($pagesel && (!isset($this->mpdf->page_box['current'])
251						|| $pagesel != $this->mpdf->page_box['current']))
252				|| (isset($p['PAGE-BREAK-BEFORE'])
253					&& $p['PAGE-BREAK-BEFORE']))) {
254			// mPDF 6 pagebreaktype
255			$startpage = $this->mpdf->page;
256			$pagebreaktype = $this->mpdf->defaultPagebreakType;
257			$this->mpdf->lastblocklevelchange = -1;
258			if ($this->mpdf->ColActive) {
259				$pagebreaktype = 'cloneall';
260			}
261			if ($pagesel && (!isset($this->mpdf->page_box['current']) || $pagesel != $this->mpdf->page_box['current'])) {
262				$pagebreaktype = 'cloneall';
263			}
264			$this->mpdf->_preForcedPagebreak($pagebreaktype);
265
266			if (isset($p['PAGE-BREAK-BEFORE'])) {
267				if (strtoupper($p['PAGE-BREAK-BEFORE']) === 'RIGHT') {
268					$this->mpdf->AddPage(
269						$this->mpdf->CurOrientation,
270						'NEXT-ODD',
271						'',
272						'',
273						'',
274						'',
275						'',
276						'',
277						'',
278						'',
279						'',
280						'',
281						'',
282						'',
283						'',
284						0,
285						0,
286						0,
287						0,
288						$pagesel
289					);
290				} elseif (strtoupper($p['PAGE-BREAK-BEFORE']) === 'LEFT') {
291					$this->mpdf->AddPage(
292						$this->mpdf->CurOrientation,
293						'NEXT-EVEN',
294						'',
295						'',
296						'',
297						'',
298						'',
299						'',
300						'',
301						'',
302						'',
303						'',
304						'',
305						'',
306						'',
307						0,
308						0,
309						0,
310						0,
311						$pagesel
312					);
313				} elseif (strtoupper($p['PAGE-BREAK-BEFORE']) === 'ALWAYS') {
314					$this->mpdf->AddPage($this->mpdf->CurOrientation, '', '', '', '', '', '', '', '', '', '', '', '', '', '', 0, 0, 0, 0, $pagesel);
315				} elseif ($this->mpdf->page_box['current'] != $pagesel) {
316					$this->mpdf->AddPage($this->mpdf->CurOrientation, '', '', '', '', '', '', '', '', '', '', '', '', '', '', 0, 0, 0, 0, $pagesel);
317				} // *CSS-PAGE*
318			} /* -- CSS-PAGE -- */
319			// Must Add new page if changed page properties
320			elseif (!isset($this->mpdf->page_box['current']) || $pagesel != $this->mpdf->page_box['current']) {
321				$this->mpdf->AddPage($this->mpdf->CurOrientation, '', '', '', '', '', '', '', '', '', '', '', '', '', '', 0, 0, 0, 0, $pagesel);
322			}
323			/* -- END CSS-PAGE -- */
324
325			// mPDF 6 pagebreaktype
326			$this->mpdf->_postForcedPagebreak($pagebreaktype, $startpage, $save_blk, $save_blklvl);
327		}
328
329		// mPDF 6 pagebreaktype - moved after pagebreak
330		$this->mpdf->blklvl++;
331		$currblk = & $this->mpdf->blk[$this->mpdf->blklvl];
332		$this->mpdf->initialiseBlock($currblk);
333		$prevblk = & $this->mpdf->blk[$this->mpdf->blklvl - 1];
334		$currblk['tag'] = $tag;
335		$currblk['attr'] = $attr;
336
337		$properties = $this->cssManager->MergeCSS('BLOCK', $tag, $attr); // mPDF 6 - moved to after page-break-before
338		// mPDF 6 page-break-inside:avoid
339		if (isset($properties['PAGE-BREAK-INSIDE']) && strtoupper($properties['PAGE-BREAK-INSIDE']) === 'AVOID'
340			&& !$this->mpdf->ColActive && !$this->mpdf->keep_block_together && !isset($attr['PAGEBREAKAVOIDCHECKED'])) {
341			// avoid re-iterating using PAGEBREAKAVOIDCHECKED; set in CloseTag
342			$currblk['keep_block_together'] = 1;
343			$currblk['array_i'] = $ihtml; // mPDF 6
344			$this->mpdf->kt_y00 = $this->mpdf->y;
345			$this->mpdf->kt_p00 = $this->mpdf->page;
346			$this->mpdf->keep_block_together = 1;
347		}
348		if ($lastbottommargin && !empty($properties['MARGIN-TOP']) && empty($properties['FLOAT'])) {
349			$currblk['lastbottommargin'] = $lastbottommargin;
350		}
351
352		if (isset($properties['Z-INDEX']) && $this->mpdf->current_layer == 0) {
353			$v = (int) $properties['Z-INDEX'];
354			if ($v > 0) {
355				$currblk['z-index'] = $v;
356				$this->mpdf->BeginLayer($v);
357			}
358		}
359
360
361		// mPDF 6  Lists
362		// List-type set by attribute
363		if ($tag === 'OL' || $tag === 'UL' || $tag === 'LI') {
364			if (!empty($attr['TYPE'])) {
365				$listtype = $attr['TYPE'];
366				switch ($listtype) {
367					case 'A':
368						$listtype = 'upper-latin';
369						break;
370					case 'a':
371						$listtype = 'lower-latin';
372						break;
373					case 'I':
374						$listtype = 'upper-roman';
375						break;
376					case 'i':
377						$listtype = 'lower-roman';
378						break;
379					case '1':
380						$listtype = 'decimal';
381						break;
382				}
383				$currblk['list_style_type'] = $listtype;
384			}
385		}
386
387		$this->mpdf->setCSS($properties, 'BLOCK', $tag); //name(id/class/style) found in the CSS array!
388		$currblk['InlineProperties'] = $this->mpdf->saveInlineProperties();
389
390		if (isset($properties['VISIBILITY'])) {
391			$v = strtolower($properties['VISIBILITY']);
392			if (($v === 'hidden' || $v === 'printonly' || $v === 'screenonly') && $this->mpdf->visibility === 'visible' && !$this->mpdf->tableLevel) {
393				$currblk['visibility'] = $v;
394				$this->mpdf->SetVisibility($v);
395			}
396		}
397
398		// mPDF 6
399		if (!empty($attr['ALIGN'])) {
400			$currblk['block-align'] = $this->getAlign($attr['ALIGN']);
401		}
402
403
404		if (isset($properties['HEIGHT'])) {
405			$currblk['css_set_height'] = $this->sizeConverter->convert(
406				$properties['HEIGHT'],
407				$this->mpdf->h - $this->mpdf->tMargin - $this->mpdf->bMargin,
408				$this->mpdf->FontSize,
409				false
410			);
411			if (($currblk['css_set_height'] + $this->mpdf->y) > $this->mpdf->PageBreakTrigger
412				&& $this->mpdf->y > $this->mpdf->tMargin + 5
413				&& $currblk['css_set_height'] < ($this->mpdf->h - ($this->mpdf->tMargin + $this->mpdf->bMargin))) {
414				$this->mpdf->AddPage($this->mpdf->CurOrientation);
415			}
416		} else {
417			$currblk['css_set_height'] = false;
418		}
419
420
421		// Added mPDF 3.0 Float DIV
422		if (isset($prevblk['blockContext'])) {
423			$currblk['blockContext'] = $prevblk['blockContext'];
424		} // *CSS-FLOAT*
425
426		if (isset($properties['CLEAR'])) {
427			$this->mpdf->ClearFloats(strtoupper($properties['CLEAR']), $this->mpdf->blklvl - 1);
428		} // *CSS-FLOAT*
429
430		$currblk['padding_left'] = is_numeric($currblk['padding_left']) ? $currblk['padding_left'] : 0;
431		$currblk['padding_right'] = is_numeric($currblk['padding_right']) ? $currblk['padding_right'] : 0;
432
433		$container_w = $prevblk['inner_width'];
434		$bdr = $currblk['border_right']['w'];
435		$bdl = $currblk['border_left']['w'];
436		$pdr = $currblk['padding_right'];
437		$pdl = $currblk['padding_left'];
438
439		$setwidth = 0;
440		if (isset($currblk['css_set_width'])) {
441			$setwidth = $currblk['css_set_width'];
442		}
443
444		/* -- CSS-FLOAT -- */
445		if (isset($properties['FLOAT']) && strtoupper($properties['FLOAT']) === 'RIGHT' && !$this->mpdf->ColActive) {
446
447			// Cancel Keep-Block-together
448			$currblk['keep_block_together'] = false;
449			$this->mpdf->kt_y00 = 0;
450			$this->mpdf->keep_block_together = 0;
451
452			$this->mpdf->blockContext++;
453			$currblk['blockContext'] = $this->mpdf->blockContext;
454
455			list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1);
456
457			// DIV is too narrow for text to fit!
458			$maxw = $container_w - $l_width - $r_width;
459			$doubleCharWidth = (2 * $this->mpdf->GetCharWidth('W', false));
460			if (($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) > $maxw
461				|| ($maxw - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) < (2 * $this->mpdf->GetCharWidth('W', false))) {
462				// Too narrow to fit - try to move down past L or R float
463				if ($l_max < $r_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width)
464					&& (($container_w - $r_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) {
465					$this->mpdf->ClearFloats('LEFT', $this->mpdf->blklvl - 1);
466				} elseif ($r_max < $l_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width)
467					&& (($container_w - $l_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) {
468					$this->mpdf->ClearFloats('RIGHT', $this->mpdf->blklvl - 1);
469				} else {
470					$this->mpdf->ClearFloats('BOTH', $this->mpdf->blklvl - 1);
471				}
472				list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1);
473			}
474
475			if ($r_exists) {
476				$currblk['margin_right'] += $r_width;
477			}
478
479			$currblk['float'] = 'R';
480			$currblk['float_start_y'] = $this->mpdf->y;
481
482			if (isset($currblk['css_set_width'])) {
483				$currblk['margin_left'] = $container_w - ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
484				$currblk['float_width'] = ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
485			} else {
486				// *** If no width set - would need to buffer and keep track of max width, then Right-align if not full width
487				// and do borders and backgrounds - For now - just set to maximum width left
488
489				if ($l_exists) {
490					$currblk['margin_left'] += $l_width;
491				}
492				$currblk['css_set_width'] = $container_w - ($currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr);
493
494				$currblk['float_width'] = ($currblk['css_set_width'] + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']);
495			}
496
497		} elseif (isset($properties['FLOAT']) && strtoupper($properties['FLOAT']) === 'LEFT' && !$this->mpdf->ColActive) {
498			// Cancel Keep-Block-together
499			$currblk['keep_block_together'] = false;
500			$this->mpdf->kt_y00 = 0;
501			$this->mpdf->keep_block_together = 0;
502
503			$this->mpdf->blockContext++;
504			$currblk['blockContext'] = $this->mpdf->blockContext;
505
506			list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1);
507
508			// DIV is too narrow for text to fit!
509			$maxw = $container_w - $l_width - $r_width;
510			$doubleCharWidth = (2 * $this->mpdf->GetCharWidth('W', false));
511			if (($setwidth + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr) > $maxw
512				|| ($maxw - ($currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) < (2 * $this->mpdf->GetCharWidth('W', false))) {
513				// Too narrow to fit - try to move down past L or R float
514				if ($l_max < $r_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width)
515					&& (($container_w - $r_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) {
516					$this->mpdf->ClearFloats('LEFT', $this->mpdf->blklvl - 1);
517				} elseif ($r_max < $l_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width)
518					&& (($container_w - $l_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) {
519					$this->mpdf->ClearFloats('RIGHT', $this->mpdf->blklvl - 1);
520				} else {
521					$this->mpdf->ClearFloats('BOTH', $this->mpdf->blklvl - 1);
522				}
523				list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1);
524			}
525
526			if ($l_exists) {
527				$currblk['margin_left'] += $l_width;
528			}
529
530			$currblk['float'] = 'L';
531			$currblk['float_start_y'] = $this->mpdf->y;
532			if ($setwidth) {
533				$currblk['margin_right'] = $container_w - ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
534				$currblk['float_width'] = ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
535			} else {
536				// *** If no width set - would need to buffer and keep track of max width, then Right-align if not full width
537				// and do borders and backgrounds - For now - just set to maximum width left
538
539				if ($r_exists) {
540					$currblk['margin_right'] += $r_width;
541				}
542				$currblk['css_set_width'] = $container_w - ($currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr);
543
544				$currblk['float_width'] = ($currblk['css_set_width'] + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']);
545			}
546		} else {
547			// Don't allow overlap - if floats present - adjust padding to avoid overlap with Floats
548			list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1);
549			$maxw = $container_w - $l_width - $r_width;
550
551			$pdl = is_numeric($pdl) ? $pdl : 0;
552			$pdr = is_numeric($pdr) ? $pdr : 0;
553
554			$doubleCharWidth = (2 * $this->mpdf->GetCharWidth('W', false));
555			if (($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) > $maxw
556				|| ($maxw - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) < $doubleCharWidth) {
557				// Too narrow to fit - try to move down past L or R float
558				if ($l_max < $r_max && ($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width)
559					&& (($container_w - $r_width) - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) {
560					$this->mpdf->ClearFloats('LEFT', $this->mpdf->blklvl - 1);
561				} elseif ($r_max < $l_max && ($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width)
562					&& (($container_w - $l_width) - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) {
563					$this->mpdf->ClearFloats('RIGHT', $this->mpdf->blklvl - 1);
564				} else {
565					$this->mpdf->ClearFloats('BOTH', $this->mpdf->blklvl - 1);
566				}
567				list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1);
568			}
569			if ($r_exists) {
570				$currblk['padding_right'] = max($r_width - $currblk['margin_right'] - $bdr, $pdr);
571			}
572			if ($l_exists) {
573				$currblk['padding_left'] = max($l_width - $currblk['margin_left'] - $bdl, $pdl);
574			}
575		}
576		/* -- END CSS-FLOAT -- */
577
578
579		/* -- BORDER-RADIUS -- */
580		// Automatically increase padding if required for border-radius
581		if ($this->mpdf->autoPadding && !$this->mpdf->ColActive) {
582			$currblk['border_radius_TL_H'] = Arrays::get($currblk, 'border_radius_TL_H', 0);
583			$currblk['border_radius_TL_V'] = Arrays::get($currblk, 'border_radius_TL_V', 0);
584			$currblk['border_radius_TR_H'] = Arrays::get($currblk, 'border_radius_TR_H', 0);
585			$currblk['border_radius_TR_V'] = Arrays::get($currblk, 'border_radius_TR_V', 0);
586			$currblk['border_radius_BL_H'] = Arrays::get($currblk, 'border_radius_BL_H', 0);
587			$currblk['border_radius_BL_V'] = Arrays::get($currblk, 'border_radius_BL_V', 0);
588			$currblk['border_radius_BR_H'] = Arrays::get($currblk, 'border_radius_BR_H', 0);
589			$currblk['border_radius_BR_V'] = Arrays::get($currblk, 'border_radius_BR_V', 0);
590
591			if ($currblk['border_radius_TL_H'] > $currblk['padding_left'] && $currblk['border_radius_TL_V'] > $currblk['padding_top']) {
592				if ($currblk['border_radius_TL_H'] > $currblk['border_radius_TL_V']) {
593					$this->mpdf->_borderPadding(
594						$currblk['border_radius_TL_H'],
595						$currblk['border_radius_TL_V'],
596						$currblk['padding_left'],
597						$currblk['padding_top']
598					);
599				} else {
600					$this->mpdf->_borderPadding(
601						$currblk['border_radius_TL_V'],
602						$currblk['border_radius_TL_H'],
603						$currblk['padding_top'],
604						$currblk['padding_left']
605					);
606				}
607			}
608			if ($currblk['border_radius_TR_H'] > $currblk['padding_right'] && $currblk['border_radius_TR_V'] > $currblk['padding_top']) {
609				if ($currblk['border_radius_TR_H'] > $currblk['border_radius_TR_V']) {
610					$this->mpdf->_borderPadding(
611						$currblk['border_radius_TR_H'],
612						$currblk['border_radius_TR_V'],
613						$currblk['padding_right'],
614						$currblk['padding_top']
615					);
616				} else {
617					$this->mpdf->_borderPadding(
618						$currblk['border_radius_TR_V'],
619						$currblk['border_radius_TR_H'],
620						$currblk['padding_top'],
621						$currblk['padding_right']
622					);
623				}
624			}
625			if ($currblk['border_radius_BL_H'] > $currblk['padding_left'] && $currblk['border_radius_BL_V'] > $currblk['padding_bottom']) {
626				if ($currblk['border_radius_BL_H'] > $currblk['border_radius_BL_V']) {
627					$this->mpdf->_borderPadding(
628						$currblk['border_radius_BL_H'],
629						$currblk['border_radius_BL_V'],
630						$currblk['padding_left'],
631						$currblk['padding_bottom']
632					);
633				} else {
634					$this->mpdf->_borderPadding(
635						$currblk['border_radius_BL_V'],
636						$currblk['border_radius_BL_H'],
637						$currblk['padding_bottom'],
638						$currblk['padding_left']
639					);
640				}
641			}
642			if ($currblk['border_radius_BR_H'] > $currblk['padding_right'] && $currblk['border_radius_BR_V'] > $currblk['padding_bottom']) {
643				if ($currblk['border_radius_BR_H'] > $currblk['border_radius_BR_V']) {
644					$this->mpdf->_borderPadding(
645						$currblk['border_radius_BR_H'],
646						$currblk['border_radius_BR_V'],
647						$currblk['padding_right'],
648						$currblk['padding_bottom']
649					);
650				} else {
651					$this->mpdf->_borderPadding(
652						$currblk['border_radius_BR_V'],
653						$currblk['border_radius_BR_H'],
654						$currblk['padding_bottom'],
655						$currblk['padding_right']
656					);
657				}
658			}
659		}
660		/* -- END BORDER-RADIUS -- */
661
662		// Hanging indent - if negative indent: ensure padding is >= indent
663		if (!isset($currblk['text_indent'])) {
664			$currblk['text_indent'] = null;
665		}
666		if (!isset($currblk['inner_width'])) {
667			$currblk['inner_width'] = null;
668		}
669		$cbti = $this->sizeConverter->convert(
670			$currblk['text_indent'],
671			$this->mpdf->blk[$this->mpdf->blklvl]['inner_width'],
672			$this->mpdf->FontSize,
673			false
674		);
675		if ($cbti < 0) {
676			$hangind = -$cbti;
677			if (isset($currblk['direction']) && $currblk['direction'] === 'rtl') { // *OTL*
678				$currblk['padding_right'] = max($currblk['padding_right'], $hangind); // *OTL*
679			} // *OTL*
680			else { // *OTL*
681				$currblk['padding_left'] = max($currblk['padding_left'], $hangind);
682			} // *OTL*
683		}
684
685		if (isset($currblk['css_set_width'])) {
686			if (isset($properties['MARGIN-LEFT'], $properties['MARGIN-RIGHT'])
687				&& strtolower($properties['MARGIN-LEFT']) === 'auto' && strtolower($properties['MARGIN-RIGHT']) === 'auto') {
688				// Try to reduce margins to accomodate - if still too wide, set margin-right/left=0 (reduces width)
689				$anyextra = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w']
690						+ $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']);
691				if ($anyextra > 0) {
692					$currblk['margin_left'] = $currblk['margin_right'] = $anyextra / 2;
693				} else {
694					$currblk['margin_left'] = $currblk['margin_right'] = 0;
695				}
696			} elseif (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT']) === 'auto') {
697				// Try to reduce margin-left to accomodate - if still too wide, set margin-left=0 (reduces width)
698				$currblk['margin_left'] = $prevblk['inner_width'] - ($currblk['css_set_width']
699						+ $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w']
700						+ $currblk['padding_right'] + $currblk['margin_right']);
701				if ($currblk['margin_left'] < 0) {
702					$currblk['margin_left'] = 0;
703				}
704			} elseif (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT']) === 'auto') {
705				// Try to reduce margin-right to accomodate - if still too wide, set margin-right=0 (reduces width)
706				$currblk['margin_right'] = $prevblk['inner_width'] - ($currblk['css_set_width']
707						+ $currblk['border_left']['w'] + $currblk['padding_left']
708						+ $currblk['border_right']['w'] + $currblk['padding_right'] + $currblk['margin_left']);
709				if ($currblk['margin_right'] < 0) {
710					$currblk['margin_right'] = 0;
711				}
712			} else {
713				if ($currblk['direction'] === 'rtl') { // *OTL*
714					// Try to reduce margin-left to accomodate - if still too wide, set margin-left=0 (reduces width)
715					$currblk['margin_left'] = $prevblk['inner_width'] - ($currblk['css_set_width']
716							+ $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w']
717							+ $currblk['padding_right'] + $currblk['margin_right']); // *OTL*
718					if ($currblk['margin_left'] < 0) { // *OTL*
719						$currblk['margin_left'] = 0; // *OTL*
720					} // *OTL*
721				} // *OTL*
722				else { // *OTL*
723					// Try to reduce margin-right to accomodate - if still too wide, set margin-right=0 (reduces width)
724					$currblk['margin_right'] = $prevblk['inner_width'] - ($currblk['css_set_width']
725							+ $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w']
726							+ $currblk['padding_right'] + $currblk['margin_left']);
727					if ($currblk['margin_right'] < 0) {
728						$currblk['margin_right'] = 0;
729					}
730				} // *OTL*
731			}
732		}
733
734		$currblk['outer_left_margin'] = $prevblk['outer_left_margin'] + $currblk['margin_left']
735			+ $prevblk['border_left']['w'] + $prevblk['padding_left'];
736
737		$currblk['outer_right_margin'] = $prevblk['outer_right_margin'] + $currblk['margin_right']
738			+ $prevblk['border_right']['w'] + $prevblk['padding_right'];
739
740		$currblk['width'] = $this->mpdf->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin']);
741
742		$currblk['inner_width'] = $currblk['width']
743			- ($currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']);
744
745		// Check DIV is not now too narrow to fit text
746		$mw = 2 * $this->mpdf->GetCharWidth('W', false);
747		if ($currblk['inner_width'] < $mw) {
748			$currblk['padding_left'] = 0;
749			$currblk['padding_right'] = 0;
750			$currblk['border_left']['w'] = 0.2;
751			$currblk['border_right']['w'] = 0.2;
752			$currblk['margin_left'] = 0;
753			$currblk['margin_right'] = 0;
754			$currblk['outer_left_margin'] = $prevblk['outer_left_margin'] + $currblk['margin_left']
755				+ $prevblk['border_left']['w'] + $prevblk['padding_left'];
756			$currblk['outer_right_margin'] = $prevblk['outer_right_margin'] + $currblk['margin_right']
757				+ $prevblk['border_right']['w'] + $prevblk['padding_right'];
758			$currblk['width'] = $this->mpdf->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin']);
759			$currblk['inner_width'] = $this->mpdf->pgwidth - ($currblk['outer_right_margin']
760					+ $currblk['outer_left_margin'] + $currblk['border_left']['w'] + $currblk['padding_left']
761					+ $currblk['border_right']['w'] + $currblk['padding_right']);
762			// if ($currblk['inner_width'] < $mw) { throw new \Mpdf\MpdfException("DIV is too narrow for text to fit!"); }
763		}
764
765		$this->mpdf->x = $this->mpdf->lMargin + $currblk['outer_left_margin'];
766
767		/* -- BACKGROUNDS -- */
768		if (!empty($properties['BACKGROUND-IMAGE']) && !$this->mpdf->kwt && !$this->mpdf->ColActive && !$this->mpdf->keep_block_together) {
769			$ret = $this->mpdf->SetBackground($properties, $currblk['inner_width']);
770			if ($ret) {
771				$currblk['background-image'] = $ret;
772			}
773		}
774		/* -- END BACKGROUNDS -- */
775
776		/* -- TABLES -- */
777		if ($this->mpdf->use_kwt && isset($attr['KEEP-WITH-TABLE']) && !$this->mpdf->ColActive && !$this->mpdf->keep_block_together) {
778			$this->mpdf->kwt = true;
779			$this->mpdf->kwt_y0 = $this->mpdf->y;
780			//$this->mpdf->kwt_x0 = $this->mpdf->x;
781			$this->mpdf->kwt_x0 = $this->mpdf->lMargin; // mPDF 6
782			$this->mpdf->kwt_height = 0;
783			$this->mpdf->kwt_buffer = [];
784			$this->mpdf->kwt_Links = [];
785			$this->mpdf->kwt_Annots = [];
786			$this->mpdf->kwt_moved = false;
787			$this->mpdf->kwt_saved = false;
788			$this->mpdf->kwt_Reference = [];
789			$this->mpdf->kwt_BMoutlines = [];
790			$this->mpdf->kwt_toc = [];
791		} else {
792			/* -- END TABLES -- */
793			$this->mpdf->kwt = false;
794		} // *TABLES*
795
796		// Save x,y coords in case we need to print borders...
797		$currblk['y0'] = $this->mpdf->y;
798		$currblk['initial_y0'] = $this->mpdf->y; // mPDF 6
799		$currblk['x0'] = $this->mpdf->x;
800		$currblk['initial_x0'] = $this->mpdf->x; // mPDF 6
801		$currblk['initial_startpage'] = $this->mpdf->page;
802		$currblk['startpage'] = $this->mpdf->page; // mPDF 6
803		$this->mpdf->oldy = $this->mpdf->y;
804
805		$this->mpdf->lastblocklevelchange = 1;
806
807		// mPDF 6  Lists
808		if ($tag === 'OL' || $tag === 'UL') {
809			$this->mpdf->listlvl++;
810			if (!empty($attr['START'])) {
811				$this->mpdf->listcounter[$this->mpdf->listlvl] = (int) $attr['START'] - 1;
812			} else {
813				$this->mpdf->listcounter[$this->mpdf->listlvl] = 0;
814			}
815			$this->mpdf->listitem = [];
816
817			// List-type
818			if (empty($currblk['list_style_type'])) {
819				if ($tag === 'OL') {
820					$currblk['list_style_type'] = 'decimal';
821				} elseif ($tag === 'UL') {
822					if ($this->mpdf->listlvl % 3 == 1) {
823						$currblk['list_style_type'] = 'disc';
824					} elseif ($this->mpdf->listlvl % 3 == 2) {
825						$currblk['list_style_type'] = 'circle';
826					} else {
827						$currblk['list_style_type'] = 'square';
828					}
829				}
830			}
831
832			// List-image
833			if (empty($currblk['list_style_image'])) {
834				$currblk['list_style_image'] = 'none';
835			}
836
837			// List-position
838			if (empty($currblk['list_style_position'])) {
839				$currblk['list_style_position'] = 'outside';
840			}
841
842			// Default indentation using padding
843			if (strtolower($this->mpdf->list_auto_mode) === 'mpdf' && isset($currblk['list_style_position'])
844				&& $currblk['list_style_position'] === 'outside' && isset($currblk['list_style_image'])
845				&& $currblk['list_style_image'] === 'none' && (!isset($currblk['list_style_type'])
846					|| !preg_match('/U\+([a-fA-F0-9]+)/i', $currblk['list_style_type']))) {
847				$autopadding = $this->mpdf->_getListMarkerWidth($currblk, $ahtml, $ihtml);
848				if ($this->mpdf->listlvl > 1 || $this->mpdf->list_indent_first_level) {
849					$autopadding += $this->sizeConverter->convert(
850						$this->mpdf->list_indent_default,
851						$currblk['inner_width'],
852						$this->mpdf->FontSize,
853						false
854					);
855				}
856				// autopadding value is applied to left or right according
857				// to dir of block. Once a CSS value is set for padding it overrides this default value.
858				if (isset($properties['PADDING-RIGHT']) && $properties['PADDING-RIGHT'] === 'auto'
859					&& isset($currblk['direction']) && $currblk['direction'] === 'rtl') {
860					$currblk['padding_right'] = $autopadding;
861				} elseif (isset($properties['PADDING-LEFT']) && $properties['PADDING-LEFT'] === 'auto') {
862					$currblk['padding_left'] = $autopadding;
863				}
864			} else {
865				// Initial default value is set by $this->mpdf->list_indent_default in config.php; this value is applied to left or right according
866				// to dir of block. Once a CSS value is set for padding it overrides this default value.
867				if (isset($properties['PADDING-RIGHT']) && $properties['PADDING-RIGHT'] === 'auto'
868					&& isset($currblk['direction']) && $currblk['direction'] === 'rtl') {
869					$currblk['padding_right'] = $this->sizeConverter->convert(
870						$this->mpdf->list_indent_default,
871						$currblk['inner_width'],
872						$this->mpdf->FontSize,
873						false
874					);
875				} elseif (isset($properties['PADDING-LEFT']) && $properties['PADDING-LEFT'] === 'auto') {
876					$currblk['padding_left'] = $this->sizeConverter->convert(
877						$this->mpdf->list_indent_default,
878						$currblk['inner_width'],
879						$this->mpdf->FontSize,
880						false
881					);
882				}
883			}
884		}
885
886		// mPDF 6  Lists
887		if ($tag === 'LI') {
888			if ($this->mpdf->listlvl == 0) { // in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...)
889				$this->mpdf->listlvl++; // first depth level
890				$this->mpdf->listcounter[$this->mpdf->listlvl] = 0;
891			}
892
893			if (!isset($attr['PAGEBREAKAVOIDCHECKED']) || !$attr['PAGEBREAKAVOIDCHECKED']) {
894				$this->mpdf->listcounter[$this->mpdf->listlvl]++;
895			}
896
897			$this->mpdf->listitem = [];
898
899			// Listitem-type
900			$this->mpdf->_setListMarker($currblk['list_style_type'], $currblk['list_style_image'], $currblk['list_style_position']);
901		}
902
903		// mPDF 6 Bidirectional formatting for block elements
904		$bdf = false;
905		$bdf2 = '';
906		$popd = '';
907
908		// Get current direction
909		$currdir = 'ltr';
910		if (isset($currblk['direction'])) {
911			$currdir = $currblk['direction'];
912		}
913		if (isset($attr['DIR']) && $attr['DIR'] != '') {
914			$currdir = strtolower($attr['DIR']);
915		}
916		if (isset($properties['DIRECTION'])) {
917			$currdir = strtolower($properties['DIRECTION']);
918		}
919
920		// mPDF 6 bidi
921		// cf. http://www.w3.org/TR/css3-writing-modes/#unicode-bidi
922		if (isset($properties ['UNICODE-BIDI'])
923			&& (strtolower($properties ['UNICODE-BIDI']) === 'bidi-override' || strtolower($properties ['UNICODE-BIDI']) === 'isolate-override')) {
924			if ($currdir === 'rtl') {
925				$bdf = 0x202E;
926				$popd = 'RLOPDF';
927			} // U+202E RLO
928			else {
929				$bdf = 0x202D;
930				$popd = 'LROPDF';
931			} // U+202D LRO
932		} elseif (isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI']) === 'plaintext') {
933			$bdf = 0x2068;
934			$popd = 'FSIPDI'; // U+2068 FSI
935		}
936		if ($bdf) {
937			if ($bdf2) {
938				$bdf2 = UtfString::code2utf($bdf);
939			}
940			$this->mpdf->OTLdata = [];
941			if ($this->mpdf->tableLevel) {
942				$this->mpdf->_saveCellTextBuffer(UtfString::code2utf($bdf) . $bdf2);
943			} else {
944				$this->mpdf->_saveTextBuffer(UtfString::code2utf($bdf) . $bdf2);
945			}
946			$this->mpdf->biDirectional = true;
947			$currblk['bidicode'] = $popd;
948		}
949	}
950
951	public function close(&$ahtml, &$ihtml)
952	{
953		$tag = $this->getTagName();
954
955		// mPDF 6 bidi
956		// Block
957		// If unicode-bidi set, any embedding levels, isolates, or overrides started by this box are closed
958		if (isset($this->mpdf->blk[$this->mpdf->blklvl]['bidicode'])) {
959			$blockpost = $this->mpdf->_setBidiCodes('end', $this->mpdf->blk[$this->mpdf->blklvl]['bidicode']);
960			if ($blockpost) {
961				$this->mpdf->OTLdata = [];
962				if ($this->mpdf->tableLevel) {
963					$this->mpdf->_saveCellTextBuffer($blockpost);
964				} else {
965					$this->mpdf->_saveTextBuffer($blockpost);
966				}
967			}
968		}
969
970		$this->mpdf->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces
971		$this->mpdf->blockjustfinished = true;
972
973		$this->mpdf->lastblockbottommargin = $this->mpdf->blk[$this->mpdf->blklvl]['margin_bottom'];
974		// mPDF 6  Lists
975		if ($tag === 'UL' || $tag === 'OL') {
976			if ($this->mpdf->listlvl > 0 && $this->mpdf->tableLevel) {
977				if (isset($this->mpdf->listtype[$this->mpdf->listlvl])) {
978					unset($this->mpdf->listtype[$this->mpdf->listlvl]);
979				}
980			}
981			$this->mpdf->listlvl--;
982			$this->mpdf->listitem = [];
983		}
984		if ($tag === 'LI') {
985			$this->mpdf->listitem = [];
986		}
987
988		if (preg_match('/^H\d/', $tag) && !$this->mpdf->tableLevel && !$this->mpdf->writingToC) {
989			if (isset($this->mpdf->h2toc[$tag]) || isset($this->mpdf->h2bookmarks[$tag])) {
990				$content = '';
991				if (count($this->mpdf->textbuffer) == 1) {
992					$content = $this->mpdf->textbuffer[0][0];
993				} else {
994					for ($i = 0; $i < count($this->mpdf->textbuffer); $i++) {
995						if (0 !== strpos($this->mpdf->textbuffer[$i][0], "\xbb\xa4\xac")) { //inline object
996							$content .= $this->mpdf->textbuffer[$i][0];
997						}
998					}
999				}
1000				/* -- TOC -- */
1001				if (isset($this->mpdf->h2toc[$tag])) {
1002					$objattr = [];
1003					$objattr['type'] = 'toc';
1004					$objattr['toclevel'] = $this->mpdf->h2toc[$tag];
1005					$objattr['CONTENT'] = htmlspecialchars($content);
1006					$e = "\xbb\xa4\xactype=toc,objattr=" . serialize($objattr) . "\xbb\xa4\xac";
1007					array_unshift($this->mpdf->textbuffer, [$e]);
1008				}
1009				/* -- END TOC -- */
1010				/* -- BOOKMARKS -- */
1011				if (isset($this->mpdf->h2bookmarks[$tag])) {
1012					$objattr = [];
1013					$objattr['type'] = 'bookmark';
1014					$objattr['bklevel'] = $this->mpdf->h2bookmarks[$tag];
1015					$objattr['CONTENT'] = $content;
1016					$e = "\xbb\xa4\xactype=toc,objattr=" . serialize($objattr) . "\xbb\xa4\xac";
1017					array_unshift($this->mpdf->textbuffer, [$e]);
1018				}
1019				/* -- END BOOKMARKS -- */
1020			}
1021		}
1022
1023		/* -- TABLES -- */
1024		if ($this->mpdf->tableLevel) {
1025			if ($this->mpdf->linebreakjustfinished) {
1026				$this->mpdf->blockjustfinished = false;
1027			}
1028			if (isset($this->mpdf->InlineProperties['BLOCKINTABLE'])) {
1029				if ($this->mpdf->InlineProperties['BLOCKINTABLE']) {
1030					$this->mpdf->restoreInlineProperties($this->mpdf->InlineProperties['BLOCKINTABLE']);
1031				}
1032				unset($this->mpdf->InlineProperties['BLOCKINTABLE']);
1033			}
1034			if ($tag === 'PRE') {
1035				$this->mpdf->ispre = false;
1036			}
1037			return;
1038		}
1039		/* -- END TABLES -- */
1040		$this->mpdf->lastoptionaltag = '';
1041		$this->mpdf->divbegin = false;
1042
1043		$this->mpdf->linebreakjustfinished = false;
1044
1045		$this->mpdf->x = $this->mpdf->lMargin + $this->mpdf->blk[$this->mpdf->blklvl]['outer_left_margin'];
1046
1047		/* -- CSS-FLOAT -- */
1048		// If float contained in a float, need to extend bottom to allow for it
1049		$currpos = $this->mpdf->page * 1000 + $this->mpdf->y;
1050		if (isset($this->mpdf->blk[$this->mpdf->blklvl]['float_endpos']) && $this->mpdf->blk[$this->mpdf->blklvl]['float_endpos'] > $currpos) {
1051			$old_page = $this->mpdf->page;
1052			$new_page = (int) ($this->mpdf->blk[$this->mpdf->blklvl]['float_endpos'] / 1000);
1053			if ($old_page != $new_page) {
1054				$s = $this->mpdf->PrintPageBackgrounds();
1055				// Writes after the marker so not overwritten later by page background etc.
1056				$this->mpdf->pages[$this->mpdf->page] = preg_replace(
1057					'/(___BACKGROUND___PATTERNS' . $this->mpdf->uniqstr . ')/',
1058					'\\1' . "\n" . $s . "\n",
1059					$this->mpdf->pages[$this->mpdf->page]
1060				);
1061				$this->mpdf->pageBackgrounds = [];
1062				$this->mpdf->page = $new_page;
1063				$this->mpdf->ResetMargins();
1064				$this->mpdf->Reset();
1065				$this->mpdf->pageoutput[$this->mpdf->page] = [];
1066			}
1067			// mod changes operands to integers before processing
1068			$this->mpdf->y = (round($this->mpdf->blk[$this->mpdf->blklvl]['float_endpos'] * 1000) % 1000000) / 1000;
1069		}
1070		/* -- END CSS-FLOAT -- */
1071
1072
1073		//Print content
1074		$blockstate = 0;
1075		if ($this->mpdf->lastblocklevelchange == 1) {
1076			$blockstate = 3;
1077		} // Top & bottom margins/padding
1078		elseif ($this->mpdf->lastblocklevelchange == -1) {
1079			$blockstate = 2;
1080		} // Bottom margins/padding only
1081
1082		// called from after e.g. </table> </div> </div> ...    Outputs block margin/border and padding
1083		if (count($this->mpdf->textbuffer) && $this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1]) {
1084			if (0 !== strpos($this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0], "\xbb\xa4\xac")) { // not special content
1085				// Right trim last content and adjust OTLdata
1086				if (preg_match('/[ ]+$/', $this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0], $m)) {
1087					$strip = strlen($m[0]);
1088					$this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0] = substr(
1089						$this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0],
1090						0,
1091						strlen($this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0]) - $strip
1092					);
1093					/* -- OTL -- */
1094					if (!empty($this->mpdf->CurrentFont['useOTL'])) {
1095						$this->otl->trimOTLdata($this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][18], false); // mPDF 6  ZZZ99K
1096					}
1097					/* -- END OTL -- */
1098				}
1099			}
1100		}
1101
1102		if (count($this->mpdf->textbuffer) == 0 && $this->mpdf->lastblocklevelchange != 0) {
1103			/*$this->mpdf->newFlowingBlock(
1104				$this->mpdf->blk[$this->mpdf->blklvl]['width'],
1105				$this->mpdf->lineheight,
1106				'',
1107				false,
1108				2,
1109				true,
1110				(isset($this->mpdf->blk[$this->mpdf->blklvl]['direction']) ? $this->mpdf->blk[$this->mpdf->blklvl]['direction'] : 'ltr')
1111			);*/
1112
1113			$this->mpdf->newFlowingBlock(
1114				$this->mpdf->blk[$this->mpdf->blklvl]['width'],
1115				$this->mpdf->lineheight,
1116				'',
1117				false,
1118				$blockstate,
1119				true,
1120				(isset($this->mpdf->blk[$this->mpdf->blklvl]['direction']) ? $this->mpdf->blk[$this->mpdf->blklvl]['direction'] : 'ltr')
1121			);
1122
1123			$this->mpdf->finishFlowingBlock(true); // true = END of flowing block
1124			$this->mpdf->PaintDivBB('', $blockstate);
1125		} else {
1126			$this->mpdf->printbuffer($this->mpdf->textbuffer, $blockstate);
1127		}
1128
1129
1130		$this->mpdf->textbuffer = [];
1131
1132		if ($this->mpdf->kwt) {
1133			$this->mpdf->kwt_height = $this->mpdf->y - $this->mpdf->kwt_y0;
1134		}
1135
1136		/* -- CSS-IMAGE-FLOAT -- */
1137		$this->mpdf->printfloatbuffer();
1138		/* -- END CSS-IMAGE-FLOAT -- */
1139
1140		if ($tag === 'PRE') {
1141			$this->mpdf->ispre = false;
1142		}
1143
1144		/* -- CSS-FLOAT -- */
1145		if ($this->mpdf->blk[$this->mpdf->blklvl]['float'] === 'R') {
1146			// If width not set, here would need to adjust and output buffer
1147			$s = $this->mpdf->PrintPageBackgrounds();
1148			// Writes after the marker so not overwritten later by page background etc.
1149			$this->mpdf->pages[$this->mpdf->page] = preg_replace('/(___BACKGROUND___PATTERNS' . $this->mpdf->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->mpdf->pages[$this->mpdf->page]);
1150			$this->mpdf->pageBackgrounds = [];
1151			$this->mpdf->Reset();
1152			$this->mpdf->pageoutput[$this->mpdf->page] = [];
1153
1154			for ($i = ($this->mpdf->blklvl - 1); $i >= 0; $i--) {
1155				if (isset($this->mpdf->blk[$i]['float_endpos'])) {
1156					$this->mpdf->blk[$i]['float_endpos'] = max($this->mpdf->blk[$i]['float_endpos'], $this->mpdf->page * 1000 + $this->mpdf->y);
1157				} else {
1158					$this->mpdf->blk[$i]['float_endpos'] = $this->mpdf->page * 1000 + $this->mpdf->y;
1159				}
1160			}
1161
1162			$this->mpdf->floatDivs[] = [
1163				'side' => 'R',
1164				'startpage' => $this->mpdf->blk[$this->mpdf->blklvl]['startpage'],
1165				'y0' => $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y'],
1166				'startpos' => $this->mpdf->blk[$this->mpdf->blklvl]['startpage'] * 1000 + $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y'],
1167				'endpage' => $this->mpdf->page,
1168				'y1' => $this->mpdf->y,
1169				'endpos' => $this->mpdf->page * 1000 + $this->mpdf->y,
1170				'w' => $this->mpdf->blk[$this->mpdf->blklvl]['float_width'],
1171				'blklvl' => $this->mpdf->blklvl,
1172				'blockContext' => $this->mpdf->blk[$this->mpdf->blklvl - 1]['blockContext']
1173			];
1174
1175			$this->mpdf->y = $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y'];
1176			$this->mpdf->page = $this->mpdf->blk[$this->mpdf->blklvl]['startpage'];
1177			$this->mpdf->ResetMargins();
1178			$this->mpdf->pageoutput[$this->mpdf->page] = [];
1179		}
1180		if ($this->mpdf->blk[$this->mpdf->blklvl]['float'] === 'L') {
1181			// If width not set, here would need to adjust and output buffer
1182			$s = $this->mpdf->PrintPageBackgrounds();
1183			// Writes after the marker so not overwritten later by page background etc.
1184			$this->mpdf->pages[$this->mpdf->page] = preg_replace('/(___BACKGROUND___PATTERNS' . $this->mpdf->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->mpdf->pages[$this->mpdf->page]);
1185			$this->mpdf->pageBackgrounds = [];
1186			$this->mpdf->Reset();
1187			$this->mpdf->pageoutput[$this->mpdf->page] = [];
1188
1189			for ($i = ($this->mpdf->blklvl - 1); $i >= 0; $i--) {
1190				if (isset($this->mpdf->blk[$i]['float_endpos'])) {
1191					$this->mpdf->blk[$i]['float_endpos'] = max($this->mpdf->blk[$i]['float_endpos'], $this->mpdf->page * 1000 + $this->mpdf->y);
1192				} else {
1193					$this->mpdf->blk[$i]['float_endpos'] = $this->mpdf->page * 1000 + $this->mpdf->y;
1194				}
1195			}
1196
1197			$this->mpdf->floatDivs[] = [
1198				'side' => 'L',
1199				'startpage' => $this->mpdf->blk[$this->mpdf->blklvl]['startpage'],
1200				'y0' => $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y'],
1201				'startpos' => $this->mpdf->blk[$this->mpdf->blklvl]['startpage'] * 1000 + $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y'],
1202				'endpage' => $this->mpdf->page,
1203				'y1' => $this->mpdf->y,
1204				'endpos' => $this->mpdf->page * 1000 + $this->mpdf->y,
1205				'w' => $this->mpdf->blk[$this->mpdf->blklvl]['float_width'],
1206				'blklvl' => $this->mpdf->blklvl,
1207				'blockContext' => $this->mpdf->blk[$this->mpdf->blklvl - 1]['blockContext']
1208			];
1209
1210			$this->mpdf->y = $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y'];
1211			$this->mpdf->page = $this->mpdf->blk[$this->mpdf->blklvl]['startpage'];
1212			$this->mpdf->ResetMargins();
1213			$this->mpdf->pageoutput[$this->mpdf->page] = [];
1214		}
1215		/* -- END CSS-FLOAT -- */
1216
1217		if (isset($this->mpdf->blk[$this->mpdf->blklvl]['visibility']) && $this->mpdf->blk[$this->mpdf->blklvl]['visibility'] !== 'visible') {
1218			$this->mpdf->SetVisibility('visible');
1219		}
1220
1221		$page_break_after = '';
1222		if (isset($this->mpdf->blk[$this->mpdf->blklvl]['page_break_after'])) {
1223			$page_break_after = $this->mpdf->blk[$this->mpdf->blklvl]['page_break_after'];
1224		}
1225
1226		// Reset values
1227		$this->mpdf->Reset();
1228
1229		if (isset($this->mpdf->blk[$this->mpdf->blklvl]['z-index']) && $this->mpdf->blk[$this->mpdf->blklvl]['z-index'] > 0) {
1230			$this->mpdf->EndLayer();
1231		}
1232
1233		// mPDF 6 page-break-inside:avoid
1234		if ($this->mpdf->blk[$this->mpdf->blklvl]['keep_block_together']) {
1235			$movepage = false;
1236			// If page-break-inside:avoid section has broken to new page but fits on one side - then move:
1237			if (($this->mpdf->page - $this->mpdf->kt_p00) == 1 && $this->mpdf->y < $this->mpdf->kt_y00) {
1238				$movepage = true;
1239			}
1240			if (($this->mpdf->page - $this->mpdf->kt_p00) > 0) {
1241				for ($i = $this->mpdf->page; $i > $this->mpdf->kt_p00; $i--) {
1242					unset($this->mpdf->pages[$i]);
1243					if (isset($this->mpdf->blk[$this->mpdf->blklvl]['bb_painted'][$i])) {
1244						unset($this->mpdf->blk[$this->mpdf->blklvl]['bb_painted'][$i]);
1245					}
1246					if (isset($this->mpdf->blk[$this->mpdf->blklvl]['marginCorrected'][$i])) {
1247						unset($this->mpdf->blk[$this->mpdf->blklvl]['marginCorrected'][$i]);
1248					}
1249					if (isset($this->mpdf->pageoutput[$i])) {
1250						unset($this->mpdf->pageoutput[$i]);
1251					}
1252				}
1253				$this->mpdf->page = $this->mpdf->kt_p00;
1254			}
1255			$this->mpdf->keep_block_together = 0;
1256			$this->mpdf->pageoutput[$this->mpdf->page] = [];
1257
1258			$this->mpdf->y = $this->mpdf->kt_y00;
1259
1260			$ihtml = $this->mpdf->blk[$this->mpdf->blklvl]['array_i'] - 1;
1261
1262			$ahtml[$ihtml + 1] .= ' pagebreakavoidchecked="true";'; // avoid re-iterating; read in OpenTag()
1263
1264			unset($this->mpdf->blk[$this->mpdf->blklvl]);
1265			$this->mpdf->blklvl--;
1266
1267			for ($blklvl = 1; $blklvl <= $this->mpdf->blklvl; $blklvl++) {
1268				$this->mpdf->blk[$blklvl]['y0'] = $this->mpdf->blk[$blklvl]['initial_y0'];
1269				$this->mpdf->blk[$blklvl]['x0'] = $this->mpdf->blk[$blklvl]['initial_x0'];
1270				$this->mpdf->blk[$blklvl]['startpage'] = $this->mpdf->blk[$blklvl]['initial_startpage'];
1271			}
1272
1273			if (isset($this->mpdf->blk[$this->mpdf->blklvl]['x0'])) {
1274				$this->mpdf->x = $this->mpdf->blk[$this->mpdf->blklvl]['x0'];
1275			} else {
1276				$this->mpdf->x = $this->mpdf->lMargin;
1277			}
1278
1279			$this->mpdf->lastblocklevelchange = 0;
1280			$this->mpdf->ResetMargins();
1281			if ($movepage) {
1282				$this->mpdf->AddPage();
1283			}
1284			return;
1285		}
1286
1287		if ($this->mpdf->blklvl > 0) { // ==0 SHOULDN'T HAPPEN - NOT XHTML
1288			if ($this->mpdf->blk[$this->mpdf->blklvl]['tag'] == $tag) {
1289				unset($this->mpdf->blk[$this->mpdf->blklvl]);
1290				$this->mpdf->blklvl--;
1291			}
1292			//else { echo $tag; exit; }	// debug - forces error if incorrectly nested html tags
1293		}
1294
1295		$this->mpdf->lastblocklevelchange = -1;
1296		// Reset Inline-type properties
1297		if (isset($this->mpdf->blk[$this->mpdf->blklvl]['InlineProperties'])) {
1298			$this->mpdf->restoreInlineProperties($this->mpdf->blk[$this->mpdf->blklvl]['InlineProperties']);
1299		}
1300
1301		$this->mpdf->x = $this->mpdf->lMargin + $this->mpdf->blk[$this->mpdf->blklvl]['outer_left_margin'];
1302
1303		if (!$this->mpdf->tableLevel && $page_break_after) {
1304			$save_blklvl = $this->mpdf->blklvl;
1305			$save_blk = $this->mpdf->blk;
1306			$save_silp = $this->mpdf->saveInlineProperties();
1307			$save_ilp = $this->mpdf->InlineProperties;
1308			$save_bflp = $this->mpdf->InlineBDF;
1309			$save_bflpc = $this->mpdf->InlineBDFctr; // mPDF 6
1310			// mPDF 6 pagebreaktype
1311			$startpage = $this->mpdf->page;
1312			$pagebreaktype = $this->mpdf->defaultPagebreakType;
1313			if ($this->mpdf->ColActive) {
1314				$pagebreaktype = 'cloneall';
1315			}
1316
1317			// mPDF 6 pagebreaktype
1318			$this->mpdf->_preForcedPagebreak($pagebreaktype);
1319
1320			if ($page_break_after === 'RIGHT') {
1321				$this->mpdf->AddPage($this->mpdf->CurOrientation, 'NEXT-ODD');
1322			} elseif ($page_break_after === 'LEFT') {
1323				$this->mpdf->AddPage($this->mpdf->CurOrientation, 'NEXT-EVEN');
1324			} else {
1325				$this->mpdf->AddPage($this->mpdf->CurOrientation);
1326			}
1327
1328			// mPDF 6 pagebreaktype
1329			$this->mpdf->_postForcedPagebreak($pagebreaktype, $startpage, $save_blk, $save_blklvl);
1330
1331			$this->mpdf->InlineProperties = $save_ilp;
1332			$this->mpdf->InlineBDF = $save_bflp;
1333			$this->mpdf->InlineBDFctr = $save_bflpc; // mPDF 6
1334			$this->mpdf->restoreInlineProperties($save_silp);
1335		}
1336		// mPDF 6 bidi
1337		// Block
1338		// If unicode-bidi set, any embedding levels, isolates, or overrides reopened in the continuing block
1339		if (isset($this->mpdf->blk[$this->mpdf->blklvl]['bidicode'])) {
1340			$blockpre = $this->mpdf->_setBidiCodes('start', $this->mpdf->blk[$this->mpdf->blklvl]['bidicode']);
1341			if ($blockpre) {
1342				$this->mpdf->OTLdata = [];
1343				if ($this->mpdf->tableLevel) {
1344					$this->mpdf->_saveCellTextBuffer($blockpre);
1345				} else {
1346					$this->mpdf->_saveTextBuffer($blockpre);
1347				}
1348			}
1349		}
1350	}
1351
1352}
1353