@flowaccount/pdfmake 1.0.5 → 1.0.6-staging.3
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.
- package/LICENSE +21 -21
- package/README.md +297 -297
- package/build/pdfmake.js +28541 -28790
- package/build/pdfmake.min.js +2 -2
- package/build/pdfmake.min.js.map +1 -1
- package/build/vfs_fonts.js +6 -6
- package/package.json +110 -110
- package/src/3rd-party/svg-to-pdfkit.js +3 -3
- package/src/browser-extensions/URLBrowserResolver.js +96 -96
- package/src/browser-extensions/pdfMake.js +361 -361
- package/src/browser-extensions/tokenizer-shim.js +15 -15
- package/src/browser-extensions/virtual-fs.js +55 -55
- package/src/columnCalculator.js +157 -157
- package/src/docMeasure.js +831 -831
- package/src/docPreprocessor.js +277 -277
- package/src/documentContext.js +383 -383
- package/src/elementWriter.js +442 -434
- package/src/fontProvider.js +68 -68
- package/src/helpers.js +138 -138
- package/src/imageMeasure.js +70 -70
- package/src/layoutBuilder.js +1993 -1770
- package/src/line.js +91 -91
- package/src/pageElementWriter.js +362 -362
- package/src/pdfKitEngine.js +21 -21
- package/src/printer.js +1191 -1191
- package/src/qrEnc.js +790 -790
- package/src/standardPageSizes.js +54 -54
- package/src/styleContextStack.js +138 -138
- package/src/svgMeasure.js +70 -70
- package/src/tableProcessor.js +791 -789
- package/src/textDecorator.js +157 -157
- package/src/textTools.js +442 -442
- package/src/traversalTracker.js +47 -47
package/src/pageElementWriter.js
CHANGED
|
@@ -1,362 +1,362 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var isUndefined = require('./helpers').isUndefined;
|
|
4
|
-
var ElementWriter = require('./elementWriter');
|
|
5
|
-
|
|
6
|
-
var newPageFooterBreak = true;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Creates an instance of PageElementWriter - an extended ElementWriter
|
|
10
|
-
* which can handle:
|
|
11
|
-
* - page-breaks (it adds new pages when there's not enough space left),
|
|
12
|
-
* - repeatable fragments (like table-headers, which are repeated everytime
|
|
13
|
-
* a page-break occurs)
|
|
14
|
-
* - transactions (used for unbreakable-blocks when we want to make sure
|
|
15
|
-
* whole block will be rendered on the same page)
|
|
16
|
-
*/
|
|
17
|
-
function PageElementWriter(context, tracker) {
|
|
18
|
-
this.transactionLevel = 0;
|
|
19
|
-
this.repeatables = [];
|
|
20
|
-
this.tracker = tracker;
|
|
21
|
-
this.writer = new ElementWriter(context, tracker);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function fitOnPage(self, addFct) {
|
|
25
|
-
var position = addFct(self);
|
|
26
|
-
if (!position) {
|
|
27
|
-
self.moveToNextPage();
|
|
28
|
-
position = addFct(self);
|
|
29
|
-
}
|
|
30
|
-
return position;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
PageElementWriter.prototype.addLine = function (line, dontUpdateContextPosition, index) {
|
|
34
|
-
return fitOnPage(this, function (self) {
|
|
35
|
-
return self.writer.addLine(line, dontUpdateContextPosition, index);
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
PageElementWriter.prototype.addImage = function (image, index) {
|
|
40
|
-
return fitOnPage(this, function (self) {
|
|
41
|
-
return self.writer.addImage(image, index);
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
PageElementWriter.prototype.addSVG = function (image, index) {
|
|
46
|
-
return fitOnPage(this, function (self) {
|
|
47
|
-
return self.writer.addSVG(image, index);
|
|
48
|
-
});
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
PageElementWriter.prototype.addQr = function (qr, index) {
|
|
52
|
-
return fitOnPage(this, function (self) {
|
|
53
|
-
return self.writer.addQr(qr, index);
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
PageElementWriter.prototype.addVector = function (vector, ignoreContextX, ignoreContextY, index, forcePage) {
|
|
58
|
-
return this.writer.addVector(vector, ignoreContextX, ignoreContextY, index, forcePage);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
PageElementWriter.prototype.beginClip = function (width, height) {
|
|
62
|
-
return this.writer.beginClip(width, height);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
PageElementWriter.prototype.endClip = function () {
|
|
66
|
-
return this.writer.endClip();
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
PageElementWriter.prototype.alignCanvas = function (node) {
|
|
70
|
-
this.writer.alignCanvas(node);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
PageElementWriter.prototype.addFragment = function (fragment, useBlockXOffset, useBlockYOffset, dontUpdateContextPosition, isFooter) {
|
|
74
|
-
if (isFooter) {
|
|
75
|
-
var ctxOpt = this.writer.context._footerGapOption;
|
|
76
|
-
if (ctxOpt && ctxOpt.enabled && fragment.footerGap !== false && !fragment._footerGapOption) {
|
|
77
|
-
fragment._footerGapOption = ctxOpt;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (this.writer.context._footerColumnGuides && !fragment.disableFooterColumnGuides && !fragment._footerGuideSpec) {
|
|
81
|
-
var g = this.writer.context._footerColumnGuides;
|
|
82
|
-
fragment._footerGuideSpec = {
|
|
83
|
-
widths: g.widths ? g.widths.slice() : undefined,
|
|
84
|
-
stops: g.stops ? g.stops.slice() : undefined,
|
|
85
|
-
style: g.style ? Object.assign({}, g.style) : {},
|
|
86
|
-
includeOuter: g.includeOuter
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
var result = this.writer.addFragment(fragment, useBlockXOffset, useBlockYOffset, dontUpdateContextPosition, isFooter);
|
|
92
|
-
if (isFooter) {
|
|
93
|
-
if (result && isFooter == 1) {
|
|
94
|
-
newPageFooterBreak = false;
|
|
95
|
-
return true;
|
|
96
|
-
} else if (!result && isFooter == 2 && newPageFooterBreak) {
|
|
97
|
-
this.moveToNextPage();
|
|
98
|
-
this.writer.addFragment(fragment, useBlockXOffset, useBlockYOffset, dontUpdateContextPosition, isFooter);
|
|
99
|
-
} else if (!result && isFooter == 1) {
|
|
100
|
-
// Draw footer vertical lines before moving to next page
|
|
101
|
-
this.drawFooterVerticalLines(fragment);
|
|
102
|
-
// Draw footer horizontal line at the bottom of the page
|
|
103
|
-
this.drawFooterHorizontalLine(fragment);
|
|
104
|
-
this.moveToNextPage();
|
|
105
|
-
}
|
|
106
|
-
} else {
|
|
107
|
-
if (!result) {
|
|
108
|
-
this.moveToNextPage();
|
|
109
|
-
this.writer.addFragment(fragment, useBlockXOffset, useBlockYOffset, dontUpdateContextPosition, isFooter);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return result;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
PageElementWriter.prototype.drawFooterVerticalLines = function (fragment) {
|
|
116
|
-
var ctx = this.writer.context;
|
|
117
|
-
var footerOpt = fragment._footerGapOption || (ctx && ctx._footerGapOption);
|
|
118
|
-
|
|
119
|
-
if (!footerOpt || !footerOpt.enabled || !footerOpt.columns || !footerOpt.columns.content) {
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
var colSpec = footerOpt.columns;
|
|
124
|
-
var rawWidths = colSpec.content.vLines || [];
|
|
125
|
-
|
|
126
|
-
if (!rawWidths || rawWidths.length === 0) {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Get the current page bottom position (accounting for margins)
|
|
131
|
-
var pageHeight = ctx.getCurrentPage().pageSize.height;
|
|
132
|
-
var bottomMargin = ctx.pageMargins.bottom;
|
|
133
|
-
var bottomY = pageHeight - bottomMargin;
|
|
134
|
-
|
|
135
|
-
// Use current Y position as the top of the vertical lines
|
|
136
|
-
var gapTopY = ctx.y;
|
|
137
|
-
|
|
138
|
-
// Store current page for drawing
|
|
139
|
-
var currentPage = ctx.page;
|
|
140
|
-
|
|
141
|
-
// Get style configuration - match elementWriter.js logic exactly
|
|
142
|
-
var style = colSpec.style || {};
|
|
143
|
-
var lw = style.lineWidth != null ? style.lineWidth : 0.5;
|
|
144
|
-
var lc = style.color || '#000000';
|
|
145
|
-
var dashCfg = style.dash;
|
|
146
|
-
var includeOuter = colSpec.includeOuter !== false;
|
|
147
|
-
|
|
148
|
-
// Draw ALL collected vertical lines
|
|
149
|
-
// When includeOuter is true, draw all lines including first and last borders
|
|
150
|
-
// When includeOuter is false, skip the first and last
|
|
151
|
-
var startIndex = includeOuter ? 0 : 1;
|
|
152
|
-
var endIndex = includeOuter ? rawWidths.length : Math.max(1, rawWidths.length - 1);
|
|
153
|
-
|
|
154
|
-
// Draw vertical lines using the same logic as elementWriter.js
|
|
155
|
-
for (var ci = startIndex; ci < endIndex; ci++) {
|
|
156
|
-
// Match elementWriter.js: ctx.x + rawWidths[ci] - 0.25
|
|
157
|
-
var xGuide = ctx.x + rawWidths[ci] - 0.25;
|
|
158
|
-
this.writer.addVector({
|
|
159
|
-
type: 'line',
|
|
160
|
-
x1: xGuide,
|
|
161
|
-
y1: gapTopY,
|
|
162
|
-
x2: xGuide,
|
|
163
|
-
y2: bottomY,
|
|
164
|
-
lineWidth: lw,
|
|
165
|
-
lineColor: lc,
|
|
166
|
-
dash: dashCfg ? {
|
|
167
|
-
length: dashCfg.length,
|
|
168
|
-
space: dashCfg.space != null ? dashCfg.space : dashCfg.gap
|
|
169
|
-
} : undefined
|
|
170
|
-
}, true, true, undefined, currentPage);
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
PageElementWriter.prototype.drawFooterHorizontalLine = function (fragment) {
|
|
175
|
-
var ctx = this.writer.context;
|
|
176
|
-
var footerOpt = fragment._footerGapOption || (ctx && ctx._footerGapOption);
|
|
177
|
-
|
|
178
|
-
if (!footerOpt || !footerOpt.enabled || !footerOpt.columns || !footerOpt.columns.content) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
var colSpec = footerOpt.columns;
|
|
183
|
-
var rawWidths = colSpec.content.vLines || [];
|
|
184
|
-
|
|
185
|
-
if (!rawWidths || rawWidths.length === 0) {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Get the page bottom position (same as vertical lines bottom)
|
|
190
|
-
var pageHeight = ctx.getCurrentPage().pageSize.height;
|
|
191
|
-
var bottomMargin = ctx.pageMargins.bottom;
|
|
192
|
-
var y = pageHeight - bottomMargin;
|
|
193
|
-
|
|
194
|
-
// Get the table width (from first to last vertical line position)
|
|
195
|
-
var x1 = ctx.x + rawWidths[0] - 0.25;
|
|
196
|
-
var x2 = ctx.x + rawWidths[rawWidths.length - 1] - 0.25;
|
|
197
|
-
|
|
198
|
-
// Store current page for drawing
|
|
199
|
-
var currentPage = ctx.page;
|
|
200
|
-
|
|
201
|
-
// Get style configuration
|
|
202
|
-
var style = colSpec.style || {};
|
|
203
|
-
var lw = style.lineWidth != null ? style.lineWidth : 0.5;
|
|
204
|
-
var lc = style.color || '#000000';
|
|
205
|
-
var dashCfg = style.dash;
|
|
206
|
-
|
|
207
|
-
// Draw horizontal line at the bottom of the page (where vertical lines end)
|
|
208
|
-
this.writer.addVector({
|
|
209
|
-
type: 'line',
|
|
210
|
-
x1: x1,
|
|
211
|
-
y1: y,
|
|
212
|
-
x2: x2,
|
|
213
|
-
y2: y,
|
|
214
|
-
lineWidth: lw,
|
|
215
|
-
lineColor: lc,
|
|
216
|
-
dash: dashCfg ? {
|
|
217
|
-
length: dashCfg.length,
|
|
218
|
-
space: dashCfg.space != null ? dashCfg.space : dashCfg.gap
|
|
219
|
-
} : undefined
|
|
220
|
-
}, true, true, undefined, currentPage);
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
PageElementWriter.prototype.addFragment_test = function (fragment) {
|
|
224
|
-
if (fragment.height > this.writer.context.availableHeight) {
|
|
225
|
-
return false;
|
|
226
|
-
}
|
|
227
|
-
return true;
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
PageElementWriter.prototype.removeBeginClip = function (item) {
|
|
231
|
-
return this.writer.removeBeginClip(item);
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
PageElementWriter.prototype.beginVerticalAlign = function (verticalAlign) {
|
|
235
|
-
return this.writer.beginVerticalAlign(verticalAlign);
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
PageElementWriter.prototype.endVerticalAlign = function (verticalAlign) {
|
|
239
|
-
return this.writer.endVerticalAlign(verticalAlign);
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
PageElementWriter.prototype.moveToNextPage = function (pageOrientation) {
|
|
243
|
-
|
|
244
|
-
var currentPage = this.writer.context.pages[this.writer.context.page];
|
|
245
|
-
this.writer.tracker.emit('beforePageChanged', {
|
|
246
|
-
prevPage: currentPage.prevPage,
|
|
247
|
-
prevY: currentPage.prevY,
|
|
248
|
-
y: currentPage.y
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
var nextPage = this.writer.context.moveToNextPage(pageOrientation);
|
|
252
|
-
|
|
253
|
-
// moveToNextPage is called multiple times for table, because is called for each column
|
|
254
|
-
// and repeatables are inserted only in the first time. If columns are used, is needed
|
|
255
|
-
// call for table in first column and then for table in the second column (is other repeatables).
|
|
256
|
-
if (nextPage.newPageCreated) {
|
|
257
|
-
this.repeatables.forEach(function (rep) {
|
|
258
|
-
this.writer.addFragment(rep, true);
|
|
259
|
-
}, this);
|
|
260
|
-
} else {
|
|
261
|
-
this.repeatables.forEach(function (rep) {
|
|
262
|
-
this.writer.context.moveDown(rep.height);
|
|
263
|
-
}, this);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
this.writer.tracker.emit('pageChanged', {
|
|
267
|
-
prevPage: nextPage.prevPage,
|
|
268
|
-
prevY: nextPage.prevY,
|
|
269
|
-
y: this.writer.context.y
|
|
270
|
-
});
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
PageElementWriter.prototype.beginUnbreakableBlock = function (width, height) {
|
|
274
|
-
if (this.transactionLevel++ === 0) {
|
|
275
|
-
this.originalX = this.writer.context.x;
|
|
276
|
-
this.writer.pushContext(width, height);
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
PageElementWriter.prototype.commitUnbreakableBlock = function (forcedX, forcedY, isFooter) {
|
|
281
|
-
if (--this.transactionLevel === 0) {
|
|
282
|
-
var unbreakableContext = this.writer.context;
|
|
283
|
-
this.writer.popContext();
|
|
284
|
-
|
|
285
|
-
var nbPages = unbreakableContext.pages.length;
|
|
286
|
-
if (nbPages > 0) {
|
|
287
|
-
// no support for multi-page unbreakableBlocks
|
|
288
|
-
var fragment = unbreakableContext.pages[0];
|
|
289
|
-
fragment.xOffset = forcedX;
|
|
290
|
-
fragment.yOffset = forcedY;
|
|
291
|
-
|
|
292
|
-
//TODO: vectors can influence height in some situations
|
|
293
|
-
if (nbPages > 1) {
|
|
294
|
-
// on out-of-context blocs (headers, footers, background) height should be the whole DocumentContext height
|
|
295
|
-
if (forcedX !== undefined || forcedY !== undefined) {
|
|
296
|
-
fragment.height = unbreakableContext.getCurrentPage().pageSize.height - unbreakableContext.pageMargins.top - unbreakableContext.pageMargins.bottom;
|
|
297
|
-
} else {
|
|
298
|
-
fragment.height = this.writer.context.getCurrentPage().pageSize.height - this.writer.context.pageMargins.top - this.writer.context.pageMargins.bottom;
|
|
299
|
-
for (var i = 0, l = this.repeatables.length; i < l; i++) {
|
|
300
|
-
fragment.height -= this.repeatables[i].height;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
} else {
|
|
304
|
-
fragment.height = unbreakableContext.y;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
if (forcedX !== undefined || forcedY !== undefined) {
|
|
308
|
-
this.writer.addFragment(fragment, true, true, true);
|
|
309
|
-
} else {
|
|
310
|
-
return this.addFragment(fragment, undefined, undefined, undefined, isFooter);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
PageElementWriter.prototype.commitUnbreakableBlock_test = function (forcedX, forcedY) {
|
|
317
|
-
if (--this.transactionLevel === 0) {
|
|
318
|
-
var unbreakableContext = this.writer.context;
|
|
319
|
-
this.writer.popContext();
|
|
320
|
-
|
|
321
|
-
var nbPages = unbreakableContext.pages.length;
|
|
322
|
-
if (nbPages > 0) {
|
|
323
|
-
var fragment = unbreakableContext.pages[0];
|
|
324
|
-
fragment.xOffset = forcedX;
|
|
325
|
-
fragment.yOffset = forcedY;
|
|
326
|
-
fragment.height = unbreakableContext.y;
|
|
327
|
-
return this.addFragment_test(fragment);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
PageElementWriter.prototype.currentBlockToRepeatable = function () {
|
|
333
|
-
var unbreakableContext = this.writer.context;
|
|
334
|
-
var rep = { items: [] };
|
|
335
|
-
|
|
336
|
-
unbreakableContext.pages[0].items.forEach(function (item) {
|
|
337
|
-
rep.items.push(item);
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
rep.xOffset = this.originalX;
|
|
341
|
-
|
|
342
|
-
//TODO: vectors can influence height in some situations
|
|
343
|
-
rep.height = unbreakableContext.y;
|
|
344
|
-
|
|
345
|
-
rep.insertedOnPages = [];
|
|
346
|
-
|
|
347
|
-
return rep;
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
PageElementWriter.prototype.pushToRepeatables = function (rep) {
|
|
351
|
-
this.repeatables.push(rep);
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
PageElementWriter.prototype.popFromRepeatables = function () {
|
|
355
|
-
this.repeatables.pop();
|
|
356
|
-
};
|
|
357
|
-
|
|
358
|
-
PageElementWriter.prototype.context = function () {
|
|
359
|
-
return this.writer.context;
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
module.exports = PageElementWriter;
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var isUndefined = require('./helpers').isUndefined;
|
|
4
|
+
var ElementWriter = require('./elementWriter');
|
|
5
|
+
|
|
6
|
+
var newPageFooterBreak = true;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates an instance of PageElementWriter - an extended ElementWriter
|
|
10
|
+
* which can handle:
|
|
11
|
+
* - page-breaks (it adds new pages when there's not enough space left),
|
|
12
|
+
* - repeatable fragments (like table-headers, which are repeated everytime
|
|
13
|
+
* a page-break occurs)
|
|
14
|
+
* - transactions (used for unbreakable-blocks when we want to make sure
|
|
15
|
+
* whole block will be rendered on the same page)
|
|
16
|
+
*/
|
|
17
|
+
function PageElementWriter(context, tracker) {
|
|
18
|
+
this.transactionLevel = 0;
|
|
19
|
+
this.repeatables = [];
|
|
20
|
+
this.tracker = tracker;
|
|
21
|
+
this.writer = new ElementWriter(context, tracker);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function fitOnPage(self, addFct) {
|
|
25
|
+
var position = addFct(self);
|
|
26
|
+
if (!position) {
|
|
27
|
+
self.moveToNextPage();
|
|
28
|
+
position = addFct(self);
|
|
29
|
+
}
|
|
30
|
+
return position;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
PageElementWriter.prototype.addLine = function (line, dontUpdateContextPosition, index) {
|
|
34
|
+
return fitOnPage(this, function (self) {
|
|
35
|
+
return self.writer.addLine(line, dontUpdateContextPosition, index);
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
PageElementWriter.prototype.addImage = function (image, index) {
|
|
40
|
+
return fitOnPage(this, function (self) {
|
|
41
|
+
return self.writer.addImage(image, index);
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
PageElementWriter.prototype.addSVG = function (image, index) {
|
|
46
|
+
return fitOnPage(this, function (self) {
|
|
47
|
+
return self.writer.addSVG(image, index);
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
PageElementWriter.prototype.addQr = function (qr, index) {
|
|
52
|
+
return fitOnPage(this, function (self) {
|
|
53
|
+
return self.writer.addQr(qr, index);
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
PageElementWriter.prototype.addVector = function (vector, ignoreContextX, ignoreContextY, index, forcePage) {
|
|
58
|
+
return this.writer.addVector(vector, ignoreContextX, ignoreContextY, index, forcePage);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
PageElementWriter.prototype.beginClip = function (width, height) {
|
|
62
|
+
return this.writer.beginClip(width, height);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
PageElementWriter.prototype.endClip = function () {
|
|
66
|
+
return this.writer.endClip();
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
PageElementWriter.prototype.alignCanvas = function (node) {
|
|
70
|
+
this.writer.alignCanvas(node);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
PageElementWriter.prototype.addFragment = function (fragment, useBlockXOffset, useBlockYOffset, dontUpdateContextPosition, isFooter) {
|
|
74
|
+
if (isFooter) {
|
|
75
|
+
var ctxOpt = this.writer.context._footerGapOption;
|
|
76
|
+
if (ctxOpt && ctxOpt.enabled && fragment.footerGap !== false && !fragment._footerGapOption) {
|
|
77
|
+
fragment._footerGapOption = ctxOpt;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (this.writer.context._footerColumnGuides && !fragment.disableFooterColumnGuides && !fragment._footerGuideSpec) {
|
|
81
|
+
var g = this.writer.context._footerColumnGuides;
|
|
82
|
+
fragment._footerGuideSpec = {
|
|
83
|
+
widths: g.widths ? g.widths.slice() : undefined,
|
|
84
|
+
stops: g.stops ? g.stops.slice() : undefined,
|
|
85
|
+
style: g.style ? Object.assign({}, g.style) : {},
|
|
86
|
+
includeOuter: g.includeOuter
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
var result = this.writer.addFragment(fragment, useBlockXOffset, useBlockYOffset, dontUpdateContextPosition, isFooter);
|
|
92
|
+
if (isFooter) {
|
|
93
|
+
if (result && isFooter == 1) {
|
|
94
|
+
newPageFooterBreak = false;
|
|
95
|
+
return true;
|
|
96
|
+
} else if (!result && isFooter == 2 && newPageFooterBreak) {
|
|
97
|
+
this.moveToNextPage();
|
|
98
|
+
this.writer.addFragment(fragment, useBlockXOffset, useBlockYOffset, dontUpdateContextPosition, isFooter);
|
|
99
|
+
} else if (!result && isFooter == 1) {
|
|
100
|
+
// Draw footer vertical lines before moving to next page
|
|
101
|
+
this.drawFooterVerticalLines(fragment);
|
|
102
|
+
// Draw footer horizontal line at the bottom of the page
|
|
103
|
+
this.drawFooterHorizontalLine(fragment);
|
|
104
|
+
this.moveToNextPage();
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
if (!result) {
|
|
108
|
+
this.moveToNextPage();
|
|
109
|
+
this.writer.addFragment(fragment, useBlockXOffset, useBlockYOffset, dontUpdateContextPosition, isFooter);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
PageElementWriter.prototype.drawFooterVerticalLines = function (fragment) {
|
|
116
|
+
var ctx = this.writer.context;
|
|
117
|
+
var footerOpt = fragment._footerGapOption || (ctx && ctx._footerGapOption);
|
|
118
|
+
|
|
119
|
+
if (!footerOpt || !footerOpt.enabled || !footerOpt.columns || !footerOpt.columns.content) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
var colSpec = footerOpt.columns;
|
|
124
|
+
var rawWidths = colSpec.content.vLines || [];
|
|
125
|
+
|
|
126
|
+
if (!rawWidths || rawWidths.length === 0) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Get the current page bottom position (accounting for margins)
|
|
131
|
+
var pageHeight = ctx.getCurrentPage().pageSize.height;
|
|
132
|
+
var bottomMargin = ctx.pageMargins.bottom;
|
|
133
|
+
var bottomY = pageHeight - bottomMargin;
|
|
134
|
+
|
|
135
|
+
// Use current Y position as the top of the vertical lines
|
|
136
|
+
var gapTopY = ctx.y;
|
|
137
|
+
|
|
138
|
+
// Store current page for drawing
|
|
139
|
+
var currentPage = ctx.page;
|
|
140
|
+
|
|
141
|
+
// Get style configuration - match elementWriter.js logic exactly
|
|
142
|
+
var style = colSpec.style || {};
|
|
143
|
+
var lw = style.lineWidth != null ? style.lineWidth : 0.5;
|
|
144
|
+
var lc = style.color || '#000000';
|
|
145
|
+
var dashCfg = style.dash;
|
|
146
|
+
var includeOuter = colSpec.includeOuter !== false;
|
|
147
|
+
|
|
148
|
+
// Draw ALL collected vertical lines
|
|
149
|
+
// When includeOuter is true, draw all lines including first and last borders
|
|
150
|
+
// When includeOuter is false, skip the first and last
|
|
151
|
+
var startIndex = includeOuter ? 0 : 1;
|
|
152
|
+
var endIndex = includeOuter ? rawWidths.length : Math.max(1, rawWidths.length - 1);
|
|
153
|
+
|
|
154
|
+
// Draw vertical lines using the same logic as elementWriter.js
|
|
155
|
+
for (var ci = startIndex; ci < endIndex; ci++) {
|
|
156
|
+
// Match elementWriter.js: ctx.x + rawWidths[ci] - 0.25
|
|
157
|
+
var xGuide = ctx.x + rawWidths[ci] - 0.25;
|
|
158
|
+
this.writer.addVector({
|
|
159
|
+
type: 'line',
|
|
160
|
+
x1: xGuide,
|
|
161
|
+
y1: gapTopY,
|
|
162
|
+
x2: xGuide,
|
|
163
|
+
y2: bottomY,
|
|
164
|
+
lineWidth: lw,
|
|
165
|
+
lineColor: lc,
|
|
166
|
+
dash: dashCfg ? {
|
|
167
|
+
length: dashCfg.length,
|
|
168
|
+
space: dashCfg.space != null ? dashCfg.space : dashCfg.gap
|
|
169
|
+
} : undefined
|
|
170
|
+
}, true, true, undefined, currentPage);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
PageElementWriter.prototype.drawFooterHorizontalLine = function (fragment) {
|
|
175
|
+
var ctx = this.writer.context;
|
|
176
|
+
var footerOpt = fragment._footerGapOption || (ctx && ctx._footerGapOption);
|
|
177
|
+
|
|
178
|
+
if (!footerOpt || !footerOpt.enabled || !footerOpt.columns || !footerOpt.columns.content) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
var colSpec = footerOpt.columns;
|
|
183
|
+
var rawWidths = colSpec.content.vLines || [];
|
|
184
|
+
|
|
185
|
+
if (!rawWidths || rawWidths.length === 0) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Get the page bottom position (same as vertical lines bottom)
|
|
190
|
+
var pageHeight = ctx.getCurrentPage().pageSize.height;
|
|
191
|
+
var bottomMargin = ctx.pageMargins.bottom;
|
|
192
|
+
var y = pageHeight - bottomMargin;
|
|
193
|
+
|
|
194
|
+
// Get the table width (from first to last vertical line position)
|
|
195
|
+
var x1 = ctx.x + rawWidths[0] - 0.25;
|
|
196
|
+
var x2 = ctx.x + rawWidths[rawWidths.length - 1] - 0.25;
|
|
197
|
+
|
|
198
|
+
// Store current page for drawing
|
|
199
|
+
var currentPage = ctx.page;
|
|
200
|
+
|
|
201
|
+
// Get style configuration
|
|
202
|
+
var style = colSpec.style || {};
|
|
203
|
+
var lw = style.lineWidth != null ? style.lineWidth : 0.5;
|
|
204
|
+
var lc = style.color || '#000000';
|
|
205
|
+
var dashCfg = style.dash;
|
|
206
|
+
|
|
207
|
+
// Draw horizontal line at the bottom of the page (where vertical lines end)
|
|
208
|
+
this.writer.addVector({
|
|
209
|
+
type: 'line',
|
|
210
|
+
x1: x1,
|
|
211
|
+
y1: y,
|
|
212
|
+
x2: x2,
|
|
213
|
+
y2: y,
|
|
214
|
+
lineWidth: lw,
|
|
215
|
+
lineColor: lc,
|
|
216
|
+
dash: dashCfg ? {
|
|
217
|
+
length: dashCfg.length,
|
|
218
|
+
space: dashCfg.space != null ? dashCfg.space : dashCfg.gap
|
|
219
|
+
} : undefined
|
|
220
|
+
}, true, true, undefined, currentPage);
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
PageElementWriter.prototype.addFragment_test = function (fragment) {
|
|
224
|
+
if (fragment.height > this.writer.context.availableHeight) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
return true;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
PageElementWriter.prototype.removeBeginClip = function (item) {
|
|
231
|
+
return this.writer.removeBeginClip(item);
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
PageElementWriter.prototype.beginVerticalAlign = function (verticalAlign) {
|
|
235
|
+
return this.writer.beginVerticalAlign(verticalAlign);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
PageElementWriter.prototype.endVerticalAlign = function (verticalAlign) {
|
|
239
|
+
return this.writer.endVerticalAlign(verticalAlign);
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
PageElementWriter.prototype.moveToNextPage = function (pageOrientation) {
|
|
243
|
+
|
|
244
|
+
var currentPage = this.writer.context.pages[this.writer.context.page];
|
|
245
|
+
this.writer.tracker.emit('beforePageChanged', {
|
|
246
|
+
prevPage: currentPage.prevPage,
|
|
247
|
+
prevY: currentPage.prevY,
|
|
248
|
+
y: currentPage.y
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
var nextPage = this.writer.context.moveToNextPage(pageOrientation);
|
|
252
|
+
|
|
253
|
+
// moveToNextPage is called multiple times for table, because is called for each column
|
|
254
|
+
// and repeatables are inserted only in the first time. If columns are used, is needed
|
|
255
|
+
// call for table in first column and then for table in the second column (is other repeatables).
|
|
256
|
+
if (nextPage.newPageCreated) {
|
|
257
|
+
this.repeatables.forEach(function (rep) {
|
|
258
|
+
this.writer.addFragment(rep, true);
|
|
259
|
+
}, this);
|
|
260
|
+
} else {
|
|
261
|
+
this.repeatables.forEach(function (rep) {
|
|
262
|
+
this.writer.context.moveDown(rep.height);
|
|
263
|
+
}, this);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
this.writer.tracker.emit('pageChanged', {
|
|
267
|
+
prevPage: nextPage.prevPage,
|
|
268
|
+
prevY: nextPage.prevY,
|
|
269
|
+
y: this.writer.context.y
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
PageElementWriter.prototype.beginUnbreakableBlock = function (width, height) {
|
|
274
|
+
if (this.transactionLevel++ === 0) {
|
|
275
|
+
this.originalX = this.writer.context.x;
|
|
276
|
+
this.writer.pushContext(width, height);
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
PageElementWriter.prototype.commitUnbreakableBlock = function (forcedX, forcedY, isFooter) {
|
|
281
|
+
if (--this.transactionLevel === 0) {
|
|
282
|
+
var unbreakableContext = this.writer.context;
|
|
283
|
+
this.writer.popContext();
|
|
284
|
+
|
|
285
|
+
var nbPages = unbreakableContext.pages.length;
|
|
286
|
+
if (nbPages > 0) {
|
|
287
|
+
// no support for multi-page unbreakableBlocks
|
|
288
|
+
var fragment = unbreakableContext.pages[0];
|
|
289
|
+
fragment.xOffset = forcedX;
|
|
290
|
+
fragment.yOffset = forcedY;
|
|
291
|
+
|
|
292
|
+
//TODO: vectors can influence height in some situations
|
|
293
|
+
if (nbPages > 1) {
|
|
294
|
+
// on out-of-context blocs (headers, footers, background) height should be the whole DocumentContext height
|
|
295
|
+
if (forcedX !== undefined || forcedY !== undefined) {
|
|
296
|
+
fragment.height = unbreakableContext.getCurrentPage().pageSize.height - unbreakableContext.pageMargins.top - unbreakableContext.pageMargins.bottom;
|
|
297
|
+
} else {
|
|
298
|
+
fragment.height = this.writer.context.getCurrentPage().pageSize.height - this.writer.context.pageMargins.top - this.writer.context.pageMargins.bottom;
|
|
299
|
+
for (var i = 0, l = this.repeatables.length; i < l; i++) {
|
|
300
|
+
fragment.height -= this.repeatables[i].height;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
} else {
|
|
304
|
+
fragment.height = unbreakableContext.y;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (forcedX !== undefined || forcedY !== undefined) {
|
|
308
|
+
this.writer.addFragment(fragment, true, true, true);
|
|
309
|
+
} else {
|
|
310
|
+
return this.addFragment(fragment, undefined, undefined, undefined, isFooter);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
PageElementWriter.prototype.commitUnbreakableBlock_test = function (forcedX, forcedY) {
|
|
317
|
+
if (--this.transactionLevel === 0) {
|
|
318
|
+
var unbreakableContext = this.writer.context;
|
|
319
|
+
this.writer.popContext();
|
|
320
|
+
|
|
321
|
+
var nbPages = unbreakableContext.pages.length;
|
|
322
|
+
if (nbPages > 0) {
|
|
323
|
+
var fragment = unbreakableContext.pages[0];
|
|
324
|
+
fragment.xOffset = forcedX;
|
|
325
|
+
fragment.yOffset = forcedY;
|
|
326
|
+
fragment.height = unbreakableContext.y;
|
|
327
|
+
return this.addFragment_test(fragment);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
PageElementWriter.prototype.currentBlockToRepeatable = function () {
|
|
333
|
+
var unbreakableContext = this.writer.context;
|
|
334
|
+
var rep = { items: [] };
|
|
335
|
+
|
|
336
|
+
unbreakableContext.pages[0].items.forEach(function (item) {
|
|
337
|
+
rep.items.push(item);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
rep.xOffset = this.originalX;
|
|
341
|
+
|
|
342
|
+
//TODO: vectors can influence height in some situations
|
|
343
|
+
rep.height = unbreakableContext.y;
|
|
344
|
+
|
|
345
|
+
rep.insertedOnPages = [];
|
|
346
|
+
|
|
347
|
+
return rep;
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
PageElementWriter.prototype.pushToRepeatables = function (rep) {
|
|
351
|
+
this.repeatables.push(rep);
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
PageElementWriter.prototype.popFromRepeatables = function () {
|
|
355
|
+
this.repeatables.pop();
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
PageElementWriter.prototype.context = function () {
|
|
359
|
+
return this.writer.context;
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
module.exports = PageElementWriter;
|