Skip to content

Commit

Permalink
backport PR #2785
Browse files Browse the repository at this point in the history
  • Loading branch information
liborm85 committed Sep 13, 2024
1 parent 7dbe98e commit ad08880
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 10 deletions.
20 changes: 16 additions & 4 deletions src/documentContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function DocumentContext(pageSize, pageMargins) {
this.addPage(pageSize);
}

DocumentContext.prototype.beginColumnGroup = function () {
DocumentContext.prototype.beginColumnGroup = function (marginXTopParent) {
this.snapshots.push({
x: this.x,
y: this.y,
Expand All @@ -44,6 +44,13 @@ DocumentContext.prototype.beginColumnGroup = function () {
});

this.lastColumnWidth = 0;
if (marginXTopParent) {
this.marginXTopParent = marginXTopParent;
}
};

DocumentContext.prototype.resetMarginXTopParent = function () {
this.marginXTopParent = null;
};

DocumentContext.prototype.beginColumn = function (width, offset, endingCell) {
Expand Down Expand Up @@ -131,14 +138,19 @@ DocumentContext.prototype.moveDown = function (offset) {
DocumentContext.prototype.initializePage = function () {
this.y = this.pageMargins.top;
this.availableHeight = this.getCurrentPage().pageSize.height - this.pageMargins.top - this.pageMargins.bottom;
this.pageSnapshot().availableWidth = this.getCurrentPage().pageSize.width - this.pageMargins.left - this.pageMargins.right;
const {pageCtx, isSnapshot} = this.pageSnapshot();
pageCtx.availableWidth = this.getCurrentPage().pageSize.width - this.pageMargins.left - this.pageMargins.right;
if (isSnapshot && this.marginXTopParent) {
pageCtx.availableWidth -= this.marginXTopParent[0];
pageCtx.availableWidth -= this.marginXTopParent[1];
}
};

DocumentContext.prototype.pageSnapshot = function () {
if (this.snapshots[0]) {
return this.snapshots[0];
return {pageCtx: this.snapshots[0], isSnapshot: true};
} else {
return this;
return {pageCtx: this, isSnapshot: false};
}
};

Expand Down
48 changes: 42 additions & 6 deletions src/layoutBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function LayoutBuilder(pageSize, pageMargins, imageMeasure, svgMeasure) {
this.imageMeasure = imageMeasure;
this.svgMeasure = svgMeasure;
this.tableLayouts = {};
this.nestedLevel = 0;
}

LayoutBuilder.prototype.registerTableLayouts = function (tableLayouts) {
Expand Down Expand Up @@ -441,32 +442,53 @@ LayoutBuilder.prototype.processNode = function (node) {
}
}

if (margin) {
const isDetachedBlock = node.relativePosition || node.absolutePosition;

// Detached nodes have no margins, their position is only determined by 'x' and 'y'
if (margin && !isDetachedBlock) {
const availableHeight = self.writer.context().availableHeight;
// If top margin is bigger than available space, move to next page
// Necessary for nodes inside tables
if (availableHeight - margin[1] < 0) {
// Consume the whole available space
self.writer.context().moveDown(availableHeight);
self.writer.moveToNextPage(node.pageOrientation);
/**
* TODO - Something to consider:
* Right now the node starts at the top of next page (after header)
* Another option would be to apply just the top margin that has not been consumed in the page before
* It would something like: this.write.context().moveDown(margin[1] - availableHeight)
*/
} else {
self.writer.context().moveDown(margin[1]);
self.writer.context().addMargin(margin[0], margin[2]);
}

// Apply lateral margins
self.writer.context().addMargin(margin[0], margin[2]);
}

callback();

if (margin) {
// Detached nodes have no margins, their position is only determined by 'x' and 'y'
if (margin && !isDetachedBlock) {
const availableHeight = self.writer.context().availableHeight;
// If bottom margin is bigger than available space, move to next page
// Necessary for nodes inside tables
if (availableHeight - margin[3] < 0) {
self.writer.context().moveDown(availableHeight);
self.writer.moveToNextPage(node.pageOrientation);
/**
* TODO - Something to consider:
* Right now next node starts at the top of next page (after header)
* Another option would be to apply the bottom margin that has not been consumed in the next page?
* It would something like: this.write.context().moveDown(margin[3] - availableHeight)
*/
} else {
self.writer.context().addMargin(-margin[0], -margin[2]);
self.writer.context().moveDown(margin[3]);
}

// Apply lateral margins
self.writer.context().addMargin(-margin[0], -margin[2]);
}

if (node.pageBreak === 'after') {
Expand Down Expand Up @@ -498,6 +520,7 @@ LayoutBuilder.prototype.processVerticalContainer = function (node) {

// columns
LayoutBuilder.prototype.processColumns = function (columnNode) {
this.nestedLevel++;
var columns = columnNode.columns;
var availableWidth = this.writer.context().availableWidth;
var gaps = gapArray(columnNode._gap);
Expand All @@ -508,12 +531,17 @@ LayoutBuilder.prototype.processColumns = function (columnNode) {

ColumnCalculator.buildColumnWidths(columns, availableWidth);
var result = this.processRow({
marginX: columnNode._margin ? [columnNode._margin[0], columnNode._margin[2]] : [0, 0],
cells: columns,
widths: columns,
gaps
});
addAll(columnNode.positions, result.positions);

this.nestedLevel--;
if (this.nestedLevel === 0) {
this.writer.context().resetMarginXTopParent();
}

function gapArray(gap) {
if (!gap) {
Expand Down Expand Up @@ -546,7 +574,7 @@ LayoutBuilder.prototype.findStartingSpanCell = function (arr, i) {
return null;
}

LayoutBuilder.prototype.processRow = function ({dontBreakRows = false, rowsWithoutPageBreak = 0, cells, widths, gaps, tableBody, rowIndex, height}) {
LayoutBuilder.prototype.processRow = function ({marginX = [0, 0], dontBreakRows = false, rowsWithoutPageBreak = 0, cells, widths, gaps, tableBody, rowIndex, height}) {
var self = this;
var isUnbreakableRow = dontBreakRows || rowIndex <= rowsWithoutPageBreak - 1;
var pageBreaks = []
Expand All @@ -560,8 +588,10 @@ LayoutBuilder.prototype.processRow = function ({dontBreakRows = false, rowsWitho
}

widths = widths || cells;
// Use the marginX if we are in a top level table/column (not nested)
const marginXParent = self.nestedLevel === 1 ? marginX : null;

self.writer.context().beginColumnGroup();
self.writer.context().beginColumnGroup(marginXParent);

for (var i = 0, l = cells.length; i < l; i++) {
var column = cells[i];
Expand Down Expand Up @@ -756,6 +786,7 @@ LayoutBuilder.prototype.processList = function (orderedList, node) {

// tables
LayoutBuilder.prototype.processTable = function (tableNode) {
this.nestedLevel++;
var processor = new TableProcessor(tableNode);

processor.beginTable(this.writer);
Expand Down Expand Up @@ -788,6 +819,7 @@ LayoutBuilder.prototype.processTable = function (tableNode) {
}

var result = this.processRow({
marginX: tableNode._margin ? [tableNode._margin[0], tableNode._margin[2]] : [0, 0],
dontBreakRows: processor.dontBreakRows,
rowsWithoutPageBreak: processor.rowsWithoutPageBreak,
cells: tableNode.table.body[i],
Expand All @@ -803,6 +835,10 @@ LayoutBuilder.prototype.processTable = function (tableNode) {
}

processor.endTable(this.writer);
this.nestedLevel--;
if (this.nestedLevel === 0) {
this.writer.context().resetMarginXTopParent();
}
};

// leafs (texts)
Expand Down

0 comments on commit ad08880

Please sign in to comment.