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