@digicole/pdfmake-rtl 1.2.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/.vscode/tasks.json +17 -0
  2. package/CHANGELOG.md +83 -128
  3. package/LICENSE +22 -22
  4. package/README.md +188 -681
  5. package/build/fonts/Cairo/Cairo-Black.ttf +0 -0
  6. package/build/fonts/Cairo/Cairo-Bold.ttf +0 -0
  7. package/build/fonts/Cairo/Cairo-ExtraLight.ttf +0 -0
  8. package/build/fonts/Cairo/Cairo-Light.ttf +0 -0
  9. package/build/fonts/Cairo/Cairo-Regular.ttf +0 -0
  10. package/build/fonts/Cairo/Cairo-SemiBold.ttf +0 -0
  11. package/build/fonts/Cairo.js +27 -0
  12. package/build/fonts/Roboto/Roboto-Italic.ttf +0 -0
  13. package/build/fonts/Roboto/Roboto-Medium.ttf +0 -0
  14. package/build/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
  15. package/build/fonts/Roboto/Roboto-Regular.ttf +0 -0
  16. package/build/fonts/Roboto.js +27 -0
  17. package/build/pdfmake.js +63736 -71285
  18. package/build/pdfmake.js.map +1 -1
  19. package/build/pdfmake.min.js +2 -2
  20. package/build/pdfmake.min.js.map +1 -1
  21. package/build/standard-fonts/Courier.js +27 -0
  22. package/build/standard-fonts/Helvetica.js +27 -0
  23. package/build/standard-fonts/Symbol.js +21 -0
  24. package/build/standard-fonts/Times.js +27 -0
  25. package/build/standard-fonts/ZapfDingbats.js +21 -0
  26. package/build/vfs_fonts.js +11 -7
  27. package/build-vfs.js +44 -44
  28. package/fonts/Cairo/Cairo-Black.ttf +0 -0
  29. package/fonts/Cairo/Cairo-Bold.ttf +0 -0
  30. package/fonts/Cairo/Cairo-ExtraLight.ttf +0 -0
  31. package/fonts/Cairo/Cairo-Light.ttf +0 -0
  32. package/fonts/Cairo/Cairo-Regular.ttf +0 -0
  33. package/fonts/Cairo/Cairo-SemiBold.ttf +0 -0
  34. package/fonts/Cairo.js +8 -0
  35. package/fonts/Roboto/Roboto-Italic.ttf +0 -0
  36. package/fonts/Roboto/Roboto-Medium.ttf +0 -0
  37. package/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
  38. package/fonts/Roboto/Roboto-Regular.ttf +0 -0
  39. package/fonts/Roboto.js +8 -0
  40. package/index.js +26 -26
  41. package/package.json +42 -39
  42. package/src/3rd-party/svg-to-pdfkit/LICENSE +9 -9
  43. package/src/3rd-party/svg-to-pdfkit/source.js +229 -36
  44. package/src/3rd-party/svg-to-pdfkit.js +3 -3
  45. package/src/OutputDocument.js +64 -0
  46. package/src/OutputDocumentServer.js +32 -0
  47. package/src/PDFDocument.js +174 -0
  48. package/src/PageSize.js +53 -0
  49. package/src/Renderer.js +445 -0
  50. package/src/TextBreaker.js +168 -0
  51. package/src/TextInlines.js +263 -0
  52. package/src/URLResolver.js +43 -0
  53. package/src/base.js +70 -0
  54. package/src/browser-extensions/OutputDocumentBrowser.js +80 -0
  55. package/src/browser-extensions/fonts/Cairo.js +27 -0
  56. package/src/browser-extensions/fonts/Roboto.js +27 -0
  57. package/src/browser-extensions/index.js +61 -0
  58. package/src/browser-extensions/pdfMake.js +1 -355
  59. package/src/browser-extensions/standard-fonts/Courier.js +27 -0
  60. package/src/browser-extensions/standard-fonts/Helvetica.js +27 -0
  61. package/src/browser-extensions/standard-fonts/Symbol.js +21 -0
  62. package/src/browser-extensions/standard-fonts/Times.js +27 -0
  63. package/src/browser-extensions/standard-fonts/ZapfDingbats.js +21 -0
  64. package/src/browser-extensions/virtual-fs-cjs.js +1 -0
  65. package/src/columnCalculator.js +154 -157
  66. package/src/docMeasure.js +802 -810
  67. package/src/docPreprocessor.js +306 -273
  68. package/src/documentContext.js +345 -340
  69. package/src/elementWriter.js +736 -411
  70. package/src/helpers/node.js +136 -0
  71. package/src/helpers/tools.js +44 -0
  72. package/src/helpers/variableType.js +50 -0
  73. package/src/index.js +16 -0
  74. package/src/layoutBuilder.js +1393 -1197
  75. package/src/line.js +122 -104
  76. package/src/pageElementWriter.js +187 -174
  77. package/src/printer.js +370 -727
  78. package/src/qrEnc.js +796 -791
  79. package/src/rtlUtils.js +500 -485
  80. package/src/standardPageSizes.js +52 -54
  81. package/src/styleContextStack.js +208 -138
  82. package/src/svgMeasure.js +109 -70
  83. package/src/tableLayouts.js +100 -0
  84. package/src/tableProcessor.js +620 -606
  85. package/src/textDecorator.js +175 -157
  86. package/src/virtual-fs.js +66 -0
  87. package/standard-fonts/Courier.js +8 -0
  88. package/standard-fonts/Helvetica.js +8 -0
  89. package/standard-fonts/Symbol.js +5 -0
  90. package/standard-fonts/Times.js +8 -0
  91. package/standard-fonts/ZapfDingbats.js +5 -0
  92. package/index.html +0 -396
  93. package/src/browser-extensions/URLBrowserResolver.js +0 -96
  94. package/src/browser-extensions/virtual-fs.js +0 -55
  95. package/src/fontProvider.js +0 -68
  96. package/src/helpers.js +0 -138
  97. package/src/imageMeasure.js +0 -62
  98. package/src/pdfKitEngine.js +0 -21
  99. package/src/textTools.js +0 -391
  100. package/src/traversalTracker.js +0 -47
@@ -1,606 +1,620 @@
1
- 'use strict';
2
-
3
- var ColumnCalculator = require('./columnCalculator');
4
- var isFunction = require('./helpers').isFunction;
5
- var isNumber = require('./helpers').isNumber;
6
- var isPositiveInteger = require('./helpers').isPositiveInteger;
7
-
8
- function TableProcessor(tableNode) {
9
- this.tableNode = tableNode;
10
- }
11
-
12
- TableProcessor.prototype.beginTable = function (writer) {
13
- var tableNode;
14
- var availableWidth;
15
- var self = this;
16
-
17
- tableNode = this.tableNode;
18
- this.offsets = tableNode._offsets;
19
- this.layout = tableNode._layout;
20
-
21
- availableWidth = writer.context().availableWidth - this.offsets.total;
22
- ColumnCalculator.buildColumnWidths(tableNode.table.widths, availableWidth, this.offsets.total, tableNode);
23
-
24
- this.tableWidth = tableNode._offsets.total + getTableInnerContentWidth();
25
- this.rowSpanData = prepareRowSpanData();
26
- this.cleanUpRepeatables = false;
27
-
28
- // headersRows and rowsWithoutPageBreak (headerRows + keepWithHeaderRows)
29
- this.headerRows = 0;
30
- this.rowsWithoutPageBreak = 0;
31
-
32
- var headerRows = tableNode.table.headerRows;
33
-
34
- if (isPositiveInteger(headerRows)) {
35
- this.headerRows = headerRows;
36
-
37
- if (this.headerRows > tableNode.table.body.length) {
38
- throw new Error(`Too few rows in the table. Property headerRows requires at least ${this.headerRows}, contains only ${tableNode.table.body.length}`);
39
- }
40
-
41
- this.rowsWithoutPageBreak = this.headerRows;
42
-
43
- const keepWithHeaderRows = tableNode.table.keepWithHeaderRows;
44
-
45
- if (isPositiveInteger(keepWithHeaderRows)) {
46
- this.rowsWithoutPageBreak += keepWithHeaderRows;
47
- }
48
- }
49
-
50
- this.dontBreakRows = tableNode.table.dontBreakRows || false;
51
-
52
- if (this.rowsWithoutPageBreak || this.dontBreakRows) {
53
- writer.beginUnbreakableBlock();
54
- // Draw the top border of the table
55
- this.drawHorizontalLine(0, writer);
56
- if (this.rowsWithoutPageBreak && this.dontBreakRows) {
57
- // We just increase the value of transactionLevel
58
- writer.beginUnbreakableBlock();
59
- }
60
- }
61
-
62
- // update the border properties of all cells before drawing any lines
63
- prepareCellBorders(this.tableNode.table.body);
64
-
65
- function getTableInnerContentWidth() {
66
- var width = 0;
67
-
68
- tableNode.table.widths.forEach(function (w) {
69
- width += w._calcWidth;
70
- });
71
-
72
- return width;
73
- }
74
-
75
- function prepareRowSpanData() {
76
- var rsd = [];
77
- var x = 0;
78
- var lastWidth = 0;
79
-
80
- rsd.push({ left: 0, rowSpan: 0 });
81
-
82
- for (var i = 0, l = self.tableNode.table.body[0].length; i < l; i++) {
83
- var paddings = self.layout.paddingLeft(i, self.tableNode) + self.layout.paddingRight(i, self.tableNode);
84
- var lBorder = self.layout.vLineWidth(i, self.tableNode);
85
- lastWidth = paddings + lBorder + self.tableNode.table.widths[i]._calcWidth;
86
- rsd[rsd.length - 1].width = lastWidth;
87
- x += lastWidth;
88
- rsd.push({ left: x, rowSpan: 0, width: 0 });
89
- }
90
-
91
- return rsd;
92
- }
93
-
94
- // Iterate through all cells. If the current cell is the start of a
95
- // rowSpan/colSpan, update the border property of the cells on its
96
- // bottom/right accordingly. This is needed since each iteration of the
97
- // line-drawing loops draws lines for a single cell, not for an entire
98
- // rowSpan/colSpan.
99
- function prepareCellBorders(body) {
100
- for (var rowIndex = 0; rowIndex < body.length; rowIndex++) {
101
- var row = body[rowIndex];
102
-
103
- for (var colIndex = 0; colIndex < row.length; colIndex++) {
104
- var cell = row[colIndex];
105
-
106
- if (cell.border) {
107
- var rowSpan = cell.rowSpan || 1;
108
- var colSpan = cell.colSpan || 1;
109
-
110
- for (var rowOffset = 0; rowOffset < rowSpan; rowOffset++) {
111
- // set left border
112
- if (cell.border[0] !== undefined && rowOffset > 0) {
113
- setBorder(rowIndex + rowOffset, colIndex, 0, cell.border[0]);
114
- }
115
-
116
- // set right border
117
- if (cell.border[2] !== undefined) {
118
- setBorder(rowIndex + rowOffset, colIndex + colSpan - 1, 2, cell.border[2]);
119
- }
120
- }
121
-
122
- for (var colOffset = 0; colOffset < colSpan; colOffset++) {
123
- // set top border
124
- if (cell.border[1] !== undefined && colOffset > 0) {
125
- setBorder(rowIndex, colIndex + colOffset, 1, cell.border[1]);
126
- }
127
-
128
- // set bottom border
129
- if (cell.border[3] !== undefined) {
130
- setBorder(rowIndex + rowSpan - 1, colIndex + colOffset, 3, cell.border[3]);
131
- }
132
- }
133
- }
134
- }
135
- }
136
-
137
- // helper function to set the border for a given cell
138
- function setBorder(rowIndex, colIndex, borderIndex, borderValue) {
139
- var cell = body[rowIndex][colIndex];
140
- cell.border = cell.border || {};
141
- cell.border[borderIndex] = borderValue;
142
- }
143
- }
144
- };
145
-
146
- TableProcessor.prototype.onRowBreak = function (rowIndex, writer) {
147
- var self = this;
148
- return function () {
149
- var offset = self.rowPaddingTop + (!self.headerRows ? self.topLineWidth : 0);
150
- writer.context().availableHeight -= self.reservedAtBottom;
151
- writer.context().moveDown(offset);
152
- };
153
- };
154
-
155
- TableProcessor.prototype.beginRow = function (rowIndex, writer) {
156
- this.topLineWidth = this.layout.hLineWidth(rowIndex, this.tableNode);
157
- this.rowPaddingTop = this.layout.paddingTop(rowIndex, this.tableNode);
158
- this.bottomLineWidth = this.layout.hLineWidth(rowIndex + 1, this.tableNode);
159
- this.rowPaddingBottom = this.layout.paddingBottom(rowIndex, this.tableNode);
160
-
161
- this.rowCallback = this.onRowBreak(rowIndex, writer);
162
- writer.tracker.startTracking('pageChanged', this.rowCallback);
163
- if (rowIndex == 0 && !this.dontBreakRows && !this.rowsWithoutPageBreak) {
164
- // We store the 'y' to draw later and if necessary the top border of the table
165
- this._tableTopBorderY = writer.context().y;
166
- writer.context().moveDown(this.topLineWidth);
167
- }
168
- if (this.dontBreakRows && rowIndex > 0) {
169
- writer.beginUnbreakableBlock();
170
- }
171
- this.rowTopY = writer.context().y;
172
- this.reservedAtBottom = this.bottomLineWidth + this.rowPaddingBottom;
173
-
174
- writer.context().availableHeight -= this.reservedAtBottom;
175
-
176
- writer.context().moveDown(this.rowPaddingTop);
177
- };
178
-
179
- TableProcessor.prototype.drawHorizontalLine = function (lineIndex, writer, overrideY, moveDown = true, forcePage) {
180
- var lineWidth = this.layout.hLineWidth(lineIndex, this.tableNode);
181
- if (lineWidth) {
182
- var style = this.layout.hLineStyle(lineIndex, this.tableNode);
183
- var dash;
184
- if (style && style.dash) {
185
- dash = style.dash;
186
- }
187
-
188
- var offset = lineWidth / 2;
189
- var currentLine = null;
190
- var body = this.tableNode.table.body;
191
- var cellAbove;
192
- var currentCell;
193
- var rowCellAbove;
194
-
195
- for (var i = 0, l = this.rowSpanData.length; i < l; i++) {
196
- var data = this.rowSpanData[i];
197
- var shouldDrawLine = !data.rowSpan;
198
- var borderColor = null;
199
-
200
- // draw only if the current cell requires a top border or the cell in the
201
- // row above requires a bottom border
202
- if (shouldDrawLine && i < l - 1) {
203
- var topBorder = false, bottomBorder = false, rowBottomBorder = false;
204
-
205
- // the cell in the row above
206
- if (lineIndex > 0) {
207
- cellAbove = body[lineIndex - 1][i];
208
- bottomBorder = cellAbove.border ? cellAbove.border[3] : this.layout.defaultBorder;
209
- if (bottomBorder && cellAbove.borderColor) {
210
- borderColor = cellAbove.borderColor[3];
211
- }
212
- }
213
-
214
- // the current cell
215
- if (lineIndex < body.length) {
216
- currentCell = body[lineIndex][i];
217
- topBorder = currentCell.border ? currentCell.border[1] : this.layout.defaultBorder;
218
- if (topBorder && borderColor == null && currentCell.borderColor) {
219
- borderColor = currentCell.borderColor[1];
220
- }
221
- }
222
-
223
- shouldDrawLine = topBorder || bottomBorder;
224
- }
225
-
226
- if (cellAbove && cellAbove._rowSpanCurrentOffset) {
227
- rowCellAbove = body[lineIndex - 1 - cellAbove._rowSpanCurrentOffset][i];
228
- rowBottomBorder = rowCellAbove && rowCellAbove.border ? rowCellAbove.border[3] : this.layout.defaultBorder;
229
- if (rowBottomBorder && rowCellAbove && rowCellAbove.borderColor) {
230
- borderColor = rowCellAbove.borderColor[3];
231
- }
232
- }
233
-
234
- if (borderColor == null) {
235
- borderColor = isFunction(this.layout.hLineColor) ? this.layout.hLineColor(lineIndex, this.tableNode, i) : this.layout.hLineColor;
236
- }
237
-
238
- if (!currentLine && shouldDrawLine) {
239
- currentLine = { left: data.left, width: 0 };
240
- }
241
-
242
- if (shouldDrawLine) {
243
- var colSpanIndex = 0;
244
- if (rowCellAbove && rowCellAbove.colSpan && rowBottomBorder) {
245
- while (rowCellAbove.colSpan > colSpanIndex) {
246
- currentLine.width += (this.rowSpanData[i + colSpanIndex++].width || 0);
247
- }
248
- i += colSpanIndex - 1;
249
- } else if (cellAbove && cellAbove.colSpan && bottomBorder) {
250
- while (cellAbove.colSpan > colSpanIndex) {
251
- currentLine.width += (this.rowSpanData[i + colSpanIndex++].width || 0);
252
- }
253
- i += colSpanIndex - 1;
254
- } else if (currentCell && currentCell.colSpan && topBorder) {
255
- while (currentCell.colSpan > colSpanIndex) {
256
- currentLine.width += (this.rowSpanData[i + colSpanIndex++].width || 0);
257
- }
258
- i += colSpanIndex - 1;
259
- } else {
260
- currentLine.width += (this.rowSpanData[i].width || 0);
261
- }
262
- }
263
-
264
- var y = (overrideY || 0) + offset;
265
-
266
-
267
- if (shouldDrawLine) {
268
- if (currentLine && currentLine.width) {
269
- writer.addVector({
270
- type: 'line',
271
- x1: currentLine.left,
272
- x2: currentLine.left + currentLine.width,
273
- y1: y,
274
- y2: y,
275
- lineWidth: lineWidth,
276
- dash: dash,
277
- lineColor: borderColor
278
- }, false, isNumber(overrideY), null, forcePage);
279
- currentLine = null;
280
- borderColor = null;
281
- cellAbove = null;
282
- currentCell = null;
283
- rowCellAbove = null;
284
- }
285
- }
286
- }
287
-
288
- if (moveDown) {
289
- writer.context().moveDown(lineWidth);
290
- }
291
- }
292
- };
293
-
294
- TableProcessor.prototype.drawVerticalLine = function (x, y0, y1, vLineColIndex, writer, vLineRowIndex, beforeVLineColIndex) {
295
- var width = this.layout.vLineWidth(vLineColIndex, this.tableNode);
296
- if (width === 0) {
297
- return;
298
- }
299
- var style = this.layout.vLineStyle(vLineColIndex, this.tableNode);
300
- var dash;
301
- if (style && style.dash) {
302
- dash = style.dash;
303
- }
304
-
305
- var body = this.tableNode.table.body;
306
- var cellBefore;
307
- var currentCell;
308
- var borderColor;
309
-
310
- // the cell in the col before
311
- if (vLineColIndex > 0) {
312
- cellBefore = body[vLineRowIndex][beforeVLineColIndex];
313
- if (cellBefore && cellBefore.borderColor) {
314
- if (cellBefore.border ? cellBefore.border[2] : this.layout.defaultBorder) {
315
- borderColor = cellBefore.borderColor[2];
316
- }
317
- }
318
- }
319
-
320
- // the current cell
321
- if (borderColor == null && vLineColIndex < body.length) {
322
- currentCell = body[vLineRowIndex][vLineColIndex];
323
- if (currentCell && currentCell.borderColor) {
324
- if (currentCell.border ? currentCell.border[0] : this.layout.defaultBorder) {
325
- borderColor = currentCell.borderColor[0];
326
- }
327
- }
328
- }
329
-
330
- if (borderColor == null && cellBefore && cellBefore._rowSpanCurrentOffset) {
331
- var rowCellBeforeAbove = body[vLineRowIndex - cellBefore._rowSpanCurrentOffset][beforeVLineColIndex];
332
- if (rowCellBeforeAbove.borderColor) {
333
- if (rowCellBeforeAbove.border ? rowCellBeforeAbove.border[2] : this.layout.defaultBorder) {
334
- borderColor = rowCellBeforeAbove.borderColor[2];
335
- }
336
- }
337
- }
338
-
339
- if (borderColor == null && currentCell && currentCell._rowSpanCurrentOffset) {
340
- var rowCurrentCellAbove = body[vLineRowIndex - currentCell._rowSpanCurrentOffset][vLineColIndex];
341
- if (rowCurrentCellAbove.borderColor) {
342
- if (rowCurrentCellAbove.border ? rowCurrentCellAbove.border[2] : this.layout.defaultBorder) {
343
- borderColor = rowCurrentCellAbove.borderColor[2];
344
- }
345
- }
346
- }
347
-
348
- if (borderColor == null) {
349
- borderColor = isFunction(this.layout.vLineColor) ? this.layout.vLineColor(vLineColIndex, this.tableNode, vLineRowIndex) : this.layout.vLineColor;
350
- }
351
- writer.addVector({
352
- type: 'line',
353
- x1: x + width / 2,
354
- x2: x + width / 2,
355
- y1: y0,
356
- y2: y1,
357
- lineWidth: width,
358
- dash: dash,
359
- lineColor: borderColor
360
- }, false, true);
361
- cellBefore = null;
362
- currentCell = null;
363
- borderColor = null;
364
- };
365
-
366
- TableProcessor.prototype.endTable = function (writer) {
367
- if (this.cleanUpRepeatables) {
368
- writer.popFromRepeatables();
369
- }
370
- };
371
-
372
- TableProcessor.prototype.endRow = function (rowIndex, writer, pageBreaks) {
373
- var l, i;
374
- var self = this;
375
- writer.tracker.stopTracking('pageChanged', this.rowCallback);
376
- writer.context().moveDown(this.layout.paddingBottom(rowIndex, this.tableNode));
377
- writer.context().availableHeight += this.reservedAtBottom;
378
-
379
- var endingPage = writer.context().page;
380
- var endingY = writer.context().y;
381
-
382
- var xs = getLineXs();
383
-
384
- var ys = [];
385
-
386
- var hasBreaks = pageBreaks && pageBreaks.length > 0;
387
- var body = this.tableNode.table.body;
388
-
389
- ys.push({
390
- y0: this.rowTopY,
391
- page: hasBreaks ? pageBreaks[0].prevPage : endingPage
392
- });
393
-
394
- if (hasBreaks) {
395
- for (i = 0, l = pageBreaks.length; i < l; i++) {
396
- var pageBreak = pageBreaks[i];
397
- ys[ys.length - 1].y1 = pageBreak.prevY;
398
-
399
- ys.push({ y0: pageBreak.y, page: pageBreak.prevPage + 1 });
400
- }
401
- }
402
-
403
- ys[ys.length - 1].y1 = endingY;
404
-
405
- var skipOrphanePadding = (ys[0].y1 - ys[0].y0 === this.rowPaddingTop);
406
- if (rowIndex === 0 && !skipOrphanePadding && !this.rowsWithoutPageBreak && !this.dontBreakRows) {
407
- // Draw the top border of the table
408
- var pageTableStartedAt = null;
409
- if (pageBreaks && pageBreaks.length > 0) {
410
- // Get the page where table started at
411
- pageTableStartedAt = pageBreaks[0].prevPage;
412
- }
413
- this.drawHorizontalLine(0, writer, this._tableTopBorderY, false, pageTableStartedAt);
414
- }
415
- for (var yi = (skipOrphanePadding ? 1 : 0), yl = ys.length; yi < yl; yi++) {
416
- var willBreak = yi < ys.length - 1;
417
- var rowBreakWithoutHeader = (yi > 0 && !this.headerRows);
418
- var hzLineOffset = rowBreakWithoutHeader ? 0 : this.topLineWidth;
419
- var y1 = ys[yi].y0;
420
- var y2 = ys[yi].y1;
421
-
422
- if (willBreak) {
423
- y2 = y2 + this.rowPaddingBottom;
424
- }
425
-
426
- if (writer.context().page != ys[yi].page) {
427
- writer.context().page = ys[yi].page;
428
-
429
- //TODO: buggy, availableHeight should be updated on every pageChanged event
430
- // TableProcessor should be pageChanged listener, instead of processRow
431
- this.reservedAtBottom = 0;
432
- }
433
-
434
- // Draw horizontal lines before the vertical lines so they are not overridden
435
- if (willBreak && this.layout.hLineWhenBroken !== false) {
436
- this.drawHorizontalLine(rowIndex + 1, writer, y2);
437
- }
438
- if (rowBreakWithoutHeader && this.layout.hLineWhenBroken !== false) {
439
- this.drawHorizontalLine(rowIndex, writer, y1);
440
- }
441
-
442
- for (i = 0, l = xs.length; i < l; i++) {
443
- var leftCellBorder = false;
444
- var rightCellBorder = false;
445
- var colIndex = xs[i].index;
446
-
447
- // current cell
448
- if (colIndex < body[rowIndex].length) {
449
- var cell = body[rowIndex][colIndex];
450
- leftCellBorder = cell.border ? cell.border[0] : this.layout.defaultBorder;
451
- rightCellBorder = cell.border ? cell.border[2] : this.layout.defaultBorder;
452
- }
453
-
454
- // before cell
455
- if (colIndex > 0 && !leftCellBorder) {
456
- var cell = body[rowIndex][colIndex - 1];
457
- leftCellBorder = cell.border ? cell.border[2] : this.layout.defaultBorder;
458
- }
459
-
460
- // after cell
461
- if (colIndex + 1 < body[rowIndex].length && !rightCellBorder) {
462
- var cell = body[rowIndex][colIndex + 1];
463
- rightCellBorder = cell.border ? cell.border[0] : this.layout.defaultBorder;
464
- }
465
-
466
- if (leftCellBorder) {
467
- this.drawVerticalLine(xs[i].x, y1 - hzLineOffset, y2 + this.bottomLineWidth, xs[i].index, writer, rowIndex, xs[i - 1] ? xs[i - 1].index : null);
468
- }
469
-
470
- if (i < l - 1) {
471
- var fillColor = body[rowIndex][colIndex].fillColor;
472
- var fillOpacity = body[rowIndex][colIndex].fillOpacity;
473
- if (!fillColor) {
474
- fillColor = isFunction(this.layout.fillColor) ? this.layout.fillColor(rowIndex, this.tableNode, colIndex) : this.layout.fillColor;
475
- }
476
- if (!isNumber(fillOpacity)) {
477
- fillOpacity = isFunction(this.layout.fillOpacity) ? this.layout.fillOpacity(rowIndex, this.tableNode, colIndex) : this.layout.fillOpacity;
478
- }
479
- var overlayPattern = body[rowIndex][colIndex].overlayPattern;
480
- var overlayOpacity = body[rowIndex][colIndex].overlayOpacity;
481
- if (fillColor || overlayPattern) {
482
- var widthLeftBorder = leftCellBorder ? this.layout.vLineWidth(colIndex, this.tableNode) : 0;
483
- var widthRightBorder;
484
- if ((colIndex === 0 || colIndex + 1 == body[rowIndex].length) && !rightCellBorder) {
485
- widthRightBorder = this.layout.vLineWidth(colIndex + 1, this.tableNode);
486
- } else if (rightCellBorder) {
487
- widthRightBorder = this.layout.vLineWidth(colIndex + 1, this.tableNode) / 2;
488
- } else {
489
- widthRightBorder = 0;
490
- }
491
-
492
- var x1f = this.dontBreakRows ? xs[i].x + widthLeftBorder : xs[i].x + (widthLeftBorder / 2);
493
- var y1f = this.dontBreakRows ? y1 : y1 - (hzLineOffset / 2);
494
- var x2f = xs[i + 1].x + widthRightBorder;
495
- var y2f = this.dontBreakRows ? y2 + this.bottomLineWidth : y2 + (this.bottomLineWidth / 2);
496
- var bgWidth = x2f - x1f;
497
- var bgHeight = y2f - y1f;
498
- if (fillColor) {
499
- writer.addVector({
500
- type: 'rect',
501
- x: x1f,
502
- y: y1f,
503
- w: bgWidth,
504
- h: bgHeight,
505
- lineWidth: 0,
506
- color: fillColor,
507
- fillOpacity: fillOpacity,
508
- // mark if we are in an unbreakable block
509
- _isFillColorFromUnbreakable: !!writer.transactionLevel
510
- }, false, true, writer.context().backgroundLength[writer.context().page]);
511
- }
512
-
513
- if (overlayPattern) {
514
- writer.addVector({
515
- type: 'rect',
516
- x: x1f,
517
- y: y1f,
518
- w: bgWidth,
519
- h: bgHeight,
520
- lineWidth: 0,
521
- color: overlayPattern,
522
- fillOpacity: overlayOpacity
523
- }, false, true);
524
- }
525
- }
526
- }
527
- }
528
- }
529
-
530
- writer.context().page = endingPage;
531
- writer.context().y = endingY;
532
-
533
- var row = this.tableNode.table.body[rowIndex];
534
- for (i = 0, l = row.length; i < l; i++) {
535
- if (row[i].rowSpan) {
536
- this.rowSpanData[i].rowSpan = row[i].rowSpan;
537
-
538
- // fix colSpans
539
- if (row[i].colSpan && row[i].colSpan > 1) {
540
- for (var j = 1; j < row[i].rowSpan; j++) {
541
- this.tableNode.table.body[rowIndex + j][i]._colSpan = row[i].colSpan;
542
- }
543
- }
544
- // fix rowSpans
545
- if (row[i].rowSpan && row[i].rowSpan > 1) {
546
- for (var j = 1; j < row[i].rowSpan; j++) {
547
- this.tableNode.table.body[rowIndex + j][i]._rowSpanCurrentOffset = j;
548
- }
549
- }
550
- }
551
-
552
- if (this.rowSpanData[i].rowSpan > 0) {
553
- this.rowSpanData[i].rowSpan--;
554
- }
555
- }
556
-
557
- this.drawHorizontalLine(rowIndex + 1, writer);
558
-
559
- if (this.headerRows && rowIndex === this.headerRows - 1) {
560
- this.headerRepeatable = writer.currentBlockToRepeatable();
561
- }
562
-
563
- if (this.dontBreakRows) {
564
- writer.tracker.auto('pageChanged',
565
- function () {
566
- if (rowIndex > 0 && !self.headerRows && self.layout.hLineWhenBroken !== false) {
567
- // Draw the top border of the row after a page break
568
- self.drawHorizontalLine(rowIndex, writer);
569
- }
570
- },
571
- function () {
572
- writer.commitUnbreakableBlock();
573
- }
574
- );
575
- }
576
-
577
- if (this.headerRepeatable && (rowIndex === (this.rowsWithoutPageBreak - 1) || rowIndex === this.tableNode.table.body.length - 1)) {
578
- writer.commitUnbreakableBlock();
579
- writer.pushToRepeatables(this.headerRepeatable);
580
- this.cleanUpRepeatables = true;
581
- this.headerRepeatable = null;
582
- }
583
-
584
- function getLineXs() {
585
- var result = [];
586
- var cols = 0;
587
-
588
- for (var i = 0, l = self.tableNode.table.body[rowIndex].length; i < l; i++) {
589
- if (!cols) {
590
- result.push({ x: self.rowSpanData[i].left, index: i });
591
-
592
- var item = self.tableNode.table.body[rowIndex][i];
593
- cols = (item._colSpan || item.colSpan || 0);
594
- }
595
- if (cols > 0) {
596
- cols--;
597
- }
598
- }
599
-
600
- result.push({ x: self.rowSpanData[self.rowSpanData.length - 1].left, index: self.rowSpanData.length - 1 });
601
-
602
- return result;
603
- }
604
- };
605
-
606
- module.exports = TableProcessor;
1
+ import ColumnCalculator from './columnCalculator';
2
+ import { isNumber, isPositiveInteger } from './helpers/variableType';
3
+
4
+ class TableProcessor {
5
+ constructor(tableNode) {
6
+ this.tableNode = tableNode;
7
+ }
8
+
9
+ beginTable(writer) {
10
+ const getTableInnerContentWidth = () => {
11
+ let width = 0;
12
+
13
+ tableNode.table.widths.forEach(w => {
14
+ width += w._calcWidth;
15
+ });
16
+
17
+ return width;
18
+ };
19
+
20
+ const prepareRowSpanData = () => {
21
+ let rsd = [];
22
+ let x = 0;
23
+ let lastWidth = 0;
24
+
25
+ rsd.push({ left: 0, rowSpan: 0 });
26
+
27
+ for (let i = 0, l = this.tableNode.table.body[0].length; i < l; i++) {
28
+ let paddings = this.layout.paddingLeft(i, this.tableNode) + this.layout.paddingRight(i, this.tableNode);
29
+ let lBorder = this.layout.vLineWidth(i, this.tableNode);
30
+ lastWidth = paddings + lBorder + this.tableNode.table.widths[i]._calcWidth;
31
+ rsd[rsd.length - 1].width = lastWidth;
32
+ x += lastWidth;
33
+ rsd.push({ left: x, rowSpan: 0, width: 0 });
34
+ }
35
+
36
+ return rsd;
37
+ };
38
+
39
+ // Iterate through all cells. If the current cell is the start of a
40
+ // rowSpan/colSpan, update the border property of the cells on its
41
+ // bottom/right accordingly. This is needed since each iteration of the
42
+ // line-drawing loops draws lines for a single cell, not for an entire
43
+ // rowSpan/colSpan.
44
+ const prepareCellBorders = body => {
45
+ for (let rowIndex = 0; rowIndex < body.length; rowIndex++) {
46
+ let row = body[rowIndex];
47
+
48
+ for (let colIndex = 0; colIndex < row.length; colIndex++) {
49
+ let cell = row[colIndex];
50
+
51
+ if (cell.border) {
52
+ let rowSpan = cell.rowSpan || 1;
53
+ let colSpan = cell.colSpan || 1;
54
+
55
+ for (let rowOffset = 0; rowOffset < rowSpan; rowOffset++) {
56
+ // set left border
57
+ if (cell.border[0] !== undefined && rowOffset > 0) {
58
+ setBorder(rowIndex + rowOffset, colIndex, 0, cell.border[0]);
59
+ }
60
+
61
+ // set right border
62
+ if (cell.border[2] !== undefined) {
63
+ setBorder(rowIndex + rowOffset, colIndex + colSpan - 1, 2, cell.border[2]);
64
+ }
65
+ }
66
+
67
+ for (let colOffset = 0; colOffset < colSpan; colOffset++) {
68
+ // set top border
69
+ if (cell.border[1] !== undefined && colOffset > 0) {
70
+ setBorder(rowIndex, colIndex + colOffset, 1, cell.border[1]);
71
+ }
72
+
73
+ // set bottom border
74
+ if (cell.border[3] !== undefined) {
75
+ setBorder(rowIndex + rowSpan - 1, colIndex + colOffset, 3, cell.border[3]);
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ // helper function to set the border for a given cell
83
+ function setBorder(rowIndex, colIndex, borderIndex, borderValue) {
84
+ let cell = body[rowIndex][colIndex];
85
+ cell.border = cell.border || {};
86
+ cell.border[borderIndex] = borderValue;
87
+ }
88
+ };
89
+
90
+ let tableNode;
91
+ let availableWidth;
92
+
93
+ tableNode = this.tableNode;
94
+ this.offsets = tableNode._offsets;
95
+ this.layout = tableNode._layout;
96
+
97
+ availableWidth = writer.context().availableWidth - this.offsets.total;
98
+ ColumnCalculator.buildColumnWidths(tableNode.table.widths, availableWidth, this.offsets.total, tableNode);
99
+
100
+ this.tableWidth = tableNode._offsets.total + getTableInnerContentWidth();
101
+ this.rowSpanData = prepareRowSpanData();
102
+ this.cleanUpRepeatables = false;
103
+
104
+ // headersRows and rowsWithoutPageBreak (headerRows + keepWithHeaderRows)
105
+ this.headerRows = 0;
106
+ this.rowsWithoutPageBreak = 0;
107
+
108
+ const headerRows = tableNode.table.headerRows;
109
+
110
+ if (isPositiveInteger(headerRows)) {
111
+ this.headerRows = headerRows;
112
+
113
+ if (this.headerRows > tableNode.table.body.length) {
114
+ throw new Error(`Too few rows in the table. Property headerRows requires at least ${this.headerRows}, contains only ${tableNode.table.body.length}`);
115
+ }
116
+
117
+ this.rowsWithoutPageBreak = this.headerRows;
118
+
119
+ const keepWithHeaderRows = tableNode.table.keepWithHeaderRows;
120
+
121
+ if (isPositiveInteger(keepWithHeaderRows)) {
122
+ this.rowsWithoutPageBreak += keepWithHeaderRows;
123
+ }
124
+ }
125
+
126
+ this.dontBreakRows = tableNode.table.dontBreakRows || false;
127
+
128
+ if (this.rowsWithoutPageBreak || this.dontBreakRows) {
129
+ writer.beginUnbreakableBlock();
130
+ // Draw the top border of the table
131
+ this.drawHorizontalLine(0, writer);
132
+ if (this.rowsWithoutPageBreak && this.dontBreakRows) {
133
+ // We just increase the value of transactionLevel
134
+ writer.beginUnbreakableBlock();
135
+ }
136
+ }
137
+
138
+ // update the border properties of all cells before drawing any lines
139
+ prepareCellBorders(this.tableNode.table.body);
140
+ }
141
+
142
+ onRowBreak(rowIndex, writer) {
143
+ return () => {
144
+ let offset = this.rowPaddingTop + (!this.headerRows ? this.topLineWidth : 0);
145
+ writer.context().availableHeight -= this.reservedAtBottom;
146
+ writer.context().moveDown(offset);
147
+ };
148
+ }
149
+
150
+ beginRow(rowIndex, writer) {
151
+ this.topLineWidth = this.layout.hLineWidth(rowIndex, this.tableNode);
152
+ this.rowPaddingTop = this.layout.paddingTop(rowIndex, this.tableNode);
153
+ this.bottomLineWidth = this.layout.hLineWidth(rowIndex + 1, this.tableNode);
154
+ this.rowPaddingBottom = this.layout.paddingBottom(rowIndex, this.tableNode);
155
+
156
+ this.rowCallback = this.onRowBreak(rowIndex, writer);
157
+ writer.addListener('pageChanged', this.rowCallback);
158
+ if (rowIndex == 0 && !this.dontBreakRows && !this.rowsWithoutPageBreak) {
159
+ // We store the 'y' to draw later and if necessary the top border of the table
160
+ this._tableTopBorderY = writer.context().y;
161
+ writer.context().moveDown(this.topLineWidth);
162
+ }
163
+
164
+ this.rowTopPageY = writer.context().y + this.rowPaddingTop;
165
+
166
+ if (this.dontBreakRows && rowIndex > 0) {
167
+ writer.beginUnbreakableBlock();
168
+ }
169
+ this.rowTopY = writer.context().y;
170
+ this.reservedAtBottom = this.bottomLineWidth + this.rowPaddingBottom;
171
+
172
+ writer.context().availableHeight -= this.reservedAtBottom;
173
+
174
+ writer.context().moveDown(this.rowPaddingTop);
175
+ }
176
+
177
+ drawHorizontalLine(lineIndex, writer, overrideY, moveDown = true, forcePage) {
178
+ let lineWidth = this.layout.hLineWidth(lineIndex, this.tableNode);
179
+ if (lineWidth) {
180
+ let style = this.layout.hLineStyle(lineIndex, this.tableNode);
181
+ let dash;
182
+ if (style && style.dash) {
183
+ dash = style.dash;
184
+ }
185
+
186
+ let offset = lineWidth / 2;
187
+ let currentLine = null;
188
+ let body = this.tableNode.table.body;
189
+ let cellAbove;
190
+ let currentCell;
191
+ let rowCellAbove;
192
+
193
+ for (let i = 0, l = this.rowSpanData.length; i < l; i++) {
194
+ let data = this.rowSpanData[i];
195
+ let shouldDrawLine = !data.rowSpan;
196
+ let borderColor = null;
197
+
198
+ // draw only if the current cell requires a top border or the cell in the
199
+ // row above requires a bottom border
200
+ if (shouldDrawLine && i < l - 1) {
201
+ var topBorder = false, bottomBorder = false, rowBottomBorder = false;
202
+
203
+ // the cell in the row above
204
+ if (lineIndex > 0) {
205
+ cellAbove = body[lineIndex - 1][i];
206
+ bottomBorder = cellAbove.border ? cellAbove.border[3] : this.layout.defaultBorder;
207
+ if (bottomBorder && cellAbove.borderColor) {
208
+ borderColor = cellAbove.borderColor[3];
209
+ }
210
+ }
211
+
212
+ // the current cell
213
+ if (lineIndex < body.length) {
214
+ currentCell = body[lineIndex][i];
215
+ topBorder = currentCell.border ? currentCell.border[1] : this.layout.defaultBorder;
216
+ if (topBorder && borderColor == null && currentCell.borderColor) {
217
+ borderColor = currentCell.borderColor[1];
218
+ }
219
+ }
220
+
221
+ shouldDrawLine = topBorder || bottomBorder;
222
+ }
223
+
224
+ if (cellAbove && cellAbove._rowSpanCurrentOffset) {
225
+ rowCellAbove = body[lineIndex - 1 - cellAbove._rowSpanCurrentOffset][i];
226
+ rowBottomBorder = rowCellAbove && rowCellAbove.border ? rowCellAbove.border[3] : this.layout.defaultBorder;
227
+ if (rowBottomBorder && rowCellAbove && rowCellAbove.borderColor) {
228
+ borderColor = rowCellAbove.borderColor[3];
229
+ }
230
+ }
231
+
232
+ if (borderColor == null) {
233
+ borderColor = typeof this.layout.hLineColor === 'function' ? this.layout.hLineColor(lineIndex, this.tableNode, i) : this.layout.hLineColor;
234
+ }
235
+
236
+ if (!currentLine && shouldDrawLine) {
237
+ currentLine = { left: data.left, width: 0 };
238
+ }
239
+
240
+ if (shouldDrawLine) {
241
+ let colSpanIndex = 0;
242
+ if (rowCellAbove && rowCellAbove.colSpan && rowBottomBorder) {
243
+ while (rowCellAbove.colSpan > colSpanIndex) {
244
+ currentLine.width += (this.rowSpanData[i + colSpanIndex++].width || 0);
245
+ }
246
+ i += colSpanIndex - 1;
247
+ } else if (cellAbove && cellAbove.colSpan && bottomBorder) {
248
+ while (cellAbove.colSpan > colSpanIndex) {
249
+ currentLine.width += (this.rowSpanData[i + colSpanIndex++].width || 0);
250
+ }
251
+ i += colSpanIndex - 1;
252
+ } else if (currentCell && currentCell.colSpan && topBorder) {
253
+ while (currentCell.colSpan > colSpanIndex) {
254
+ currentLine.width += (this.rowSpanData[i + colSpanIndex++].width || 0);
255
+ }
256
+ i += colSpanIndex - 1;
257
+ } else {
258
+ currentLine.width += (this.rowSpanData[i].width || 0);
259
+ }
260
+ }
261
+
262
+ let y = (overrideY || 0) + offset;
263
+
264
+ if (shouldDrawLine) {
265
+ if (currentLine && currentLine.width) {
266
+ writer.addVector({
267
+ type: 'line',
268
+ x1: currentLine.left,
269
+ x2: currentLine.left + currentLine.width,
270
+ y1: y,
271
+ y2: y,
272
+ lineWidth: lineWidth,
273
+ dash: dash,
274
+ lineColor: borderColor
275
+ }, false, isNumber(overrideY), null, forcePage);
276
+ currentLine = null;
277
+ borderColor = null;
278
+ cellAbove = null;
279
+ currentCell = null;
280
+ rowCellAbove = null;
281
+ }
282
+ }
283
+ }
284
+
285
+ if (moveDown) {
286
+ writer.context().moveDown(lineWidth);
287
+ }
288
+ }
289
+ }
290
+
291
+ drawVerticalLine(x, y0, y1, vLineColIndex, writer, vLineRowIndex, beforeVLineColIndex) {
292
+ let width = this.layout.vLineWidth(vLineColIndex, this.tableNode);
293
+ if (width === 0) {
294
+ return;
295
+ }
296
+ let style = this.layout.vLineStyle(vLineColIndex, this.tableNode);
297
+ let dash;
298
+ if (style && style.dash) {
299
+ dash = style.dash;
300
+ }
301
+
302
+ let body = this.tableNode.table.body;
303
+ let cellBefore;
304
+ let currentCell;
305
+ let borderColor;
306
+
307
+ // the cell in the col before
308
+ if (vLineColIndex > 0) {
309
+ cellBefore = body[vLineRowIndex][beforeVLineColIndex];
310
+ if (cellBefore && cellBefore.borderColor) {
311
+ if (cellBefore.border ? cellBefore.border[2] : this.layout.defaultBorder) {
312
+ borderColor = cellBefore.borderColor[2];
313
+ }
314
+ }
315
+ }
316
+
317
+ // the current cell
318
+ if (borderColor == null && vLineColIndex < body.length) {
319
+ currentCell = body[vLineRowIndex][vLineColIndex];
320
+ if (currentCell && currentCell.borderColor) {
321
+ if (currentCell.border ? currentCell.border[0] : this.layout.defaultBorder) {
322
+ borderColor = currentCell.borderColor[0];
323
+ }
324
+ }
325
+ }
326
+
327
+ if (borderColor == null && cellBefore && cellBefore._rowSpanCurrentOffset) {
328
+ let rowCellBeforeAbove = body[vLineRowIndex - cellBefore._rowSpanCurrentOffset][beforeVLineColIndex];
329
+ if (rowCellBeforeAbove.borderColor) {
330
+ if (rowCellBeforeAbove.border ? rowCellBeforeAbove.border[2] : this.layout.defaultBorder) {
331
+ borderColor = rowCellBeforeAbove.borderColor[2];
332
+ }
333
+ }
334
+ }
335
+
336
+ if (borderColor == null && currentCell && currentCell._rowSpanCurrentOffset) {
337
+ let rowCurrentCellAbove = body[vLineRowIndex - currentCell._rowSpanCurrentOffset][vLineColIndex];
338
+ if (rowCurrentCellAbove.borderColor) {
339
+ if (rowCurrentCellAbove.border ? rowCurrentCellAbove.border[2] : this.layout.defaultBorder) {
340
+ borderColor = rowCurrentCellAbove.borderColor[2];
341
+ }
342
+ }
343
+ }
344
+
345
+ if (borderColor == null) {
346
+ borderColor = typeof this.layout.vLineColor === 'function' ? this.layout.vLineColor(vLineColIndex, this.tableNode, vLineRowIndex) : this.layout.vLineColor;
347
+ }
348
+
349
+ writer.addVector({
350
+ type: 'line',
351
+ x1: x + width / 2,
352
+ x2: x + width / 2,
353
+ y1: y0,
354
+ y2: y1,
355
+ lineWidth: width,
356
+ dash: dash,
357
+ lineColor: borderColor
358
+ }, false, true);
359
+ cellBefore = null;
360
+ currentCell = null;
361
+ borderColor = null;
362
+ }
363
+
364
+ endTable(writer) {
365
+ if (this.cleanUpRepeatables) {
366
+ writer.popFromRepeatables();
367
+ }
368
+ }
369
+
370
+ endRow(rowIndex, writer, pageBreaks) {
371
+ const getLineXs = () => {
372
+ let result = [];
373
+ let cols = 0;
374
+
375
+ for (let i = 0, l = this.tableNode.table.body[rowIndex].length; i < l; i++) {
376
+ if (!cols) {
377
+ result.push({ x: this.rowSpanData[i].left, index: i });
378
+
379
+ let item = this.tableNode.table.body[rowIndex][i];
380
+ cols = (item._colSpan || item.colSpan || 0);
381
+ }
382
+ if (cols > 0) {
383
+ cols--;
384
+ }
385
+ }
386
+
387
+ result.push({ x: this.rowSpanData[this.rowSpanData.length - 1].left, index: this.rowSpanData.length - 1 });
388
+
389
+ return result;
390
+ };
391
+
392
+ writer.removeListener('pageChanged', this.rowCallback);
393
+ writer.context().moveDown(this.layout.paddingBottom(rowIndex, this.tableNode));
394
+ writer.context().availableHeight += this.reservedAtBottom;
395
+
396
+ let endingPage = writer.context().page;
397
+ let endingY = writer.context().y;
398
+
399
+ let xs = getLineXs();
400
+
401
+ let ys = [];
402
+
403
+ let hasBreaks = pageBreaks && pageBreaks.length > 0;
404
+ let body = this.tableNode.table.body;
405
+
406
+ ys.push({
407
+ y0: this.rowTopY,
408
+ page: hasBreaks ? pageBreaks[0].prevPage : endingPage
409
+ });
410
+
411
+ if (hasBreaks) {
412
+ for (let i = 0, l = pageBreaks.length; i < l; i++) {
413
+ let pageBreak = pageBreaks[i];
414
+ ys[ys.length - 1].y1 = pageBreak.prevY;
415
+
416
+ ys.push({ y0: pageBreak.y, page: pageBreak.prevPage + 1 });
417
+ }
418
+ }
419
+
420
+ ys[ys.length - 1].y1 = endingY;
421
+
422
+ let skipOrphanePadding = (ys[0].y1 - ys[0].y0 === this.rowPaddingTop);
423
+ if (rowIndex === 0 && !skipOrphanePadding && !this.rowsWithoutPageBreak && !this.dontBreakRows) {
424
+ // Draw the top border of the table
425
+ let pageTableStartedAt = null;
426
+ if (pageBreaks && pageBreaks.length > 0) {
427
+ // Get the page where table started at
428
+ pageTableStartedAt = pageBreaks[0].prevPage;
429
+ }
430
+ this.drawHorizontalLine(0, writer, this._tableTopBorderY, false, pageTableStartedAt);
431
+ }
432
+ for (let yi = (skipOrphanePadding ? 1 : 0), yl = ys.length; yi < yl; yi++) {
433
+ let willBreak = yi < ys.length - 1;
434
+ let rowBreakWithoutHeader = (yi > 0 && !this.headerRows);
435
+ let hzLineOffset = rowBreakWithoutHeader ? 0 : this.topLineWidth;
436
+ let y1 = ys[yi].y0;
437
+ let y2 = ys[yi].y1;
438
+
439
+ if (willBreak) {
440
+ y2 = y2 + this.rowPaddingBottom;
441
+ }
442
+
443
+ if (writer.context().page != ys[yi].page) {
444
+ writer.context().page = ys[yi].page;
445
+
446
+ //TODO: buggy, availableHeight should be updated on every pageChanged event
447
+ // TableProcessor should be pageChanged listener, instead of processRow
448
+ this.reservedAtBottom = 0;
449
+ }
450
+
451
+ // Draw horizontal lines before the vertical lines so they are not overridden
452
+ if (willBreak && this.layout.hLineWhenBroken !== false) {
453
+ this.drawHorizontalLine(rowIndex + 1, writer, y2);
454
+ }
455
+ if (rowBreakWithoutHeader && this.layout.hLineWhenBroken !== false) {
456
+ this.drawHorizontalLine(rowIndex, writer, y1);
457
+ }
458
+
459
+ for (let i = 0, l = xs.length; i < l; i++) {
460
+ let leftCellBorder = false;
461
+ let rightCellBorder = false;
462
+ let colIndex = xs[i].index;
463
+
464
+ // current cell
465
+ if (colIndex < body[rowIndex].length) {
466
+ let cell = body[rowIndex][colIndex];
467
+ leftCellBorder = cell.border ? cell.border[0] : this.layout.defaultBorder;
468
+ rightCellBorder = cell.border ? cell.border[2] : this.layout.defaultBorder;
469
+ }
470
+
471
+ // before cell
472
+ if (colIndex > 0 && !leftCellBorder) {
473
+ let cell = body[rowIndex][colIndex - 1];
474
+ leftCellBorder = cell.border ? cell.border[2] : this.layout.defaultBorder;
475
+ }
476
+
477
+ // after cell
478
+ if (colIndex + 1 < body[rowIndex].length && !rightCellBorder) {
479
+ let cell = body[rowIndex][colIndex + 1];
480
+ rightCellBorder = cell.border ? cell.border[0] : this.layout.defaultBorder;
481
+ }
482
+
483
+ if (leftCellBorder) {
484
+ this.drawVerticalLine(xs[i].x, y1 - hzLineOffset, y2 + this.bottomLineWidth, xs[i].index, writer, rowIndex, xs[i - 1] ? xs[i - 1].index : null);
485
+ }
486
+
487
+ if (i < l - 1) {
488
+ body[rowIndex][colIndex]._willBreak = body[rowIndex][colIndex]._willBreak ?? willBreak;
489
+ if (body[rowIndex][colIndex]._bottomY === undefined) {
490
+ let bottomY = this.dontBreakRows ? y2 + this.bottomLineWidth : y2 + (this.bottomLineWidth / 2);
491
+ if (willBreak || this.dontBreakRows) {
492
+ bottomY = bottomY - this.rowPaddingBottom;
493
+ }
494
+ body[rowIndex][colIndex]._bottomY = bottomY - this.reservedAtBottom;
495
+ }
496
+ body[rowIndex][colIndex]._rowTopPageY = this.rowTopPageY;
497
+ if (this.dontBreakRows) {
498
+ body[rowIndex][colIndex]._rowTopPageYPadding = this.rowPaddingTop;
499
+ }
500
+
501
+ body[rowIndex][colIndex]._lastPageNumber = ys[yi].page + 1;
502
+
503
+ let fillColor = body[rowIndex][colIndex].fillColor;
504
+ let fillOpacity = body[rowIndex][colIndex].fillOpacity;
505
+ if (!fillColor) {
506
+ fillColor = typeof this.layout.fillColor === 'function' ? this.layout.fillColor(rowIndex, this.tableNode, colIndex) : this.layout.fillColor;
507
+ }
508
+ if (!isNumber(fillOpacity)) {
509
+ fillOpacity = typeof this.layout.fillOpacity === 'function' ? this.layout.fillOpacity(rowIndex, this.tableNode, colIndex) : this.layout.fillOpacity;
510
+ }
511
+ var overlayPattern = body[rowIndex][colIndex].overlayPattern;
512
+ var overlayOpacity = body[rowIndex][colIndex].overlayOpacity;
513
+ if (fillColor || overlayPattern) {
514
+ let widthLeftBorder = leftCellBorder ? this.layout.vLineWidth(colIndex, this.tableNode) : 0;
515
+ let widthRightBorder;
516
+ if ((colIndex === 0 || colIndex + 1 == body[rowIndex].length) && !rightCellBorder) {
517
+ widthRightBorder = this.layout.vLineWidth(colIndex + 1, this.tableNode);
518
+ } else if (rightCellBorder) {
519
+ widthRightBorder = this.layout.vLineWidth(colIndex + 1, this.tableNode) / 2;
520
+ } else {
521
+ widthRightBorder = 0;
522
+ }
523
+
524
+ let x1f = this.dontBreakRows ? xs[i].x + widthLeftBorder : xs[i].x + (widthLeftBorder / 2);
525
+ let y1f = this.dontBreakRows ? y1 : y1 - (hzLineOffset / 2);
526
+ let x2f = xs[i + 1].x + widthRightBorder;
527
+ let y2f = this.dontBreakRows ? y2 + this.bottomLineWidth : y2 + (this.bottomLineWidth / 2);
528
+ var bgWidth = x2f - x1f;
529
+ var bgHeight = y2f - y1f;
530
+ if (fillColor) {
531
+ writer.addVector({
532
+ type: 'rect',
533
+ x: x1f,
534
+ y: y1f,
535
+ w: bgWidth,
536
+ h: bgHeight,
537
+ lineWidth: 0,
538
+ color: fillColor,
539
+ fillOpacity: fillOpacity,
540
+ // mark if we are in an unbreakable block
541
+ _isFillColorFromUnbreakable: !!writer.transactionLevel
542
+ }, false, true, writer.context().backgroundLength[writer.context().page]);
543
+ }
544
+
545
+ if (overlayPattern) {
546
+ writer.addVector({
547
+ type: 'rect',
548
+ x: x1f,
549
+ y: y1f,
550
+ w: bgWidth,
551
+ h: bgHeight,
552
+ lineWidth: 0,
553
+ color: overlayPattern,
554
+ fillOpacity: overlayOpacity
555
+ }, false, true);
556
+ }
557
+ }
558
+ }
559
+ }
560
+ }
561
+
562
+ writer.context().page = endingPage;
563
+ writer.context().y = endingY;
564
+
565
+ let row = this.tableNode.table.body[rowIndex];
566
+ for (let i = 0, l = row.length; i < l; i++) {
567
+ if (row[i].rowSpan) {
568
+ this.rowSpanData[i].rowSpan = row[i].rowSpan;
569
+
570
+ // fix colSpans
571
+ if (row[i].colSpan && row[i].colSpan > 1) {
572
+ for (let j = 1; j < row[i].rowSpan; j++) {
573
+ this.tableNode.table.body[rowIndex + j][i]._colSpan = row[i].colSpan;
574
+ }
575
+ }
576
+
577
+ // fix rowSpans
578
+ if (row[i].rowSpan && row[i].rowSpan > 1) {
579
+ for (let j = 1; j < row[i].rowSpan; j++) {
580
+ this.tableNode.table.body[rowIndex + j][i]._rowSpanCurrentOffset = j;
581
+ }
582
+ }
583
+ }
584
+
585
+ if (this.rowSpanData[i].rowSpan > 0) {
586
+ this.rowSpanData[i].rowSpan--;
587
+ }
588
+ }
589
+
590
+ this.drawHorizontalLine(rowIndex + 1, writer);
591
+
592
+ if (this.headerRows && rowIndex === this.headerRows - 1) {
593
+ this.headerRepeatable = writer.currentBlockToRepeatable();
594
+ }
595
+
596
+ if (this.dontBreakRows) {
597
+ const pageChangedCallback = () => {
598
+ if (rowIndex > 0 && !this.headerRows && this.layout.hLineWhenBroken !== false) {
599
+ // Draw the top border of the row after a page break
600
+ this.drawHorizontalLine(rowIndex, writer);
601
+ }
602
+ };
603
+
604
+ writer.addListener('pageChanged', pageChangedCallback);
605
+
606
+ writer.commitUnbreakableBlock();
607
+
608
+ writer.removeListener('pageChanged', pageChangedCallback);
609
+ }
610
+
611
+ if (this.headerRepeatable && (rowIndex === (this.rowsWithoutPageBreak - 1) || rowIndex === this.tableNode.table.body.length - 1)) {
612
+ writer.commitUnbreakableBlock();
613
+ writer.pushToRepeatables(this.headerRepeatable);
614
+ this.cleanUpRepeatables = true;
615
+ this.headerRepeatable = null;
616
+ }
617
+ }
618
+ }
619
+
620
+ export default TableProcessor;