Current File : /home/tradevaly/www/node_modules/pdfmake/src/elementWriter.js |
'use strict';
var Line = require('./line');
var isNumber = require('./helpers').isNumber;
var pack = require('./helpers').pack;
var offsetVector = require('./helpers').offsetVector;
var DocumentContext = require('./documentContext');
/**
* Creates an instance of ElementWriter - a line/vector writer, which adds
* elements to current page and sets their positions based on the context
*/
function ElementWriter(context, tracker) {
this.context = context;
this.contextStack = [];
this.tracker = tracker;
}
function addPageItem(page, item, index) {
if (index === null || index === undefined || index < 0 || index > page.items.length) {
page.items.push(item);
} else {
page.items.splice(index, 0, item);
}
}
ElementWriter.prototype.addLine = function (line, dontUpdateContextPosition, index) {
var height = line.getHeight();
var context = this.context;
var page = context.getCurrentPage(),
position = this.getCurrentPositionOnPage();
if (context.availableHeight < height || !page) {
return false;
}
line.x = context.x + (line.x || 0);
line.y = context.y + (line.y || 0);
this.alignLine(line);
addPageItem(page, {
type: 'line',
item: line
}, index);
this.tracker.emit('lineAdded', line);
if (!dontUpdateContextPosition) {
context.moveDown(height);
}
return position;
};
ElementWriter.prototype.alignLine = function (line) {
var width = this.context.availableWidth;
var lineWidth = line.getWidth();
var alignment = line.inlines && line.inlines.length > 0 && line.inlines[0].alignment;
var offset = 0;
switch (alignment) {
case 'right':
offset = width - lineWidth;
break;
case 'center':
offset = (width - lineWidth) / 2;
break;
}
if (offset) {
line.x = (line.x || 0) + offset;
}
if (alignment === 'justify' &&
!line.newLineForced &&
!line.lastLineInParagraph &&
line.inlines.length > 1) {
var additionalSpacing = (width - lineWidth) / (line.inlines.length - 1);
for (var i = 1, l = line.inlines.length; i < l; i++) {
offset = i * additionalSpacing;
line.inlines[i].x += offset;
line.inlines[i].justifyShift = additionalSpacing;
}
}
};
ElementWriter.prototype.addImage = function (image, index, type) {
var context = this.context;
var page = context.getCurrentPage(),
position = this.getCurrentPositionOnPage();
if (!page || (image.absolutePosition === undefined && context.availableHeight < image._height && page.items.length > 0)) {
return false;
}
if (image._x === undefined) {
image._x = image.x || 0;
}
image.x = context.x + image._x;
image.y = context.y;
this.alignImage(image);
addPageItem(page, {
type: type || 'image',
item: image
}, index);
context.moveDown(image._height);
return position;
};
ElementWriter.prototype.addSVG = function (image, index) {
return this.addImage(image, index, 'svg')
};
ElementWriter.prototype.addQr = function (qr, index) {
var context = this.context;
var page = context.getCurrentPage(),
position = this.getCurrentPositionOnPage();
if (!page || (qr.absolutePosition === undefined && context.availableHeight < qr._height)) {
return false;
}
if (qr._x === undefined) {
qr._x = qr.x || 0;
}
qr.x = context.x + qr._x;
qr.y = context.y;
this.alignImage(qr);
for (var i = 0, l = qr._canvas.length; i < l; i++) {
var vector = qr._canvas[i];
vector.x += qr.x;
vector.y += qr.y;
this.addVector(vector, true, true, index);
}
context.moveDown(qr._height);
return position;
};
ElementWriter.prototype.alignImage = function (image) {
var width = this.context.availableWidth;
var imageWidth = image._minWidth;
var offset = 0;
switch (image._alignment) {
case 'right':
offset = width - imageWidth;
break;
case 'center':
offset = (width - imageWidth) / 2;
break;
}
if (offset) {
image.x = (image.x || 0) + offset;
}
};
ElementWriter.prototype.alignCanvas = function (node) {
var width = this.context.availableWidth;
var canvasWidth = node._minWidth;
var offset = 0;
switch (node._alignment) {
case 'right':
offset = width - canvasWidth;
break;
case 'center':
offset = (width - canvasWidth) / 2;
break;
}
if (offset) {
node.canvas.forEach(function (vector) {
offsetVector(vector, offset, 0);
});
}
};
ElementWriter.prototype.addVector = function (vector, ignoreContextX, ignoreContextY, index) {
var context = this.context;
var page = context.getCurrentPage(),
position = this.getCurrentPositionOnPage();
if (page) {
offsetVector(vector, ignoreContextX ? 0 : context.x, ignoreContextY ? 0 : context.y);
addPageItem(page, {
type: 'vector',
item: vector
}, index);
return position;
}
};
ElementWriter.prototype.beginClip = function (width, height) {
var ctx = this.context;
var page = ctx.getCurrentPage();
page.items.push({
type: 'beginClip',
item: { x: ctx.x, y: ctx.y, width: width, height: height }
});
return true;
};
ElementWriter.prototype.endClip = function () {
var ctx = this.context;
var page = ctx.getCurrentPage();
page.items.push({
type: 'endClip'
});
return true;
};
function cloneLine(line) {
var result = new Line(line.maxWidth);
for (var key in line) {
if (line.hasOwnProperty(key)) {
result[key] = line[key];
}
}
return result;
}
ElementWriter.prototype.addFragment = function (block, useBlockXOffset, useBlockYOffset, dontUpdateContextPosition) {
var ctx = this.context;
var page = ctx.getCurrentPage();
if (!useBlockXOffset && block.height > ctx.availableHeight) {
return false;
}
block.items.forEach(function (item) {
switch (item.type) {
case 'line':
var l = cloneLine(item.item);
if (l._node) {
l._node.positions[0].pageNumber = ctx.page + 1;
}
l.x = (l.x || 0) + (useBlockXOffset ? (block.xOffset || 0) : ctx.x);
l.y = (l.y || 0) + (useBlockYOffset ? (block.yOffset || 0) : ctx.y);
page.items.push({
type: 'line',
item: l
});
break;
case 'vector':
var v = pack(item.item);
offsetVector(v, useBlockXOffset ? (block.xOffset || 0) : ctx.x, useBlockYOffset ? (block.yOffset || 0) : ctx.y);
page.items.push({
type: 'vector',
item: v
});
break;
case 'image':
case 'svg':
var img = 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);
page.items.push({
type: item.type,
item: img
});
break;
}
});
if (!dontUpdateContextPosition) {
ctx.moveDown(block.height);
}
return true;
};
/**
* Pushes the provided context onto the stack or creates a new one
*
* pushContext(context) - pushes the provided context and makes it current
* pushContext(width, height) - creates and pushes a new context with the specified width and height
* pushContext() - creates a new context for unbreakable blocks (with current availableWidth and full-page-height)
*/
ElementWriter.prototype.pushContext = function (contextOrWidth, height) {
if (contextOrWidth === undefined) {
height = this.context.getCurrentPage().height - this.context.pageMargins.top - this.context.pageMargins.bottom;
contextOrWidth = this.context.availableWidth;
}
if (isNumber(contextOrWidth)) {
contextOrWidth = new DocumentContext({ width: contextOrWidth, height: height }, { left: 0, right: 0, top: 0, bottom: 0 });
}
this.contextStack.push(this.context);
this.context = contextOrWidth;
};
ElementWriter.prototype.popContext = function () {
this.context = this.contextStack.pop();
};
ElementWriter.prototype.getCurrentPositionOnPage = function () {
return (this.contextStack[0] || this.context).getCurrentPosition();
};
module.exports = ElementWriter;