Skip to content
Draft
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
113 changes: 113 additions & 0 deletions src/Mpdf.php
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,14 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
var $floatbuffer;
var $floatmargins;

/**
* The top and bottom of each floated image drawn in a column since the columns were last laid out, by column,
* so balancing does not split a column beside one
*
* @var array[]
*/
var $columnFloats;

var $bullet;
var $bulletarray;

Expand Down Expand Up @@ -1305,6 +1313,7 @@ public function __construct(array $config = [], $container = null)
$this->PageAnnots = [];
$this->PageNumSubstitutions = [];
$this->breakpoints = []; // used in columnbuffer
$this->columnFloats = [];
$this->tableLevel = 0;
$this->tbctr = []; // counter for nested tables at each level
$this->page_box = new PageBox();
Expand Down Expand Up @@ -17386,6 +17395,15 @@ function printbuffer($arrayaux, $blockstate = 0, $is_table = false, $table_draft
/* -- END CSS-IMAGE-FLOAT -- */

list($skipln) = $this->inlineObject($objattr['type'], '', $this->y, $objattr, $this->lMargin, ($this->flowingBlockAttr['contentWidth'] / Mpdf::SCALE), $maxWidth, $this->flowingBlockAttr['height'], false, $is_table);
/* -- COLUMNS -- */
// A floated image too tall or wide for an empty column is set in its line as before
if ($this->ColActive && isset($objattr['float'])) {
$columnHeight = $this->PageBreakTrigger - ($this->CurrCol < $this->NbCol - 1 ? $this->y0 : $this->tMargin);
if (abs($objattr['height']) > $columnHeight || $objattr['width'] > $this->blk[$this->blklvl]['inner_width']) {
unset($objattr['float']);
}
}
/* -- END COLUMNS -- */
// 1 -> New line needed because of width
// -1 -> Will fit width on line but NEW PAGE REQUIRED because of height
// -2 -> Will not fit on line therefore needs new line but thus NEW PAGE REQUIRED
Expand Down Expand Up @@ -17504,6 +17522,12 @@ function printbuffer($arrayaux, $blockstate = 0, $is_table = false, $table_draft
$objattr['OUTER-HEIGHT'] = $h;
$objattr['OUTER-X'] = $fx;
$objattr['OUTER-Y'] = $fy;
/* -- COLUMNS -- */
if ($this->ColActive) {
$objattr['column'] = $this->CurrCol;
$objattr['columnbuffer_from'] = count($this->columnbuffer);
}
/* -- END COLUMNS -- */
if ($objattr['float'] == 'R') {
// If R float already exists at this level
$this->floatmargins['R']['skipline'] = false;
Expand Down Expand Up @@ -25280,6 +25304,8 @@ function AcceptPageBreak()
} // *TABLES*
/* -- COLUMNS -- */
if ($this->ColActive == 1) {
// A floated image stays in the column it was placed in
$this->printfloatbuffer(); // *CSS-IMAGE-FLOAT*
if ($this->CurrCol < $this->NbCol - 1) {
// Go to the next column
$this->CurrCol++;
Expand Down Expand Up @@ -25326,6 +25352,10 @@ function AcceptPageBreak()
function SetColumns($NbCol, $vAlign = '', $gap = 5)
{
// NbCol = number of columns
// A floated image is drawn in its column before the columns are laid out
if ($this->ColActive) {
$this->printfloatbuffer(); // *CSS-IMAGE-FLOAT*
}
// Anything less than 2 turns columns off
if ($NbCol < 2) { // SET COLUMNS OFF
if ($this->ColActive) {
Expand All @@ -25348,6 +25378,7 @@ function SetColumns($NbCol, $vAlign = '', $gap = 5)
$this->col_BMoutlines = [];
$this->col_toc = [];
$this->breakpoints = [];
$this->columnFloats = [];
} else { // SET COLUMNS ON
if ($this->ColActive) {
$this->ColActive = 0;
Expand All @@ -25372,6 +25403,7 @@ function SetColumns($NbCol, $vAlign = '', $gap = 5)
$this->col_BMoutlines = [];
$this->col_toc = [];
$this->breakpoints = [];
$this->columnFloats = [];
if ((strtoupper($vAlign) == 'J') || (strtoupper($vAlign) == 'JUSTIFY')) {
$vAlign = 'J';
} else {
Expand Down Expand Up @@ -25428,6 +25460,8 @@ function AddColumn()
function NewColumn()
{
if ($this->ColActive == 1) {
// A floated image stays in the column it was placed in
$this->printfloatbuffer(); // *CSS-IMAGE-FLOAT*
if ($this->CurrCol < $this->NbCol - 1) {
// Go to the next column
$this->CurrCol++;
Expand Down Expand Up @@ -25504,6 +25538,9 @@ function printcolumnbuffer()
$breaks = [];
foreach ($this->breakpoints as $c => $bpa) {
foreach ($bpa as $rely) {
if ($this->besideColumnFloat($c, $rely)) {
continue;
}
$breaks[] = $rely + $this->ColDetails[$c]['add_y'] - $this->y0;
}
}
Expand Down Expand Up @@ -25925,6 +25962,7 @@ function printcolumnbuffer()
$this->col_BMoutlines = [];
$this->col_toc = [];
$this->breakpoints = [];
$this->columnFloats = [];
}

// mPDF 5.7+
Expand Down Expand Up @@ -26362,6 +26400,15 @@ function printkwtbuffer()
function printfloatbuffer()
{
if (count($this->floatbuffer)) {
/* -- COLUMNS -- */
if ($this->ColActive) {
$this->printColumnFloats();
$this->floatbuffer = [];
$this->floatmargins = [];

return;
}
/* -- END COLUMNS -- */
$this->objectbuffer = $this->floatbuffer;
$this->printobjectbuffer(false);
$this->objectbuffer = [];
Expand All @@ -26370,6 +26417,72 @@ function printfloatbuffer()
}
}

/* -- COLUMNS -- */
/**
* Draw the floated images into the column buffer, each where balancing the columns will keep it with the lines
* beside it
*
* A float is drawn after the lines that wrap around it, but balancing assigns columns in buffer order, so it is
* filed before the first line level with or below its top. The object buffer and current column are put back.
*/
private function printColumnFloats()
{
$column = $this->CurrCol;
$objects = $this->objectbuffer;

foreach ($this->floatbuffer as $float) {
$this->CurrCol = isset($float['column']) ? $float['column'] : $column;
$top = $float['OUTER-Y'];
$bottom = $top + $float['OUTER-HEIGHT'];
$columnBottom = isset($this->ColDetails[$this->CurrCol]['bottom_margin']) ? $this->ColDetails[$this->CurrCol]['bottom_margin'] : 0;
$drawnFrom = count($this->columnbuffer);

$this->objectbuffer = [$float];
$this->printobjectbuffer(false);

$this->ColDetails[$this->CurrCol]['bottom_margin'] = max($columnBottom, $bottom);
$this->columnFloats[$this->CurrCol][] = [$top, $bottom];

// columnbuffer_from may sit before an earlier float's splice: the scan still finds the first level line
$drawn = array_splice($this->columnbuffer, $drawnFrom);
$at = count($this->columnbuffer);
for ($i = isset($float['columnbuffer_from']) ? $float['columnbuffer_from'] : $drawnFrom; $i < $drawnFrom; $i++) {
if ($this->columnbuffer[$i]['col'] == $this->CurrCol && $this->columnbuffer[$i]['y'] >= $top - 0.001) {
$at = $i;
break;
}
}
array_splice($this->columnbuffer, $at, 0, $drawn);
}

$this->CurrCol = $column;
$this->objectbuffer = $objects;
}

/**
* Whether a column break at this height would split the column beside a floated image
*
* @param int $column
* @param float $y
*
* @return bool
*/
private function besideColumnFloat($column, $y)
{
if (empty($this->columnFloats[$column])) {
return false;
}

foreach ($this->columnFloats[$column] as $extent) {
if ($y > $extent[0] + 0.001 && $y < $extent[1] - 0.001) {
return true;
}
}

return false;
}
/* -- END COLUMNS -- */

function Circle($x, $y, $r, $style = 'S')
{
$this->Ellipse($x, $y, $r, $r, $style);
Expand Down
2 changes: 1 addition & 1 deletion src/Tag/Img.php
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ public function open($attr, &$ahtml, &$ihtml)
}
/* -- END BORDER-RADIUS -- */
/* -- CSS-IMAGE-FLOAT -- */
if (!$this->mpdf->ColActive && !$this->mpdf->tableLevel && !$this->mpdf->listlvl && !$this->mpdf->kwt) {
if (!$this->mpdf->tableLevel && !$this->mpdf->listlvl && !$this->mpdf->kwt) {
if (isset($properties['FLOAT']) && (strtoupper($properties['FLOAT']) === 'RIGHT' || strtoupper($properties['FLOAT']) === 'LEFT')) {
$objattr['float'] = strtoupper(substr($properties['FLOAT'], 0, 1));
}
Expand Down
Loading
Loading