Skip to content

Commit

Permalink
Vertical alignment for table cells (bpampuch#74, bpampuch#505)
Browse files Browse the repository at this point in the history
  • Loading branch information
sherpya committed Sep 14, 2016
1 parent af08905 commit f1a051f
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 17 deletions.
14 changes: 11 additions & 3 deletions src/documentContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,18 @@ DocumentContext.prototype.completeColumnGroup = function(height) {

this.endingCell = null;
this.x = saved.x;
this.y = height && (saved.y + height) || saved.bottomMost.y;
this.page = saved.bottomMost.page;
if (height) {
this.y = saved.y + height;
this.page = saved.page;
this.height = height;
this.availableHeight = saved.availableHeight - height;
} else {
this.y = saved.bottomMost.y;
this.page = saved.bottomMost.page;
this.height = saved.bottomMost.y - saved.y;
this.availableHeight = saved.bottomMost.availableHeight;
}
this.availableWidth = saved.availableWidth;
this.availableHeight = saved.bottomMost.availableHeight;
this.lastColumnWidth = saved.lastColumnWidth;
};

Expand Down
50 changes: 39 additions & 11 deletions src/elementWriter.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,14 +210,18 @@ ElementWriter.prototype.addFragment = function(block, useBlockXOffset, useBlockY
break;

case 'image':
var img = pack(item.item);
case 'beginVerticalAlign':
case 'endVerticalAlign':
case 'beginClip':
case 'endClip':
var it = pack(item.item);

img.x = (img.x || 0) + (useBlockXOffset ? (block.xOffset || 0) : ctx.x);
img.y = (img.y || 0) + (useBlockYOffset ? (block.yOffset || 0) : ctx.y);
it.x = (it.x || 0) + (useBlockXOffset ? (block.xOffset || 0) : ctx.x);
it.y = (it.y || 0) + (useBlockYOffset ? (block.yOffset || 0) : ctx.y);

page.items.push({
type: 'image',
item: img
type: item.type,
item: it
});
break;
}
Expand All @@ -231,20 +235,44 @@ ElementWriter.prototype.addFragment = function(block, useBlockXOffset, useBlockY
ElementWriter.prototype.beginClip = function (width, height) {
var ctx = this.context;
var page = ctx.getCurrentPage();
page.items.push({
var item = {
type: 'beginClip',
item: { x: ctx.x, y: ctx.y, width: width, height: height }
});
return true;
};
page.items.push(item);
return item;
};

ElementWriter.prototype.endClip = function () {
var ctx = this.context;
var page = ctx.getCurrentPage();
page.items.push({
var item = {
type: 'endClip'
});
return true;
};
page.items.push(item);
return item;
};

ElementWriter.prototype.beginVerticalAlign = function (verticalAlign) {
var ctx = this.context;
var page = ctx.getCurrentPage();
var item = {
type: 'beginVerticalAlign',
item: { verticalAlign: verticalAlign }
};
page.items.push(item);
return item;
};

ElementWriter.prototype.endVerticalAlign = function (verticalAlign) {
var ctx = this.context;
var page = ctx.getCurrentPage();
var item = {
type: 'endVerticalAlign',
item: { verticalAlign: verticalAlign }
};
page.items.push(item);
return item;
};

/**
Expand Down
35 changes: 33 additions & 2 deletions src/layoutBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function LayoutBuilder(pageSize, pageMargins, imageMeasure) {
this.tracker = new TraversalTracker();
this.imageMeasure = imageMeasure;
this.tableLayouts = {};
this.verticalAlignItemStack = [];
}

LayoutBuilder.prototype.registerTableLayouts = function (tableLayouts) {
Expand Down Expand Up @@ -295,7 +296,12 @@ LayoutBuilder.prototype.processNode = function(node) {
this.linearNodeList.push(node);
decorateNode(node);

var prevTop = self.writer.context().getCurrentPosition().top;
applyMargins(function() {
if (node.verticalAlign) {
var verticalAlignBegin = self.writer.beginVerticalAlign(node.verticalAlign);
}

var absPosition = node.absolutePosition;
if(absPosition){
self.writer.context().beginDetachedBlock();
Expand Down Expand Up @@ -327,7 +333,13 @@ LayoutBuilder.prototype.processNode = function(node) {
if(absPosition){
self.writer.context().endDetachedBlock();
}

if (node.verticalAlign) {
self.verticalAlignItemStack.push({ begin: verticalAlignBegin, end: self.writer.endVerticalAlign(node.verticalAlign) });
}
});
// TODO: ugly; does not work (at least) when page break in node
node._height = self.writer.context().getCurrentPosition().top - prevTop;

function applyMargins(callback) {
var margin = node._margin;
Expand Down Expand Up @@ -401,10 +413,13 @@ LayoutBuilder.prototype.processRow = function(columns, widths, gaps, tableBody,

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

var verticalAlignCols = {};

for(var i = 0, l = columns.length; i < l; i++) {
var column = columns[i];
var width = widths[i]._calcWidth;
var leftOffset = colLeftOffset(i);
var colI = i;

if (column.colSpan && column.colSpan > 1) {
for(var j = 1; j < column.colSpan; j++) {
Expand All @@ -415,12 +430,18 @@ LayoutBuilder.prototype.processRow = function(columns, widths, gaps, tableBody,
self.writer.context().beginColumn(width, leftOffset, getEndingCell(column, i));
if (!column._span) {
if (height) {
self.writer.beginClip(width, height);
var lastClipItem = self.writer.beginClip(width, height);
}
self.processNode(column);
verticalAlignCols[colI] = self.verticalAlignItemStack.length - 1;
addAll(positions, column.positions);
if (height) {
self.writer.endClip();
if (column._height > height) {
self.writer.endClip();
} else {
// optimize by removing unnecessary clipping; this is ugly
lastClipItem.type = '';
}
}
} else if (column._columnEndingContext) {
// row-span ending
Expand All @@ -429,6 +450,16 @@ LayoutBuilder.prototype.processRow = function(columns, widths, gaps, tableBody,
}

self.writer.context().completeColumnGroup(height);

var rowHeight = self.writer.context().height;
for(var i = 0, l = columns.length; i < l; i++) {
var column = columns[i];
if (!column._span && column.verticalAlign) {
var item = self.verticalAlignItemStack[verticalAlignCols[i]].begin.item;
item.viewHeight = rowHeight;
item.nodeHeight = column._height;
}
}
});

return {pageBreaks: pageBreaks, positions: positions};
Expand Down
8 changes: 8 additions & 0 deletions src/pageElementWriter.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ PageElementWriter.prototype.endClip = function() {
return this.writer.endClip();
};

PageElementWriter.prototype.beginVerticalAlign = function(verticalAlign) {
return this.writer.beginVerticalAlign(verticalAlign);
};

PageElementWriter.prototype.endVerticalAlign = function(verticalAlign) {
return this.writer.endVerticalAlign(verticalAlign);
};

PageElementWriter.prototype.addVector = function(vector, ignoreContextX, ignoreContextY, index) {
return this.writer.addVector(vector, ignoreContextX, ignoreContextY, index);
};
Expand Down
30 changes: 29 additions & 1 deletion src/printer.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,13 @@ function renderPages(pages, fontProvider, pdfKitDoc) {
break;
case 'endClip':
endClip(pdfKitDoc);
break
break;
case 'beginVerticalAlign':
beginVerticalAlign(item.item, pdfKitDoc);
break;
case 'endVerticalAlign':
endVerticalAlign(item.item, pdfKitDoc);
break;
}
}
if(page.watermark){
Expand All @@ -275,6 +281,28 @@ function endClip(pdfKitDoc) {
pdfKitDoc.restore();
}

function beginVerticalAlign(item, pdfKitDoc) {
switch(item.verticalAlign) {
case 'center':
pdfKitDoc.save();
pdfKitDoc.translate(0, -(item.nodeHeight - item.viewHeight) / 2);
break;
case 'bottom':
pdfKitDoc.save();
pdfKitDoc.translate(0, -(item.nodeHeight - item.viewHeight));
break;
}
}

function endVerticalAlign(item, pdfKitDoc) {
switch(item.verticalAlign) {
case 'center':
case 'bottom':
pdfKitDoc.restore();
break;
}
}

function renderLine(line, x, y, pdfKitDoc) {
x = x || 0;
y = y || 0;
Expand Down

0 comments on commit f1a051f

Please sign in to comment.