@flowaccount/pdfmake 0.2.20-staging.2

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