Skip to content

Commit

Permalink
breakOverflow infinite loop bugfix
Browse files Browse the repository at this point in the history
  • Loading branch information
Rafał Pośpiech committed Mar 7, 2019
1 parent d4e06e4 commit 3606ccc
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 26 deletions.
6 changes: 6 additions & 0 deletions examples/LongTable.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<table style="border:1px solid red;width:100%;">
<tr>
<td style="border:1px solid black;width:50%;"><div style="height:1000px;">Long table</div></td>
<td style="border:1px solid black;">Long Table</td>
</tr>
</table>
Binary file added examples/LongTable.pdf
Binary file not shown.
12 changes: 12 additions & 0 deletions examples/LongTable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

$loader = require '../vendor/autoload.php';
$files = ['LongTable'];
foreach ($files as $file) {
$document = (new YetiForcePDF\Document())->init();
$document->loadHtml(file_get_contents($file . '.html'));
$time = microtime(true);
$pdfFile = $document->render();
echo microtime(true) -$time;
file_put_contents($file . '.pdf', $pdfFile);
}
4 changes: 2 additions & 2 deletions lib/Document.php
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ protected function getDocumentFooter(): string
*
* @return \YetiForcePDF\Document
*/
public function addObject(PdfObject $object, $after = null): \YetiForcePDF\Document
public function addObject(PdfObject $object, $after = null): self
{
$afterIndex = count($this->objects);
if ($after) {
Expand Down Expand Up @@ -706,7 +706,7 @@ public function addObject(PdfObject $object, $after = null): \YetiForcePDF\Docum
*
* @return \YetiForcePDF\Document
*/
public function removeObject(\YetiForcePDF\Objects\PdfObject $object): \YetiForcePDF\Document
public function removeObject(\YetiForcePDF\Objects\PdfObject $object): self
{
$this->objects = array_filter($this->objects, function ($currentObject) use ($object) {
return $currentObject !== $object;
Expand Down
56 changes: 32 additions & 24 deletions lib/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -1001,6 +1001,32 @@ public function cutBelow(Box $child, string $yPos)
return $this;
}

public function cutBox($box, $yPos, $cloned)
{
foreach ($box->getChildren() as $child) {
if (!$child->isForMeasurement() || !$child->isRenderable()) {
continue;
}
$childCoords = $child->getCoordinates();
if (Math::comp($childCoords->getEndY(), $yPos) >= 0) {
$childBoxes = $this->cloneAndDivideChildrenAfterY($yPos, [$child]);
foreach ($childBoxes as $childBox) {
$cloned->appendChild($childBox);
}
}
if (Math::comp($childCoords->getY(), $yPos) >= 0) {
$child->setRenderable(false)->setForMeasurement(false);
}
}
if (Math::comp($box->getCoordinates()->getY(), $yPos) < 0 && Math::comp($box->getCoordinates()->getEndY(), $yPos) > 0) {
$this->cutBelow($box, $yPos);
$this->cutAbove($cloned, $yPos);
} elseif (Math::comp($box->getCoordinates()->getY(), $yPos) >= 0) {
$box->setRenderable(false)->setForMeasurement(false);
}
return $cloned;
}

/**
* Group boxes by parent.
*
Expand Down Expand Up @@ -1029,27 +1055,7 @@ public function cloneAndDivideChildrenAfterY(string $yPos, array $boxes = null)
if ($box instanceof TableWrapperBox && Math::comp($boxCoords->getY(), $yPos) <= 0 && Math::comp($boxCoords->getEndY(), $yPos) > 0) {
$cloned = $this->divideTable($box);
} else {
foreach ($box->getChildren() as $child) {
if (!$child->isForMeasurement() || !$child->isRenderable()) {
continue;
}
$childCoords = $child->getCoordinates();
if (Math::comp($childCoords->getEndY(), $yPos) >= 0) {
$childBoxes = $this->cloneAndDivideChildrenAfterY($yPos, [$child]);
foreach ($childBoxes as $childBox) {
$cloned->appendChild($childBox);
}
}
if (Math::comp($childCoords->getY(), $yPos) >= 0) {
$child->setRenderable(false)->setForMeasurement(false);
}
}
if (Math::comp($box->getCoordinates()->getY(), $yPos) < 0 && Math::comp($box->getCoordinates()->getEndY(), $yPos) > 0) {
$this->cutBelow($box, $yPos);
$this->cutAbove($cloned, $yPos);
} elseif (Math::comp($box->getCoordinates()->getY(), $yPos) >= 0) {
$box->setRenderable(false)->setForMeasurement(false);
}
$cloned = $this->cutBox($box, $yPos, $cloned);
}
$clonedBoxes[] = $cloned;
}
Expand Down Expand Up @@ -1219,9 +1225,11 @@ public function breakAfter(Box $box)
/**
* Break overflow of the current page.
*
* @param int $level Is used to stop infinite loop if something goes wrong
*
* @return $this
*/
public function breakOverflow()
public function breakOverflow(int $level = 0)
{
$atYPos = Math::add($this->getDimensions()->getHeight(), (string) $this->margins['top']);
$clonedBoxes = $this->cloneAndDivideChildrenAfterY($atYPos);
Expand All @@ -1238,8 +1246,8 @@ public function breakOverflow()
$this->getBox()->measureHeight(true)->measureOffset()->alignText()->measurePosition();
$newBox->layout(true);
$this->document->setCurrentPage($newPage);
if (Math::comp($newBox->getDimensions()->getHeight(), $this->getDimensions()->getHeight()) > 0) {
$newPage->breakOverflow();
if (Math::comp($newBox->getDimensions()->getHeight(), $this->getDimensions()->getHeight()) > 0 && $level < 1024) {
$newPage->breakOverflow(++$level);
}
unset($clonedBoxes);
return $this;
Expand Down

0 comments on commit 3606ccc

Please sign in to comment.