UNPKG

pdfmake

Version:

Client/server side PDF printing in pure JavaScript

158 lines (136 loc) 5.02 kB
'use strict'; var isString = require('./helpers').isString; function buildColumnWidths(columns, availableWidth, offsetTotal = 0, tableNode) { var autoColumns = [], autoMin = 0, autoMax = 0, starColumns = [], starMaxMin = 0, starMaxMax = 0, fixedColumns = [], initial_availableWidth = availableWidth; columns.forEach(function (column) { if (isAutoColumn(column)) { autoColumns.push(column); autoMin += column._minWidth; autoMax += column._maxWidth; } else if (isStarColumn(column)) { starColumns.push(column); starMaxMin = Math.max(starMaxMin, column._minWidth); starMaxMax = Math.max(starMaxMax, column._maxWidth); } else { fixedColumns.push(column); } }); fixedColumns.forEach(function (col, colIndex) { // width specified as % if (isString(col.width) && /\d+%/.test(col.width)) { // In tables we have to take into consideration the reserved width for paddings and borders var reservedWidth = 0; if (tableNode) { var paddingLeft = tableNode._layout.paddingLeft(colIndex, tableNode); var paddingRight = tableNode._layout.paddingRight(colIndex, tableNode); var borderLeft = tableNode._layout.vLineWidth(colIndex, tableNode); var borderRight = tableNode._layout.vLineWidth(colIndex + 1, tableNode); if (colIndex === 0) { // first column assumes whole borderLeft and half of border right reservedWidth = paddingLeft + paddingRight + borderLeft + (borderRight / 2); } else if (colIndex === fixedColumns.length - 1) { // last column assumes whole borderRight and half of border left reservedWidth = paddingLeft + paddingRight + (borderLeft / 2) + borderRight; } else { // Columns in the middle assume half of each border reservedWidth = paddingLeft + paddingRight + (borderLeft / 2) + (borderRight / 2); } } var totalAvailableWidth = initial_availableWidth + offsetTotal; col.width = (parseFloat(col.width) * totalAvailableWidth / 100) - reservedWidth; } if (col.width < (col._minWidth) && col.elasticWidth) { col._calcWidth = col._minWidth; } else { col._calcWidth = col.width; } availableWidth -= col._calcWidth; }); // http://www.freesoft.org/CIE/RFC/1942/18.htm // http://www.w3.org/TR/CSS2/tables.html#width-layout // http://dev.w3.org/csswg/css3-tables-algorithms/Overview.src.htm var minW = autoMin + starMaxMin * starColumns.length; var maxW = autoMax + starMaxMax * starColumns.length; if (minW >= availableWidth) { // case 1 - there's no way to fit all columns within available width // that's actually pretty bad situation with PDF as we have no horizontal scroll // no easy workaround (unless we decide, in the future, to split single words) // currently we simply use minWidths for all columns autoColumns.forEach(function (col) { col._calcWidth = col._minWidth; }); starColumns.forEach(function (col) { col._calcWidth = starMaxMin; // starMaxMin already contains padding }); } else { if (maxW < availableWidth) { // case 2 - we can fit rest of the table within available space autoColumns.forEach(function (col) { col._calcWidth = col._maxWidth; availableWidth -= col._calcWidth; }); } else { // maxW is too large, but minW fits within available width var W = availableWidth - minW; var D = maxW - minW; autoColumns.forEach(function (col) { var d = col._maxWidth - col._minWidth; col._calcWidth = col._minWidth + d * W / D; availableWidth -= col._calcWidth; }); } if (starColumns.length > 0) { var starSize = availableWidth / starColumns.length; starColumns.forEach(function (col) { col._calcWidth = starSize; }); } } } function isAutoColumn(column) { return column.width === 'auto'; } function isStarColumn(column) { return column.width === null || column.width === undefined || column.width === '*' || column.width === 'star'; } //TODO: refactor and reuse in measureTable function measureMinMax(columns) { var result = { min: 0, max: 0 }; var maxStar = { min: 0, max: 0 }; var starCount = 0; for (var i = 0, l = columns.length; i < l; i++) { var c = columns[i]; if (isStarColumn(c)) { maxStar.min = Math.max(maxStar.min, c._minWidth); maxStar.max = Math.max(maxStar.max, c._maxWidth); starCount++; } else if (isAutoColumn(c)) { result.min += c._minWidth; result.max += c._maxWidth; } else { result.min += ((c.width !== undefined && c.width) || c._minWidth); result.max += ((c.width !== undefined && c.width) || c._maxWidth); } } if (starCount) { result.min += starCount * maxStar.min; result.max += starCount * maxStar.max; } return result; } /** * Calculates column widths * @private */ module.exports = { buildColumnWidths: buildColumnWidths, measureMinMax: measureMinMax, isAutoColumn: isAutoColumn, isStarColumn: isStarColumn };