Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 12 additions & 14 deletions src/Mpdf.php
Original file line number Diff line number Diff line change
Expand Up @@ -23469,29 +23469,27 @@ function _tableWrite(&$table, $split = false, $startrow = 0, $startcol = 0, $spl
/* -- END BACKGROUNDS -- */
}

if ($this->tableBackgrounds && $level == 1) {
if ($level == 1) {
// Nothing else paints while a page-break-inside:avoid block is being measured - see
// PaintDivBB() and BaseWriter::write() - and what is drawn on the page it starts on
// stays there when the block moves
if (!$this->keep_block_together) {
$s = $this->PrintTableBackgrounds();
$s = $this->tableBackgrounds ? "\n" . $this->PrintTableBackgrounds() . "\n" : '';

// The placeholder this table wrote is spent whether or not anything was put behind
// it. One left in place takes a copy of the next table's backgrounds as well, so a
// table with no background of its own used to leave the one after it painted twice
$placeholder = '___TABLE___BACKGROUNDS' . $this->uniqstr;

if ($this->table_rotate && !$this->processingHeader && !$this->processingFooter) {
$this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->tablebuffer);
if ($level == 1) {
$this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->tablebuffer);
}
$this->tablebuffer = str_replace($placeholder, ' ' . $s, $this->tablebuffer);
} elseif ($this->bufferoutput) {
$this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->headerbuffer);
if ($level == 1) {
$this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->headerbuffer);
}
$this->headerbuffer = str_replace($placeholder, ' ' . $s, $this->headerbuffer);
} else {
$this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->pages[$this->page]);
if ($level == 1) {
$this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->pages[$this->page]);
}
$this->pages[$this->page] = str_replace($placeholder, ' ' . $s, $this->pages[$this->page]);
}
}

$this->tableBackgrounds = [];
}

Expand Down
55 changes: 52 additions & 3 deletions tests/Mpdf/TableBackgroundTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,14 @@ private function pages($pdf)
}

/**
* The rectangles filled red, without the duplicates that come of the same background being
* spliced in behind more than one placeholder
* Every rectangle filled red, in order, including any drawn more than once
*/
private function redRectangles($pdf)
{
$matches = [];
preg_match_all('/' . preg_quote(self::RED_FILL, '/') . '\n([\d.\- ]+) re f/', $pdf, $matches);

return array_values(array_unique($matches[1]));
return $matches[1];
}

private function document($before, $after)
Expand Down Expand Up @@ -87,4 +86,54 @@ public function testATableBackgroundOutsideAnyAvoidBlockIsUnaffected()
$this->assertCount(1, $this->redRectangles($this->render($html)));
}

/**
* Each table writes a placeholder for its backgrounds to be spliced in behind. A table with no
* background of its own left the placeholder in the page, and the next table's backgrounds went
* behind that one as well as its own.
*/
public function testATableWithNoBackgroundDoesNotLeaveTheNextOnePaintedTwice()
{
$html = '<table><tr><td>Plain table cell</td></tr></table>'
. '<table><tr><td bgcolor="red">Red table cell</td></tr></table>';

$this->assertCount(1, $this->redRectangles($this->render($html)));
}

public function testEachTableWithNoBackgroundUsedToAddAnotherCopy()
{
$html = str_repeat('<table><tr><td>Plain table cell</td></tr></table>', 5)
. '<table><tr><td bgcolor="red">Red table cell</td></tr></table>';

$this->assertCount(1, $this->redRectangles($this->render($html)));
}

/**
* Painting the same rectangle twice is invisible while it is opaque; a translucent one comes out
* darker than it was asked to be
*/
public function testATranslucentBackgroundIsNotDarkenedByBeingPaintedTwice()
{
$table = '<table style="background: rgba(255, 0, 0, 0.35)"><tr><td>Translucent table cell</td></tr></table>';

$alone = $this->render($table);
$preceded = $this->render('<table><tr><td>Plain table cell</td></tr></table>' . $table);

$this->assertSame(
preg_match_all('/ re f/', $alone),
preg_match_all('/ re f/', $preceded)
);
}

/**
* The table with the background comes first here, so its placeholder was always taken out before
* the plain table wrote one - this way round has never been wrong
*/
public function testATableWithNoBackgroundAfterAColouredOneIsStillUnaffected()
{
$html = '<table><tr><td bgcolor="red">Red table cell</td></tr></table>'
. '<table><tr><td>Plain table cell</td></tr></table>';

$this->assertCount(1, $this->redRectangles($this->render($html)));
}

}
72 changes: 72 additions & 0 deletions tests/Snapshots/TableBackgroundSnapshotTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace Snapshots;

/**
* @group snapshot
*/
class TableBackgroundSnapshotTest extends Snapshot
{
public function getId()
{
return 'table-background';
}

public function generatePdf()
{
ob_start();
?>
<style>
p.note { margin: 0 0 3mm 0; }

table.panel { border-collapse: collapse; width: 100%; margin-bottom: 4mm; }
table.panel td { padding: 3mm; border: 0.2mm solid #404040; }

table.plain { background: none; }
table.red { background: rgba(208, 32, 32, 0.35); }
table.blue { background: rgba(32, 64, 192, 0.35); }

td.tint { background: rgba(32, 128, 32, 0.35); }
</style>

<h1>mPDF</h1>
<h2>Table backgrounds</h2>

<p class="note">Each pair below is the same colour written twice. The second of each pair has a
table with no background of its own in front of it, which used to leave the pair's second
half painted on top of itself and so darker than the first.</p>

<table class="panel red">
<tr><td>Translucent red, with nothing in front of it</td></tr>
</table>

<table class="panel plain">
<tr><td>A table with no background of its own</td></tr>
</table>

<table class="panel red">
<tr><td>Translucent red again, and the same shade as the first</td></tr>
</table>

<table class="panel plain">
<tr><td>Another table with no background of its own</td></tr>
</table>

<table class="panel blue">
<tr><td>Translucent blue, one table with no background behind it</td></tr>
</table>

<table class="panel plain">
<tr><td>A third table with no background of its own</td></tr>
</table>

<table class="panel">
<tr><td class="tint">A translucent cell rather than a translucent table</td></tr>
</table>
<?php
$html = ob_get_clean();

$this->mpdf = new \Mpdf\Mpdf();
$this->mpdf->WriteHTML($html);
}
}
Binary file added tests/data/snapshots/table-background.pdf
Binary file not shown.
Binary file modified tests/data/snapshots/table.pdf
Binary file not shown.
Loading