pdfmake 0.3.3 → 0.3.5

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 (93) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/LICENSE +21 -21
  3. package/README.md +76 -78
  4. package/build/fonts/Roboto/Roboto-Italic.ttf +0 -0
  5. package/build/fonts/Roboto/Roboto-Medium.ttf +0 -0
  6. package/build/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
  7. package/build/fonts/Roboto/Roboto-Regular.ttf +0 -0
  8. package/build/fonts/Roboto.js +27 -0
  9. package/build/pdfmake.js +65042 -64408
  10. package/build/pdfmake.js.map +1 -1
  11. package/build/pdfmake.min.js +2 -2
  12. package/build/pdfmake.min.js.map +1 -1
  13. package/build/standard-fonts/Courier.js +27 -27
  14. package/build/standard-fonts/Helvetica.js +27 -27
  15. package/build/standard-fonts/Symbol.js +21 -21
  16. package/build/standard-fonts/Times.js +27 -27
  17. package/build/standard-fonts/ZapfDingbats.js +21 -21
  18. package/build/vfs_fonts.js +5 -5
  19. package/build-vfs.js +44 -44
  20. package/fonts/Roboto.js +8 -8
  21. package/js/DocMeasure.js +9 -6
  22. package/js/DocumentContext.js +236 -7
  23. package/js/ElementWriter.js +42 -16
  24. package/js/LayoutBuilder.js +277 -86
  25. package/js/Line.js +16 -16
  26. package/js/OutputDocument.js +10 -10
  27. package/js/OutputDocumentServer.js +3 -3
  28. package/js/PDFDocument.js +6 -4
  29. package/js/PageElementWriter.js +124 -11
  30. package/js/Printer.js +28 -28
  31. package/js/Renderer.js +53 -8
  32. package/js/SVGMeasure.js +14 -12
  33. package/js/StyleContextStack.js +48 -48
  34. package/js/TableProcessor.js +15 -5
  35. package/js/TextBreaker.js +17 -17
  36. package/js/TextInlines.js +33 -33
  37. package/js/URLResolver.js +3 -1
  38. package/js/base.js +4 -4
  39. package/js/browser-extensions/OutputDocumentBrowser.js +24 -24
  40. package/js/columnCalculator.js +2 -2
  41. package/js/helpers/node.js +14 -15
  42. package/js/helpers/variableType.js +18 -18
  43. package/js/qrEnc.js +38 -38
  44. package/js/virtual-fs.js +11 -11
  45. package/package.json +10 -10
  46. package/src/3rd-party/svg-to-pdfkit/LICENSE +9 -9
  47. package/src/3rd-party/svg-to-pdfkit/source.js +2745 -2745
  48. package/src/3rd-party/svg-to-pdfkit.js +3 -3
  49. package/src/DocMeasure.js +749 -745
  50. package/src/DocPreprocessor.js +283 -283
  51. package/src/DocumentContext.js +579 -338
  52. package/src/ElementWriter.js +441 -417
  53. package/src/LayoutBuilder.js +1470 -1262
  54. package/src/Line.js +114 -114
  55. package/src/OutputDocument.js +64 -64
  56. package/src/OutputDocumentServer.js +32 -32
  57. package/src/PDFDocument.js +174 -174
  58. package/src/PageElementWriter.js +306 -179
  59. package/src/PageSize.js +53 -53
  60. package/src/Printer.js +306 -306
  61. package/src/Renderer.js +458 -409
  62. package/src/SVGMeasure.js +109 -109
  63. package/src/StyleContextStack.js +208 -208
  64. package/src/TableProcessor.js +616 -602
  65. package/src/TextBreaker.js +168 -168
  66. package/src/TextDecorator.js +175 -175
  67. package/src/TextInlines.js +224 -224
  68. package/src/URLResolver.js +43 -43
  69. package/src/base.js +70 -70
  70. package/src/browser-extensions/OutputDocumentBrowser.js +80 -80
  71. package/src/browser-extensions/fonts/Roboto.js +27 -27
  72. package/src/browser-extensions/index.js +55 -55
  73. package/src/browser-extensions/pdfMake.js +1 -1
  74. package/src/browser-extensions/standard-fonts/Courier.js +27 -27
  75. package/src/browser-extensions/standard-fonts/Helvetica.js +27 -27
  76. package/src/browser-extensions/standard-fonts/Symbol.js +21 -21
  77. package/src/browser-extensions/standard-fonts/Times.js +27 -27
  78. package/src/browser-extensions/standard-fonts/ZapfDingbats.js +21 -21
  79. package/src/browser-extensions/virtual-fs-cjs.js +1 -1
  80. package/src/columnCalculator.js +154 -154
  81. package/src/helpers/node.js +134 -136
  82. package/src/helpers/tools.js +44 -44
  83. package/src/helpers/variableType.js +50 -50
  84. package/src/index.js +16 -16
  85. package/src/qrEnc.js +796 -796
  86. package/src/standardPageSizes.js +52 -52
  87. package/src/tableLayouts.js +100 -100
  88. package/src/virtual-fs.js +66 -66
  89. package/standard-fonts/Courier.js +8 -8
  90. package/standard-fonts/Helvetica.js +8 -8
  91. package/standard-fonts/Symbol.js +5 -5
  92. package/standard-fonts/Times.js +8 -8
  93. package/standard-fonts/ZapfDingbats.js +5 -5
@@ -1,602 +1,616 @@
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
- if (this.dontBreakRows && rowIndex > 0) {
164
- writer.beginUnbreakableBlock();
165
- }
166
- this.rowTopY = writer.context().y;
167
- this.reservedAtBottom = this.bottomLineWidth + this.rowPaddingBottom;
168
-
169
- writer.context().availableHeight -= this.reservedAtBottom;
170
-
171
- writer.context().moveDown(this.rowPaddingTop);
172
- }
173
-
174
- drawHorizontalLine(lineIndex, writer, overrideY, moveDown = true, forcePage) {
175
- let lineWidth = this.layout.hLineWidth(lineIndex, this.tableNode);
176
- if (lineWidth) {
177
- let style = this.layout.hLineStyle(lineIndex, this.tableNode);
178
- let dash;
179
- if (style && style.dash) {
180
- dash = style.dash;
181
- }
182
-
183
- let offset = lineWidth / 2;
184
- let currentLine = null;
185
- let body = this.tableNode.table.body;
186
- let cellAbove;
187
- let currentCell;
188
- let rowCellAbove;
189
-
190
- for (let i = 0, l = this.rowSpanData.length; i < l; i++) {
191
- let data = this.rowSpanData[i];
192
- let shouldDrawLine = !data.rowSpan;
193
- let borderColor = null;
194
-
195
- // draw only if the current cell requires a top border or the cell in the
196
- // row above requires a bottom border
197
- if (shouldDrawLine && i < l - 1) {
198
- var topBorder = false, bottomBorder = false, rowBottomBorder = false;
199
-
200
- // the cell in the row above
201
- if (lineIndex > 0) {
202
- cellAbove = body[lineIndex - 1][i];
203
- bottomBorder = cellAbove.border ? cellAbove.border[3] : this.layout.defaultBorder;
204
- if (bottomBorder && cellAbove.borderColor) {
205
- borderColor = cellAbove.borderColor[3];
206
- }
207
- }
208
-
209
- // the current cell
210
- if (lineIndex < body.length) {
211
- currentCell = body[lineIndex][i];
212
- topBorder = currentCell.border ? currentCell.border[1] : this.layout.defaultBorder;
213
- if (topBorder && borderColor == null && currentCell.borderColor) {
214
- borderColor = currentCell.borderColor[1];
215
- }
216
- }
217
-
218
- shouldDrawLine = topBorder || bottomBorder;
219
- }
220
-
221
- if (cellAbove && cellAbove._rowSpanCurrentOffset) {
222
- rowCellAbove = body[lineIndex - 1 - cellAbove._rowSpanCurrentOffset][i];
223
- rowBottomBorder = rowCellAbove && rowCellAbove.border ? rowCellAbove.border[3] : this.layout.defaultBorder;
224
- if (rowBottomBorder && rowCellAbove && rowCellAbove.borderColor) {
225
- borderColor = rowCellAbove.borderColor[3];
226
- }
227
- }
228
-
229
- if (borderColor == null) {
230
- borderColor = typeof this.layout.hLineColor === 'function' ? this.layout.hLineColor(lineIndex, this.tableNode, i) : this.layout.hLineColor;
231
- }
232
-
233
- if (!currentLine && shouldDrawLine) {
234
- currentLine = { left: data.left, width: 0 };
235
- }
236
-
237
- if (shouldDrawLine) {
238
- let colSpanIndex = 0;
239
- if (rowCellAbove && rowCellAbove.colSpan && rowBottomBorder) {
240
- while (rowCellAbove.colSpan > colSpanIndex) {
241
- currentLine.width += (this.rowSpanData[i + colSpanIndex++].width || 0);
242
- }
243
- i += colSpanIndex - 1;
244
- } else if (cellAbove && cellAbove.colSpan && bottomBorder) {
245
- while (cellAbove.colSpan > colSpanIndex) {
246
- currentLine.width += (this.rowSpanData[i + colSpanIndex++].width || 0);
247
- }
248
- i += colSpanIndex - 1;
249
- } else if (currentCell && currentCell.colSpan && topBorder) {
250
- while (currentCell.colSpan > colSpanIndex) {
251
- currentLine.width += (this.rowSpanData[i + colSpanIndex++].width || 0);
252
- }
253
- i += colSpanIndex - 1;
254
- } else {
255
- currentLine.width += (this.rowSpanData[i].width || 0);
256
- }
257
- }
258
-
259
- let y = (overrideY || 0) + offset;
260
-
261
- if (shouldDrawLine) {
262
- if (currentLine && currentLine.width) {
263
- writer.addVector({
264
- type: 'line',
265
- x1: currentLine.left,
266
- x2: currentLine.left + currentLine.width,
267
- y1: y,
268
- y2: y,
269
- lineWidth: lineWidth,
270
- dash: dash,
271
- lineColor: borderColor
272
- }, false, isNumber(overrideY), null, forcePage);
273
- currentLine = null;
274
- borderColor = null;
275
- cellAbove = null;
276
- currentCell = null;
277
- rowCellAbove = null;
278
- }
279
- }
280
- }
281
-
282
- if (moveDown) {
283
- writer.context().moveDown(lineWidth);
284
- }
285
- }
286
- }
287
-
288
- drawVerticalLine(x, y0, y1, vLineColIndex, writer, vLineRowIndex, beforeVLineColIndex) {
289
- let width = this.layout.vLineWidth(vLineColIndex, this.tableNode);
290
- if (width === 0) {
291
- return;
292
- }
293
- let style = this.layout.vLineStyle(vLineColIndex, this.tableNode);
294
- let dash;
295
- if (style && style.dash) {
296
- dash = style.dash;
297
- }
298
-
299
- let body = this.tableNode.table.body;
300
- let cellBefore;
301
- let currentCell;
302
- let borderColor;
303
-
304
- // the cell in the col before
305
- if (vLineColIndex > 0) {
306
- cellBefore = body[vLineRowIndex][beforeVLineColIndex];
307
- if (cellBefore && cellBefore.borderColor) {
308
- if (cellBefore.border ? cellBefore.border[2] : this.layout.defaultBorder) {
309
- borderColor = cellBefore.borderColor[2];
310
- }
311
- }
312
- }
313
-
314
- // the current cell
315
- if (borderColor == null && vLineColIndex < body.length) {
316
- currentCell = body[vLineRowIndex][vLineColIndex];
317
- if (currentCell && currentCell.borderColor) {
318
- if (currentCell.border ? currentCell.border[0] : this.layout.defaultBorder) {
319
- borderColor = currentCell.borderColor[0];
320
- }
321
- }
322
- }
323
-
324
- if (borderColor == null && cellBefore && cellBefore._rowSpanCurrentOffset) {
325
- let rowCellBeforeAbove = body[vLineRowIndex - cellBefore._rowSpanCurrentOffset][beforeVLineColIndex];
326
- if (rowCellBeforeAbove.borderColor) {
327
- if (rowCellBeforeAbove.border ? rowCellBeforeAbove.border[2] : this.layout.defaultBorder) {
328
- borderColor = rowCellBeforeAbove.borderColor[2];
329
- }
330
- }
331
- }
332
-
333
- if (borderColor == null && currentCell && currentCell._rowSpanCurrentOffset) {
334
- let rowCurrentCellAbove = body[vLineRowIndex - currentCell._rowSpanCurrentOffset][vLineColIndex];
335
- if (rowCurrentCellAbove.borderColor) {
336
- if (rowCurrentCellAbove.border ? rowCurrentCellAbove.border[2] : this.layout.defaultBorder) {
337
- borderColor = rowCurrentCellAbove.borderColor[2];
338
- }
339
- }
340
- }
341
-
342
- if (borderColor == null) {
343
- borderColor = typeof this.layout.vLineColor === 'function' ? this.layout.vLineColor(vLineColIndex, this.tableNode, vLineRowIndex) : this.layout.vLineColor;
344
- }
345
-
346
- writer.addVector({
347
- type: 'line',
348
- x1: x + width / 2,
349
- x2: x + width / 2,
350
- y1: y0,
351
- y2: y1,
352
- lineWidth: width,
353
- dash: dash,
354
- lineColor: borderColor
355
- }, false, true);
356
- cellBefore = null;
357
- currentCell = null;
358
- borderColor = null;
359
- }
360
-
361
- endTable(writer) {
362
- if (this.cleanUpRepeatables) {
363
- writer.popFromRepeatables();
364
- }
365
- }
366
-
367
- endRow(rowIndex, writer, pageBreaks) {
368
- const getLineXs = () => {
369
- let result = [];
370
- let cols = 0;
371
-
372
- for (let i = 0, l = this.tableNode.table.body[rowIndex].length; i < l; i++) {
373
- if (!cols) {
374
- result.push({ x: this.rowSpanData[i].left, index: i });
375
-
376
- let item = this.tableNode.table.body[rowIndex][i];
377
- cols = (item._colSpan || item.colSpan || 0);
378
- }
379
- if (cols > 0) {
380
- cols--;
381
- }
382
- }
383
-
384
- result.push({ x: this.rowSpanData[this.rowSpanData.length - 1].left, index: this.rowSpanData.length - 1 });
385
-
386
- return result;
387
- };
388
-
389
- writer.removeListener('pageChanged', this.rowCallback);
390
- writer.context().moveDown(this.layout.paddingBottom(rowIndex, this.tableNode));
391
- writer.context().availableHeight += this.reservedAtBottom;
392
-
393
- let endingPage = writer.context().page;
394
- let endingY = writer.context().y;
395
-
396
- let xs = getLineXs();
397
-
398
- let ys = [];
399
-
400
- let hasBreaks = pageBreaks && pageBreaks.length > 0;
401
- let body = this.tableNode.table.body;
402
-
403
- ys.push({
404
- y0: this.rowTopY,
405
- page: hasBreaks ? pageBreaks[0].prevPage : endingPage
406
- });
407
-
408
- if (hasBreaks) {
409
- for (let i = 0, l = pageBreaks.length; i < l; i++) {
410
- let pageBreak = pageBreaks[i];
411
- ys[ys.length - 1].y1 = pageBreak.prevY;
412
-
413
- ys.push({ y0: pageBreak.y, page: pageBreak.prevPage + 1 });
414
- }
415
- }
416
-
417
- ys[ys.length - 1].y1 = endingY;
418
-
419
- let skipOrphanePadding = (ys[0].y1 - ys[0].y0 === this.rowPaddingTop);
420
- if (rowIndex === 0 && !skipOrphanePadding && !this.rowsWithoutPageBreak && !this.dontBreakRows) {
421
- // Draw the top border of the table
422
- let pageTableStartedAt = null;
423
- if (pageBreaks && pageBreaks.length > 0) {
424
- // Get the page where table started at
425
- pageTableStartedAt = pageBreaks[0].prevPage;
426
- }
427
- this.drawHorizontalLine(0, writer, this._tableTopBorderY, false, pageTableStartedAt);
428
- }
429
- for (let yi = (skipOrphanePadding ? 1 : 0), yl = ys.length; yi < yl; yi++) {
430
- let willBreak = yi < ys.length - 1;
431
- let rowBreakWithoutHeader = (yi > 0 && !this.headerRows);
432
- let hzLineOffset = rowBreakWithoutHeader ? 0 : this.topLineWidth;
433
- let y1 = ys[yi].y0;
434
- let y2 = ys[yi].y1;
435
-
436
- if (willBreak) {
437
- y2 = y2 + this.rowPaddingBottom;
438
- }
439
-
440
- if (writer.context().page != ys[yi].page) {
441
- writer.context().page = ys[yi].page;
442
-
443
- //TODO: buggy, availableHeight should be updated on every pageChanged event
444
- // TableProcessor should be pageChanged listener, instead of processRow
445
- this.reservedAtBottom = 0;
446
- }
447
-
448
- // Draw horizontal lines before the vertical lines so they are not overridden
449
- if (willBreak && this.layout.hLineWhenBroken !== false) {
450
- this.drawHorizontalLine(rowIndex + 1, writer, y2);
451
- }
452
- if (rowBreakWithoutHeader && this.layout.hLineWhenBroken !== false) {
453
- this.drawHorizontalLine(rowIndex, writer, y1);
454
- }
455
-
456
- for (let i = 0, l = xs.length; i < l; i++) {
457
- let leftCellBorder = false;
458
- let rightCellBorder = false;
459
- let colIndex = xs[i].index;
460
-
461
- // current cell
462
- if (colIndex < body[rowIndex].length) {
463
- let cell = body[rowIndex][colIndex];
464
- leftCellBorder = cell.border ? cell.border[0] : this.layout.defaultBorder;
465
- rightCellBorder = cell.border ? cell.border[2] : this.layout.defaultBorder;
466
- }
467
-
468
- // before cell
469
- if (colIndex > 0 && !leftCellBorder) {
470
- let cell = body[rowIndex][colIndex - 1];
471
- leftCellBorder = cell.border ? cell.border[2] : this.layout.defaultBorder;
472
- }
473
-
474
- // after cell
475
- if (colIndex + 1 < body[rowIndex].length && !rightCellBorder) {
476
- let cell = body[rowIndex][colIndex + 1];
477
- rightCellBorder = cell.border ? cell.border[0] : this.layout.defaultBorder;
478
- }
479
-
480
- if (leftCellBorder) {
481
- this.drawVerticalLine(xs[i].x, y1 - hzLineOffset, y2 + this.bottomLineWidth, xs[i].index, writer, rowIndex, xs[i - 1] ? xs[i - 1].index : null);
482
- }
483
-
484
- if (i < l - 1) {
485
- let fillColor = body[rowIndex][colIndex].fillColor;
486
- let fillOpacity = body[rowIndex][colIndex].fillOpacity;
487
- if (!fillColor) {
488
- fillColor = typeof this.layout.fillColor === 'function' ? this.layout.fillColor(rowIndex, this.tableNode, colIndex) : this.layout.fillColor;
489
- }
490
- if (!isNumber(fillOpacity)) {
491
- fillOpacity = typeof this.layout.fillOpacity === 'function' ? this.layout.fillOpacity(rowIndex, this.tableNode, colIndex) : this.layout.fillOpacity;
492
- }
493
- var overlayPattern = body[rowIndex][colIndex].overlayPattern;
494
- var overlayOpacity = body[rowIndex][colIndex].overlayOpacity;
495
- if (fillColor || overlayPattern) {
496
- let widthLeftBorder = leftCellBorder ? this.layout.vLineWidth(colIndex, this.tableNode) : 0;
497
- let widthRightBorder;
498
- if ((colIndex === 0 || colIndex + 1 == body[rowIndex].length) && !rightCellBorder) {
499
- widthRightBorder = this.layout.vLineWidth(colIndex + 1, this.tableNode);
500
- } else if (rightCellBorder) {
501
- widthRightBorder = this.layout.vLineWidth(colIndex + 1, this.tableNode) / 2;
502
- } else {
503
- widthRightBorder = 0;
504
- }
505
-
506
- let x1f = this.dontBreakRows ? xs[i].x + widthLeftBorder : xs[i].x + (widthLeftBorder / 2);
507
- let y1f = this.dontBreakRows ? y1 : y1 - (hzLineOffset / 2);
508
- let x2f = xs[i + 1].x + widthRightBorder;
509
- let y2f = this.dontBreakRows ? y2 + this.bottomLineWidth : y2 + (this.bottomLineWidth / 2);
510
- var bgWidth = x2f - x1f;
511
- var bgHeight = y2f - y1f;
512
- if (fillColor) {
513
- writer.addVector({
514
- type: 'rect',
515
- x: x1f,
516
- y: y1f,
517
- w: bgWidth,
518
- h: bgHeight,
519
- lineWidth: 0,
520
- color: fillColor,
521
- fillOpacity: fillOpacity,
522
- // mark if we are in an unbreakable block
523
- _isFillColorFromUnbreakable: !!writer.transactionLevel
524
- }, false, true, writer.context().backgroundLength[writer.context().page]);
525
- }
526
-
527
- if (overlayPattern) {
528
- writer.addVector({
529
- type: 'rect',
530
- x: x1f,
531
- y: y1f,
532
- w: bgWidth,
533
- h: bgHeight,
534
- lineWidth: 0,
535
- color: overlayPattern,
536
- fillOpacity: overlayOpacity
537
- }, false, true);
538
- }
539
- }
540
- }
541
- }
542
- }
543
-
544
- writer.context().page = endingPage;
545
- writer.context().y = endingY;
546
-
547
- let row = this.tableNode.table.body[rowIndex];
548
- for (let i = 0, l = row.length; i < l; i++) {
549
- if (row[i].rowSpan) {
550
- this.rowSpanData[i].rowSpan = row[i].rowSpan;
551
-
552
- // fix colSpans
553
- if (row[i].colSpan && row[i].colSpan > 1) {
554
- for (let j = 1; j < row[i].rowSpan; j++) {
555
- this.tableNode.table.body[rowIndex + j][i]._colSpan = row[i].colSpan;
556
- }
557
- }
558
-
559
- // fix rowSpans
560
- if (row[i].rowSpan && row[i].rowSpan > 1) {
561
- for (let j = 1; j < row[i].rowSpan; j++) {
562
- this.tableNode.table.body[rowIndex + j][i]._rowSpanCurrentOffset = j;
563
- }
564
- }
565
- }
566
-
567
- if (this.rowSpanData[i].rowSpan > 0) {
568
- this.rowSpanData[i].rowSpan--;
569
- }
570
- }
571
-
572
- this.drawHorizontalLine(rowIndex + 1, writer);
573
-
574
- if (this.headerRows && rowIndex === this.headerRows - 1) {
575
- this.headerRepeatable = writer.currentBlockToRepeatable();
576
- }
577
-
578
- if (this.dontBreakRows) {
579
- const pageChangedCallback = () => {
580
- if (rowIndex > 0 && !this.headerRows && this.layout.hLineWhenBroken !== false) {
581
- // Draw the top border of the row after a page break
582
- this.drawHorizontalLine(rowIndex, writer);
583
- }
584
- };
585
-
586
- writer.addListener('pageChanged', pageChangedCallback);
587
-
588
- writer.commitUnbreakableBlock();
589
-
590
- writer.removeListener('pageChanged', pageChangedCallback);
591
- }
592
-
593
- if (this.headerRepeatable && (rowIndex === (this.rowsWithoutPageBreak - 1) || rowIndex === this.tableNode.table.body.length - 1)) {
594
- writer.commitUnbreakableBlock();
595
- writer.pushToRepeatables(this.headerRepeatable);
596
- this.cleanUpRepeatables = true;
597
- this.headerRepeatable = null;
598
- }
599
- }
600
- }
601
-
602
- export default 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;
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
+ cellAbove = null;
278
+ currentCell = null;
279
+ rowCellAbove = null;
280
+ }
281
+ }
282
+ }
283
+
284
+ if (moveDown) {
285
+ writer.context().moveDown(lineWidth);
286
+ }
287
+ }
288
+ }
289
+
290
+ drawVerticalLine(x, y0, y1, vLineColIndex, writer, vLineRowIndex, beforeVLineColIndex) {
291
+ let width = this.layout.vLineWidth(vLineColIndex, this.tableNode);
292
+ if (width === 0) {
293
+ return;
294
+ }
295
+ let style = this.layout.vLineStyle(vLineColIndex, this.tableNode);
296
+ let dash;
297
+ if (style && style.dash) {
298
+ dash = style.dash;
299
+ }
300
+
301
+ let body = this.tableNode.table.body;
302
+ let cellBefore;
303
+ let currentCell;
304
+ let borderColor;
305
+
306
+ // the cell in the col before
307
+ if (vLineColIndex > 0) {
308
+ cellBefore = body[vLineRowIndex][beforeVLineColIndex];
309
+ if (cellBefore && cellBefore.borderColor) {
310
+ if (cellBefore.border ? cellBefore.border[2] : this.layout.defaultBorder) {
311
+ borderColor = cellBefore.borderColor[2];
312
+ }
313
+ }
314
+ }
315
+
316
+ // the current cell
317
+ if (borderColor == null && vLineColIndex < body.length) {
318
+ currentCell = body[vLineRowIndex][vLineColIndex];
319
+ if (currentCell && currentCell.borderColor) {
320
+ if (currentCell.border ? currentCell.border[0] : this.layout.defaultBorder) {
321
+ borderColor = currentCell.borderColor[0];
322
+ }
323
+ }
324
+ }
325
+
326
+ if (borderColor == null && cellBefore && cellBefore._rowSpanCurrentOffset) {
327
+ let rowCellBeforeAbove = body[vLineRowIndex - cellBefore._rowSpanCurrentOffset][beforeVLineColIndex];
328
+ if (rowCellBeforeAbove.borderColor) {
329
+ if (rowCellBeforeAbove.border ? rowCellBeforeAbove.border[2] : this.layout.defaultBorder) {
330
+ borderColor = rowCellBeforeAbove.borderColor[2];
331
+ }
332
+ }
333
+ }
334
+
335
+ if (borderColor == null && currentCell && currentCell._rowSpanCurrentOffset) {
336
+ let rowCurrentCellAbove = body[vLineRowIndex - currentCell._rowSpanCurrentOffset][vLineColIndex];
337
+ if (rowCurrentCellAbove.borderColor) {
338
+ if (rowCurrentCellAbove.border ? rowCurrentCellAbove.border[2] : this.layout.defaultBorder) {
339
+ borderColor = rowCurrentCellAbove.borderColor[2];
340
+ }
341
+ }
342
+ }
343
+
344
+ if (borderColor == null) {
345
+ borderColor = typeof this.layout.vLineColor === 'function' ? this.layout.vLineColor(vLineColIndex, this.tableNode, vLineRowIndex) : this.layout.vLineColor;
346
+ }
347
+
348
+ writer.addVector({
349
+ type: 'line',
350
+ x1: x + width / 2,
351
+ x2: x + width / 2,
352
+ y1: y0,
353
+ y2: y1,
354
+ lineWidth: width,
355
+ dash: dash,
356
+ lineColor: borderColor
357
+ }, false, true);
358
+ }
359
+
360
+ endTable(writer) {
361
+ if (this.cleanUpRepeatables) {
362
+ writer.popFromRepeatables();
363
+ }
364
+ }
365
+
366
+ endRow(rowIndex, writer, pageBreaks) {
367
+ const getLineXs = () => {
368
+ let result = [];
369
+ let cols = 0;
370
+
371
+ for (let i = 0, l = this.tableNode.table.body[rowIndex].length; i < l; i++) {
372
+ if (!cols) {
373
+ result.push({ x: this.rowSpanData[i].left, index: i });
374
+
375
+ let item = this.tableNode.table.body[rowIndex][i];
376
+ cols = (item._colSpan || item.colSpan || 0);
377
+ }
378
+ if (cols > 0) {
379
+ cols--;
380
+ }
381
+ }
382
+
383
+ result.push({ x: this.rowSpanData[this.rowSpanData.length - 1].left, index: this.rowSpanData.length - 1 });
384
+
385
+ return result;
386
+ };
387
+
388
+ writer.removeListener('pageChanged', this.rowCallback);
389
+ writer.context().moveDown(this.layout.paddingBottom(rowIndex, this.tableNode));
390
+ writer.context().availableHeight += this.reservedAtBottom;
391
+
392
+ let endingPage = writer.context().page;
393
+ let endingY = writer.context().y;
394
+
395
+ let xs = getLineXs();
396
+
397
+ let ys = [];
398
+
399
+ let hasBreaks = pageBreaks && pageBreaks.length > 0;
400
+ let body = this.tableNode.table.body;
401
+
402
+ ys.push({
403
+ y0: this.rowTopY,
404
+ page: hasBreaks ? pageBreaks[0].prevPage : endingPage
405
+ });
406
+
407
+ if (hasBreaks) {
408
+ for (let i = 0, l = pageBreaks.length; i < l; i++) {
409
+ let pageBreak = pageBreaks[i];
410
+ ys[ys.length - 1].y1 = pageBreak.prevY;
411
+
412
+ ys.push({ y0: pageBreak.y, page: pageBreak.prevPage + 1 });
413
+ }
414
+ }
415
+
416
+ ys[ys.length - 1].y1 = endingY;
417
+
418
+ let skipOrphanePadding = (ys[0].y1 - ys[0].y0 === this.rowPaddingTop);
419
+ if (rowIndex === 0 && !skipOrphanePadding && !this.rowsWithoutPageBreak && !this.dontBreakRows) {
420
+ // Draw the top border of the table
421
+ let pageTableStartedAt = null;
422
+ if (pageBreaks && pageBreaks.length > 0) {
423
+ // Get the page where table started at
424
+ pageTableStartedAt = pageBreaks[0].prevPage;
425
+ }
426
+ this.drawHorizontalLine(0, writer, this._tableTopBorderY, false, pageTableStartedAt);
427
+ }
428
+ for (let yi = (skipOrphanePadding ? 1 : 0), yl = ys.length; yi < yl; yi++) {
429
+ let willBreak = yi < ys.length - 1;
430
+ let rowBreakWithoutHeader = (yi > 0 && !this.headerRows);
431
+ let hzLineOffset = rowBreakWithoutHeader ? 0 : this.topLineWidth;
432
+ let y1 = ys[yi].y0;
433
+ let y2 = ys[yi].y1;
434
+
435
+ if (willBreak) {
436
+ y2 = y2 + this.rowPaddingBottom;
437
+ }
438
+
439
+ if (writer.context().page != ys[yi].page) {
440
+ writer.context().page = ys[yi].page;
441
+
442
+ //TODO: buggy, availableHeight should be updated on every pageChanged event
443
+ // TableProcessor should be pageChanged listener, instead of processRow
444
+ this.reservedAtBottom = 0;
445
+ }
446
+
447
+ // Draw horizontal lines before the vertical lines so they are not overridden
448
+ if (willBreak && this.layout.hLineWhenBroken !== false) {
449
+ this.drawHorizontalLine(rowIndex + 1, writer, y2);
450
+ }
451
+ if (rowBreakWithoutHeader && this.layout.hLineWhenBroken !== false) {
452
+ this.drawHorizontalLine(rowIndex, writer, y1);
453
+ }
454
+
455
+ for (let i = 0, l = xs.length; i < l; i++) {
456
+ let leftCellBorder = false;
457
+ let rightCellBorder = false;
458
+ let colIndex = xs[i].index;
459
+
460
+ // current cell
461
+ if (colIndex < body[rowIndex].length) {
462
+ let cell = body[rowIndex][colIndex];
463
+ leftCellBorder = cell.border ? cell.border[0] : this.layout.defaultBorder;
464
+ rightCellBorder = cell.border ? cell.border[2] : this.layout.defaultBorder;
465
+ }
466
+
467
+ // before cell
468
+ if (colIndex > 0 && !leftCellBorder) {
469
+ let cell = body[rowIndex][colIndex - 1];
470
+ leftCellBorder = cell.border ? cell.border[2] : this.layout.defaultBorder;
471
+ }
472
+
473
+ // after cell
474
+ if (colIndex + 1 < body[rowIndex].length && !rightCellBorder) {
475
+ let cell = body[rowIndex][colIndex + 1];
476
+ rightCellBorder = cell.border ? cell.border[0] : this.layout.defaultBorder;
477
+ }
478
+
479
+ if (leftCellBorder) {
480
+ this.drawVerticalLine(xs[i].x, y1 - hzLineOffset, y2 + this.bottomLineWidth, xs[i].index, writer, rowIndex, xs[i - 1] ? xs[i - 1].index : null);
481
+ }
482
+
483
+ if (i < l - 1) {
484
+ body[rowIndex][colIndex]._willBreak = body[rowIndex][colIndex]._willBreak ?? willBreak;
485
+ if (body[rowIndex][colIndex]._bottomY === undefined) {
486
+ let bottomY = this.dontBreakRows ? y2 + this.bottomLineWidth : y2 + (this.bottomLineWidth / 2);
487
+ if (willBreak || this.dontBreakRows) {
488
+ bottomY = bottomY - this.rowPaddingBottom;
489
+ }
490
+ body[rowIndex][colIndex]._bottomY = bottomY - this.reservedAtBottom;
491
+ }
492
+ body[rowIndex][colIndex]._rowTopPageY = this.rowTopPageY;
493
+ if (this.dontBreakRows) {
494
+ body[rowIndex][colIndex]._rowTopPageYPadding = this.rowPaddingTop;
495
+ }
496
+
497
+ body[rowIndex][colIndex]._lastPageNumber = ys[yi].page + 1;
498
+
499
+ let fillColor = body[rowIndex][colIndex].fillColor;
500
+ let fillOpacity = body[rowIndex][colIndex].fillOpacity;
501
+ if (!fillColor) {
502
+ fillColor = typeof this.layout.fillColor === 'function' ? this.layout.fillColor(rowIndex, this.tableNode, colIndex) : this.layout.fillColor;
503
+ }
504
+ if (!isNumber(fillOpacity)) {
505
+ fillOpacity = typeof this.layout.fillOpacity === 'function' ? this.layout.fillOpacity(rowIndex, this.tableNode, colIndex) : this.layout.fillOpacity;
506
+ }
507
+ var overlayPattern = body[rowIndex][colIndex].overlayPattern;
508
+ var overlayOpacity = body[rowIndex][colIndex].overlayOpacity;
509
+ if (fillColor || overlayPattern) {
510
+ let widthLeftBorder = leftCellBorder ? this.layout.vLineWidth(colIndex, this.tableNode) : 0;
511
+ let widthRightBorder;
512
+ if ((colIndex === 0 || colIndex + 1 == body[rowIndex].length) && !rightCellBorder) {
513
+ widthRightBorder = this.layout.vLineWidth(colIndex + 1, this.tableNode);
514
+ } else if (rightCellBorder) {
515
+ widthRightBorder = this.layout.vLineWidth(colIndex + 1, this.tableNode) / 2;
516
+ } else {
517
+ widthRightBorder = 0;
518
+ }
519
+
520
+ let x1f = this.dontBreakRows ? xs[i].x + widthLeftBorder : xs[i].x + (widthLeftBorder / 2);
521
+ let y1f = this.dontBreakRows ? y1 : y1 - (hzLineOffset / 2);
522
+ let x2f = xs[i + 1].x + widthRightBorder;
523
+ let y2f = this.dontBreakRows ? y2 + this.bottomLineWidth : y2 + (this.bottomLineWidth / 2);
524
+ var bgWidth = x2f - x1f;
525
+ var bgHeight = y2f - y1f;
526
+ if (fillColor) {
527
+ writer.addVector({
528
+ type: 'rect',
529
+ x: x1f,
530
+ y: y1f,
531
+ w: bgWidth,
532
+ h: bgHeight,
533
+ lineWidth: 0,
534
+ color: fillColor,
535
+ fillOpacity: fillOpacity,
536
+ // mark if we are in an unbreakable block
537
+ _isFillColorFromUnbreakable: !!writer.transactionLevel
538
+ }, false, true, writer.context().backgroundLength[writer.context().page]);
539
+ }
540
+
541
+ if (overlayPattern) {
542
+ writer.addVector({
543
+ type: 'rect',
544
+ x: x1f,
545
+ y: y1f,
546
+ w: bgWidth,
547
+ h: bgHeight,
548
+ lineWidth: 0,
549
+ color: overlayPattern,
550
+ fillOpacity: overlayOpacity
551
+ }, false, true);
552
+ }
553
+ }
554
+ }
555
+ }
556
+ }
557
+
558
+ writer.context().page = endingPage;
559
+ writer.context().y = endingY;
560
+
561
+ let row = this.tableNode.table.body[rowIndex];
562
+ for (let i = 0, l = row.length; i < l; i++) {
563
+ if (row[i].rowSpan) {
564
+ this.rowSpanData[i].rowSpan = row[i].rowSpan;
565
+
566
+ // fix colSpans
567
+ if (row[i].colSpan && row[i].colSpan > 1) {
568
+ for (let j = 1; j < row[i].rowSpan; j++) {
569
+ this.tableNode.table.body[rowIndex + j][i]._colSpan = row[i].colSpan;
570
+ }
571
+ }
572
+
573
+ // fix rowSpans
574
+ if (row[i].rowSpan && row[i].rowSpan > 1) {
575
+ for (let j = 1; j < row[i].rowSpan; j++) {
576
+ this.tableNode.table.body[rowIndex + j][i]._rowSpanCurrentOffset = j;
577
+ }
578
+ }
579
+ }
580
+
581
+ if (this.rowSpanData[i].rowSpan > 0) {
582
+ this.rowSpanData[i].rowSpan--;
583
+ }
584
+ }
585
+
586
+ this.drawHorizontalLine(rowIndex + 1, writer);
587
+
588
+ if (this.headerRows && rowIndex === this.headerRows - 1) {
589
+ this.headerRepeatable = writer.currentBlockToRepeatable();
590
+ }
591
+
592
+ if (this.dontBreakRows) {
593
+ const pageChangedCallback = () => {
594
+ if (rowIndex > 0 && !this.headerRows && this.layout.hLineWhenBroken !== false) {
595
+ // Draw the top border of the row after a page break
596
+ this.drawHorizontalLine(rowIndex, writer);
597
+ }
598
+ };
599
+
600
+ writer.addListener('pageChanged', pageChangedCallback);
601
+
602
+ writer.commitUnbreakableBlock();
603
+
604
+ writer.removeListener('pageChanged', pageChangedCallback);
605
+ }
606
+
607
+ if (this.headerRepeatable && (rowIndex === (this.rowsWithoutPageBreak - 1) || rowIndex === this.tableNode.table.body.length - 1)) {
608
+ writer.commitUnbreakableBlock();
609
+ writer.pushToRepeatables(this.headerRepeatable);
610
+ this.cleanUpRepeatables = true;
611
+ this.headerRepeatable = null;
612
+ }
613
+ }
614
+ }
615
+
616
+ export default TableProcessor;