pdfmake 0.2.1 → 0.3.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/CHANGELOG.md +8 -14
  2. package/README.md +8 -6
  3. package/build/pdfmake.js +31416 -28217
  4. package/build/pdfmake.js.map +1 -1
  5. package/build/pdfmake.min.js +2 -2
  6. package/build/pdfmake.min.js.map +1 -1
  7. package/build/standard-fonts/Courier.js +27 -0
  8. package/build/standard-fonts/Helvetica.js +27 -0
  9. package/build/standard-fonts/Symbol.js +21 -0
  10. package/build/standard-fonts/Times.js +27 -0
  11. package/build/standard-fonts/ZapfDingbats.js +21 -0
  12. package/build/vfs_fonts.js +2 -2
  13. package/build-vfs.js +3 -3
  14. package/fonts/Roboto/Roboto-Italic.ttf +0 -0
  15. package/fonts/Roboto/Roboto-Medium.ttf +0 -0
  16. package/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
  17. package/fonts/Roboto/Roboto-Regular.ttf +0 -0
  18. package/fonts/Roboto.js +8 -0
  19. package/js/3rd-party/svg-to-pdfkit/source.js +4301 -0
  20. package/js/3rd-party/svg-to-pdfkit.js +11 -0
  21. package/js/DocMeasure.js +750 -0
  22. package/js/DocPreprocessor.js +285 -0
  23. package/js/DocumentContext.js +306 -0
  24. package/js/ElementWriter.js +377 -0
  25. package/js/LayoutBuilder.js +833 -0
  26. package/js/Line.js +125 -0
  27. package/js/OutputDocument.js +86 -0
  28. package/js/OutputDocumentServer.js +34 -0
  29. package/js/PDFDocument.js +163 -0
  30. package/js/PageElementWriter.js +161 -0
  31. package/js/PageSize.js +88 -0
  32. package/js/Printer.js +238 -0
  33. package/js/Renderer.js +433 -0
  34. package/js/SVGMeasure.js +89 -0
  35. package/js/StyleContextStack.js +206 -0
  36. package/js/TableProcessor.js +590 -0
  37. package/js/TextBreaker.js +182 -0
  38. package/js/TextDecorator.js +181 -0
  39. package/js/TextInlines.js +248 -0
  40. package/js/URLResolver.js +79 -0
  41. package/js/base.js +69 -0
  42. package/js/browser-extensions/OutputDocumentBrowser.js +131 -0
  43. package/js/browser-extensions/URLBrowserResolver.js +89 -0
  44. package/js/browser-extensions/fonts/Roboto.js +42 -0
  45. package/js/browser-extensions/index.js +70 -0
  46. package/js/browser-extensions/pdfMake.js +17 -0
  47. package/js/browser-extensions/standard-fonts/Courier.js +42 -0
  48. package/js/browser-extensions/standard-fonts/Helvetica.js +42 -0
  49. package/js/browser-extensions/standard-fonts/Symbol.js +27 -0
  50. package/js/browser-extensions/standard-fonts/Times.js +42 -0
  51. package/js/browser-extensions/standard-fonts/ZapfDingbats.js +27 -0
  52. package/js/browser-extensions/virtual-fs-cjs.js +3 -0
  53. package/js/columnCalculator.js +142 -0
  54. package/js/helpers/node.js +122 -0
  55. package/js/helpers/tools.js +48 -0
  56. package/js/helpers/variableType.js +52 -0
  57. package/js/index.js +21 -0
  58. package/js/qrEnc.js +810 -0
  59. package/js/standardPageSizes.js +57 -0
  60. package/js/tableLayouts.js +127 -0
  61. package/js/virtual-fs.js +77 -0
  62. package/package.json +31 -25
  63. package/src/3rd-party/svg-to-pdfkit/LICENSE +9 -0
  64. package/src/3rd-party/svg-to-pdfkit/source.js +2552 -0
  65. package/src/3rd-party/svg-to-pdfkit.js +3 -0
  66. package/src/DocMeasure.js +694 -0
  67. package/src/DocPreprocessor.js +258 -0
  68. package/src/DocumentContext.js +309 -0
  69. package/src/ElementWriter.js +368 -0
  70. package/src/LayoutBuilder.js +814 -0
  71. package/src/Line.js +114 -0
  72. package/src/OutputDocument.js +78 -0
  73. package/src/OutputDocumentServer.js +26 -0
  74. package/src/PDFDocument.js +148 -0
  75. package/src/PageElementWriter.js +156 -0
  76. package/src/PageSize.js +53 -0
  77. package/src/Printer.js +220 -0
  78. package/src/Renderer.js +370 -0
  79. package/src/SVGMeasure.js +79 -0
  80. package/src/StyleContextStack.js +216 -0
  81. package/src/TableProcessor.js +558 -0
  82. package/src/TextBreaker.js +149 -0
  83. package/src/TextDecorator.js +161 -0
  84. package/src/TextInlines.js +223 -0
  85. package/src/URLResolver.js +69 -0
  86. package/src/base.js +61 -0
  87. package/src/browser-extensions/OutputDocumentBrowser.js +117 -0
  88. package/src/browser-extensions/URLBrowserResolver.js +46 -53
  89. package/src/browser-extensions/fonts/Roboto.js +27 -0
  90. package/src/browser-extensions/index.js +55 -0
  91. package/src/browser-extensions/pdfMake.js +10 -287
  92. package/src/browser-extensions/standard-fonts/Courier.js +27 -0
  93. package/src/browser-extensions/standard-fonts/Helvetica.js +27 -0
  94. package/src/browser-extensions/standard-fonts/Symbol.js +21 -0
  95. package/src/browser-extensions/standard-fonts/Times.js +27 -0
  96. package/src/browser-extensions/standard-fonts/ZapfDingbats.js +21 -0
  97. package/src/browser-extensions/virtual-fs-cjs.js +1 -0
  98. package/src/columnCalculator.js +29 -32
  99. package/src/helpers/node.js +110 -0
  100. package/src/helpers/tools.js +39 -0
  101. package/src/helpers/variableType.js +39 -0
  102. package/src/index.js +16 -0
  103. package/src/qrEnc.js +15 -10
  104. package/src/standardPageSizes.js +1 -3
  105. package/src/tableLayouts.js +100 -0
  106. package/src/virtual-fs.js +66 -0
  107. package/standard-fonts/Courier.js +8 -0
  108. package/standard-fonts/Helvetica.js +9 -0
  109. package/standard-fonts/Symbol.js +5 -0
  110. package/standard-fonts/Times.js +8 -0
  111. package/standard-fonts/ZapfDingbats.js +5 -0
  112. package/src/browser-extensions/virtual-fs.js +0 -55
  113. package/src/docMeasure.js +0 -807
  114. package/src/docPreprocessor.js +0 -255
  115. package/src/documentContext.js +0 -314
  116. package/src/elementWriter.js +0 -322
  117. package/src/fontProvider.js +0 -68
  118. package/src/helpers.js +0 -113
  119. package/src/imageMeasure.js +0 -51
  120. package/src/layoutBuilder.js +0 -807
  121. package/src/line.js +0 -91
  122. package/src/pageElementWriter.js +0 -174
  123. package/src/pdfKitEngine.js +0 -21
  124. package/src/printer.js +0 -685
  125. package/src/styleContextStack.js +0 -179
  126. package/src/svgMeasure.js +0 -70
  127. package/src/tableProcessor.js +0 -542
  128. package/src/textDecorator.js +0 -151
  129. package/src/textTools.js +0 -373
  130. package/src/traversalTracker.js +0 -47
@@ -0,0 +1,3 @@
1
+ import SVGtoPDF from './svg-to-pdfkit/source.js';
2
+
3
+ export default SVGtoPDF;
@@ -0,0 +1,694 @@
1
+ import TextInlines from './TextInlines';
2
+ import StyleContextStack from './StyleContextStack';
3
+ import ColumnCalculator from './columnCalculator';
4
+ import { defaultTableLayout } from './tableLayouts';
5
+ import { isString, isNumber, isObject } from './helpers/variableType';
6
+ import { stringifyNode, getNodeId, getNodeMargin } from './helpers/node';
7
+ import { pack } from './helpers/tools';
8
+ import qrEncoder from './qrEnc.js';
9
+
10
+ class DocMeasure {
11
+ constructor(
12
+ pdfDocument,
13
+ styleDictionary,
14
+ defaultStyle,
15
+ svgMeasure,
16
+ tableLayouts
17
+ ) {
18
+ this.pdfDocument = pdfDocument;
19
+ this.textInlines = new TextInlines(pdfDocument);
20
+ this.styleStack = new StyleContextStack(styleDictionary, defaultStyle);
21
+ this.svgMeasure = svgMeasure;
22
+ this.tableLayouts = tableLayouts;
23
+ this.autoImageIndex = 1;
24
+ }
25
+
26
+ /**
27
+ * Measures all nodes and sets min/max-width properties required for the second
28
+ * layout-pass.
29
+ *
30
+ * @param {object} docStructure document-definition-object
31
+ * @returns {object} document-measurement-object
32
+ */
33
+ measureDocument(docStructure) {
34
+ return this.measureNode(docStructure);
35
+ }
36
+
37
+ measureNode(node) {
38
+ return this.styleStack.auto(node, () => {
39
+ // TODO: refactor + rethink whether this is the proper way to handle margins
40
+ node._margin = getNodeMargin(node, this.styleStack);
41
+
42
+ if (node.columns) {
43
+ return extendMargins(this.measureColumns(node));
44
+ } else if (node.stack) {
45
+ return extendMargins(this.measureVerticalContainer(node));
46
+ } else if (node.ul) {
47
+ return extendMargins(this.measureUnorderedList(node));
48
+ } else if (node.ol) {
49
+ return extendMargins(this.measureOrderedList(node));
50
+ } else if (node.table) {
51
+ return extendMargins(this.measureTable(node));
52
+ } else if (node.text !== undefined) {
53
+ return extendMargins(this.measureLeaf(node));
54
+ } else if (node.toc) {
55
+ return extendMargins(this.measureToc(node));
56
+ } else if (node.image) {
57
+ return extendMargins(this.measureImage(node));
58
+ } else if (node.svg) {
59
+ return extendMargins(this.measureSVG(node));
60
+ } else if (node.canvas) {
61
+ return extendMargins(this.measureCanvas(node));
62
+ } else if (node.qr) {
63
+ return extendMargins(this.measureQr(node));
64
+ } else {
65
+ throw new Error(`Unrecognized document structure: ${stringifyNode(node)}`);
66
+ }
67
+ });
68
+
69
+ function extendMargins(node) {
70
+ let margin = node._margin;
71
+
72
+ if (margin) {
73
+ node._minWidth += margin[0] + margin[2];
74
+ node._maxWidth += margin[0] + margin[2];
75
+ }
76
+
77
+ return node;
78
+ }
79
+ }
80
+
81
+ measureImageWithDimensions(node, dimensions) {
82
+ if (node.fit) {
83
+ let factor = (dimensions.width / dimensions.height > node.fit[0] / node.fit[1]) ? node.fit[0] / dimensions.width : node.fit[1] / dimensions.height;
84
+ node._width = node._minWidth = node._maxWidth = dimensions.width * factor;
85
+ node._height = dimensions.height * factor;
86
+ } else {
87
+ node._width = node._minWidth = node._maxWidth = node.width || dimensions.width;
88
+ node._height = node.height || (dimensions.height * node._width / dimensions.width);
89
+
90
+ if (isNumber(node.maxWidth) && node.maxWidth < node._width) {
91
+ node._width = node._minWidth = node._maxWidth = node.maxWidth;
92
+ node._height = node._width * dimensions.height / dimensions.width;
93
+ }
94
+
95
+ if (isNumber(node.maxHeight) && node.maxHeight < node._height) {
96
+ node._height = node.maxHeight;
97
+ node._width = node._minWidth = node._maxWidth = node._height * dimensions.width / dimensions.height;
98
+ }
99
+
100
+ if (isNumber(node.minWidth) && node.minWidth > node._width) {
101
+ node._width = node._minWidth = node._maxWidth = node.minWidth;
102
+ node._height = node._width * dimensions.height / dimensions.width;
103
+ }
104
+
105
+ if (isNumber(node.minHeight) && node.minHeight > node._height) {
106
+ node._height = node.minHeight;
107
+ node._width = node._minWidth = node._maxWidth = node._height * dimensions.width / dimensions.height;
108
+ }
109
+ }
110
+
111
+ node._alignment = this.styleStack.getProperty('alignment');
112
+ }
113
+
114
+ convertIfBase64Image(node) {
115
+ if (/^data:image\/(jpeg|jpg|png);base64,/.test(node.image)) { // base64 image
116
+ let label = `$$pdfmake$$${this.autoImageIndex++}`;
117
+ this.pdfDocument.images[label] = node.image;
118
+ node.image = label;
119
+ }
120
+ }
121
+
122
+ measureImage(node) {
123
+ this.convertIfBase64Image(node);
124
+
125
+ let image = this.pdfDocument.provideImage(node.image);
126
+ let imageSize = { width: image.width, height: image.height };
127
+
128
+ this.measureImageWithDimensions(node, imageSize);
129
+
130
+ return node;
131
+ }
132
+
133
+ measureSVG(node) {
134
+ let dimensions = this.svgMeasure.measureSVG(node.svg);
135
+
136
+ this.measureImageWithDimensions(node, dimensions);
137
+
138
+ node.font = this.styleStack.getProperty('font');
139
+
140
+ // scale SVG based on final dimension
141
+ node.svg = this.svgMeasure.writeDimensions(node.svg, { width: node._width, height: node._height });
142
+
143
+ return node;
144
+ }
145
+
146
+ measureLeaf(node) {
147
+
148
+ if (node._textRef && node._textRef._textNodeRef.text) {
149
+ node.text = node._textRef._textNodeRef.text;
150
+ }
151
+
152
+ // Make sure style properties of the node itself are considered when building inlines.
153
+ // We could also just pass [node] to buildInlines, but that fails for bullet points.
154
+ let styleStack = this.styleStack.clone();
155
+ styleStack.push(node);
156
+
157
+ let data = this.textInlines.buildInlines(node.text, styleStack);
158
+
159
+ node._inlines = data.items;
160
+ node._minWidth = data.minWidth;
161
+ node._maxWidth = data.maxWidth;
162
+
163
+ return node;
164
+ }
165
+
166
+ measureToc(node) {
167
+ if (node.toc.title) {
168
+ node.toc.title = this.measureNode(node.toc.title);
169
+ }
170
+
171
+ if (node.toc._items.length > 0) {
172
+ let body = [];
173
+ let textStyle = node.toc.textStyle || {};
174
+ let numberStyle = node.toc.numberStyle || textStyle;
175
+ let textMargin = node.toc.textMargin || [0, 0, 0, 0];
176
+ for (let i = 0, l = node.toc._items.length; i < l; i++) {
177
+ let item = node.toc._items[i];
178
+ let lineStyle = item._textNodeRef.tocStyle || textStyle;
179
+ let lineMargin = item._textNodeRef.tocMargin || textMargin;
180
+ let lineNumberStyle = item._textNodeRef.tocNumberStyle || numberStyle;
181
+ let destination = getNodeId(item._nodeRef);
182
+ body.push([
183
+ { text: item._textNodeRef.text, linkToDestination: destination, alignment: 'left', style: lineStyle, margin: lineMargin },
184
+ { text: '00000', linkToDestination: destination, alignment: 'right', _tocItemRef: item._nodeRef, style: lineNumberStyle, margin: [0, lineMargin[1], 0, lineMargin[3]] }
185
+ ]);
186
+ }
187
+
188
+ node.toc._table = {
189
+ table: {
190
+ dontBreakRows: true,
191
+ widths: ['*', 'auto'],
192
+ body: body
193
+ },
194
+ layout: 'noBorders'
195
+ };
196
+
197
+ node.toc._table = this.measureNode(node.toc._table);
198
+ }
199
+
200
+ return node;
201
+ }
202
+
203
+ measureVerticalContainer(node) {
204
+ let items = node.stack;
205
+
206
+ node._minWidth = 0;
207
+ node._maxWidth = 0;
208
+
209
+ for (let i = 0, l = items.length; i < l; i++) {
210
+ items[i] = this.measureNode(items[i]);
211
+
212
+ node._minWidth = Math.max(node._minWidth, items[i]._minWidth);
213
+ node._maxWidth = Math.max(node._maxWidth, items[i]._maxWidth);
214
+ }
215
+
216
+ return node;
217
+ }
218
+
219
+ gapSizeForList() {
220
+ return this.textInlines.sizeOfText('9. ', this.styleStack);
221
+ }
222
+
223
+ buildUnorderedMarker(styleStack, gapSize, type) {
224
+ function buildDisc(gapSize, color) {
225
+ // TODO: ascender-based calculations
226
+ let radius = gapSize.fontSize / 6;
227
+ return {
228
+ canvas: [{
229
+ x: radius,
230
+ y: (gapSize.height / gapSize.lineHeight) + gapSize.descender - gapSize.fontSize / 3,
231
+ r1: radius,
232
+ r2: radius,
233
+ type: 'ellipse',
234
+ color: color
235
+ }]
236
+ };
237
+ }
238
+
239
+ function buildSquare(gapSize, color) {
240
+ // TODO: ascender-based calculations
241
+ let size = gapSize.fontSize / 3;
242
+ return {
243
+ canvas: [{
244
+ x: 0,
245
+ y: (gapSize.height / gapSize.lineHeight) + gapSize.descender - (gapSize.fontSize / 3) - (size / 2),
246
+ h: size,
247
+ w: size,
248
+ type: 'rect',
249
+ color: color
250
+ }]
251
+ };
252
+ }
253
+
254
+ function buildCircle(gapSize, color) {
255
+ // TODO: ascender-based calculations
256
+ let radius = gapSize.fontSize / 6;
257
+ return {
258
+ canvas: [{
259
+ x: radius,
260
+ y: (gapSize.height / gapSize.lineHeight) + gapSize.descender - gapSize.fontSize / 3,
261
+ r1: radius,
262
+ r2: radius,
263
+ type: 'ellipse',
264
+ lineColor: color
265
+ }]
266
+ };
267
+ }
268
+
269
+ let marker;
270
+ let color = styleStack.getProperty('markerColor') || styleStack.getProperty('color') || 'black';
271
+
272
+ switch (type) {
273
+ case 'circle':
274
+ marker = buildCircle(gapSize, color);
275
+ break;
276
+
277
+ case 'square':
278
+ marker = buildSquare(gapSize, color);
279
+ break;
280
+
281
+ case 'none':
282
+ marker = {};
283
+ break;
284
+
285
+ case 'disc':
286
+ default:
287
+ marker = buildDisc(gapSize, color);
288
+ break;
289
+ }
290
+
291
+ marker._minWidth = marker._maxWidth = gapSize.width;
292
+ marker._minHeight = marker._maxHeight = gapSize.height;
293
+
294
+ return marker;
295
+ }
296
+
297
+ buildOrderedMarker(counter, styleStack, type, separator) {
298
+ function prepareAlpha(counter) {
299
+ function toAlpha(num) {
300
+ return (num >= 26 ? toAlpha((num / 26 >> 0) - 1) : '') + 'abcdefghijklmnopqrstuvwxyz'[num % 26 >> 0];
301
+ }
302
+
303
+ if (counter < 1) {
304
+ return counter.toString();
305
+ }
306
+
307
+ return toAlpha(counter - 1);
308
+ }
309
+
310
+ function prepareRoman(counter) {
311
+ if (counter < 1 || counter > 4999) {
312
+ return counter.toString();
313
+ }
314
+ let num = counter;
315
+ let lookup = { M: 1000, CM: 900, D: 500, CD: 400, C: 100, XC: 90, L: 50, XL: 40, X: 10, IX: 9, V: 5, IV: 4, I: 1 };
316
+ let roman = '';
317
+ for (let i in lookup) {
318
+ while (num >= lookup[i]) {
319
+ roman += i;
320
+ num -= lookup[i];
321
+ }
322
+ }
323
+ return roman;
324
+ }
325
+
326
+ function prepareDecimal(counter) {
327
+ return counter.toString();
328
+ }
329
+
330
+ let counterText;
331
+ switch (type) {
332
+ case 'none':
333
+ counterText = null;
334
+ break;
335
+
336
+ case 'upper-alpha':
337
+ counterText = prepareAlpha(counter).toUpperCase();
338
+ break;
339
+
340
+ case 'lower-alpha':
341
+ counterText = prepareAlpha(counter);
342
+ break;
343
+
344
+ case 'upper-roman':
345
+ counterText = prepareRoman(counter);
346
+ break;
347
+
348
+ case 'lower-roman':
349
+ counterText = prepareRoman(counter).toLowerCase();
350
+ break;
351
+
352
+ case 'decimal':
353
+ default:
354
+ counterText = prepareDecimal(counter);
355
+ break;
356
+ }
357
+
358
+ if (counterText === null) {
359
+ return {};
360
+ }
361
+
362
+ if (separator) {
363
+ if (Array.isArray(separator)) {
364
+ if (separator[0]) {
365
+ counterText = separator[0] + counterText;
366
+ }
367
+
368
+ if (separator[1]) {
369
+ counterText += separator[1];
370
+ }
371
+ counterText += ' ';
372
+ } else {
373
+ counterText += `${separator} `;
374
+ }
375
+ }
376
+
377
+ let textArray = { text: counterText };
378
+ let markerColor = styleStack.getProperty('markerColor');
379
+ if (markerColor) {
380
+ textArray.color = markerColor;
381
+ }
382
+
383
+ return { _inlines: this.textInlines.buildInlines(textArray, styleStack).items };
384
+ }
385
+
386
+ measureUnorderedList(node) {
387
+ let style = this.styleStack.clone();
388
+ let items = node.ul;
389
+ node.type = node.type || 'disc';
390
+ node._gapSize = this.gapSizeForList();
391
+ node._minWidth = 0;
392
+ node._maxWidth = 0;
393
+
394
+ for (let i = 0, l = items.length; i < l; i++) {
395
+ let item = items[i] = this.measureNode(items[i]);
396
+
397
+ if (!item.ol && !item.ul) {
398
+ item.listMarker = this.buildUnorderedMarker(style, node._gapSize, item.listType || node.type);
399
+ }
400
+
401
+ node._minWidth = Math.max(node._minWidth, items[i]._minWidth + node._gapSize.width);
402
+ node._maxWidth = Math.max(node._maxWidth, items[i]._maxWidth + node._gapSize.width);
403
+ }
404
+
405
+ return node;
406
+ }
407
+
408
+ measureOrderedList(node) {
409
+ let style = this.styleStack.clone();
410
+ let items = node.ol;
411
+ node.type = node.type || 'decimal';
412
+ node.separator = node.separator || '.';
413
+ node.reversed = node.reversed || false;
414
+ if (!isNumber(node.start)) {
415
+ node.start = node.reversed ? items.length : 1;
416
+ }
417
+ node._gapSize = this.gapSizeForList();
418
+ node._minWidth = 0;
419
+ node._maxWidth = 0;
420
+
421
+ let counter = node.start;
422
+ for (let i = 0, l = items.length; i < l; i++) {
423
+ let item = items[i] = this.measureNode(items[i]);
424
+
425
+ if (!item.ol && !item.ul) {
426
+ let counterValue = isNumber(item.counter) ? item.counter : counter;
427
+ item.listMarker = this.buildOrderedMarker(counterValue, style, item.listType || node.type, node.separator);
428
+ if (item.listMarker._inlines) {
429
+ node._gapSize.width = Math.max(node._gapSize.width, item.listMarker._inlines[0].width);
430
+ }
431
+ } // TODO: else - nested lists numbering
432
+
433
+ node._minWidth = Math.max(node._minWidth, items[i]._minWidth);
434
+ node._maxWidth = Math.max(node._maxWidth, items[i]._maxWidth);
435
+
436
+ if (node.reversed) {
437
+ counter--;
438
+ } else {
439
+ counter++;
440
+ }
441
+ }
442
+
443
+ node._minWidth += node._gapSize.width;
444
+ node._maxWidth += node._gapSize.width;
445
+
446
+ for (let i = 0, l = items.length; i < l; i++) {
447
+ let item = items[i];
448
+ if (!item.ol && !item.ul) {
449
+ item.listMarker._minWidth = item.listMarker._maxWidth = node._gapSize.width;
450
+ }
451
+ }
452
+
453
+ return node;
454
+ }
455
+
456
+ measureColumns(node) {
457
+ let columns = node.columns;
458
+ node._gap = this.styleStack.getProperty('columnGap') || 0;
459
+
460
+ for (let i = 0, l = columns.length; i < l; i++) {
461
+ columns[i] = this.measureNode(columns[i]);
462
+ }
463
+
464
+ let measures = ColumnCalculator.measureMinMax(columns);
465
+
466
+ let numGaps = (columns.length > 0) ? (columns.length - 1) : 0;
467
+ node._minWidth = measures.min + node._gap * numGaps;
468
+ node._maxWidth = measures.max + node._gap * numGaps;
469
+
470
+ return node;
471
+ }
472
+
473
+ measureTable(node) {
474
+ extendTableWidths(node);
475
+ node._layout = getLayout(this.tableLayouts);
476
+ node._offsets = getOffsets(node._layout);
477
+
478
+ let colSpans = [];
479
+ let col;
480
+ let row;
481
+ let cols;
482
+ let rows;
483
+
484
+ for (col = 0, cols = node.table.body[0].length; col < cols; col++) {
485
+ let c = node.table.widths[col];
486
+ c._minWidth = 0;
487
+ c._maxWidth = 0;
488
+
489
+ for (row = 0, rows = node.table.body.length; row < rows; row++) {
490
+ let rowData = node.table.body[row];
491
+ let data = rowData[col];
492
+ if (data === undefined) {
493
+ throw new Error(`Malformed table row, a cell is undefined.\nRow index: ${row}\nColumn index: ${col}\nRow data: ${stringifyNode(rowData)}`);
494
+ }
495
+ if (data === null) { // transform to object
496
+ data = '';
497
+ }
498
+
499
+ if (!data._span) {
500
+ data = rowData[col] = this.styleStack.auto(data, measureCb(this, data));
501
+
502
+ if (data.colSpan && data.colSpan > 1) {
503
+ markSpans(rowData, col, data.colSpan);
504
+ colSpans.push({ col: col, span: data.colSpan, minWidth: data._minWidth, maxWidth: data._maxWidth });
505
+ } else {
506
+ c._minWidth = Math.max(c._minWidth, data._minWidth);
507
+ c._maxWidth = Math.max(c._maxWidth, data._maxWidth);
508
+ }
509
+ }
510
+
511
+ if (data.rowSpan && data.rowSpan > 1) {
512
+ markVSpans(node.table, row, col, data.rowSpan);
513
+ }
514
+ }
515
+ }
516
+
517
+ extendWidthsForColSpans();
518
+
519
+ let measures = ColumnCalculator.measureMinMax(node.table.widths);
520
+
521
+ node._minWidth = measures.min + node._offsets.total;
522
+ node._maxWidth = measures.max + node._offsets.total;
523
+
524
+ return node;
525
+
526
+ function measureCb(_this, data) {
527
+ return () => {
528
+ if (isObject(data)) {
529
+ data.fillColor = _this.styleStack.getProperty('fillColor');
530
+ data.fillOpacity = _this.styleStack.getProperty('fillOpacity');
531
+ }
532
+ return _this.measureNode(data);
533
+ };
534
+ }
535
+
536
+ function getLayout(tableLayouts) {
537
+ let layout = node.layout;
538
+
539
+ if (isString(layout)) {
540
+ layout = tableLayouts[layout];
541
+ }
542
+
543
+ return pack(defaultTableLayout, layout);
544
+ }
545
+
546
+ function getOffsets(layout) {
547
+ let offsets = [];
548
+ let totalOffset = 0;
549
+ let prevRightPadding = 0;
550
+
551
+ for (let i = 0, l = node.table.widths.length; i < l; i++) {
552
+ let lOffset = prevRightPadding + layout.vLineWidth(i, node) + layout.paddingLeft(i, node);
553
+ offsets.push(lOffset);
554
+ totalOffset += lOffset;
555
+ prevRightPadding = layout.paddingRight(i, node);
556
+ }
557
+
558
+ totalOffset += prevRightPadding + layout.vLineWidth(node.table.widths.length, node);
559
+
560
+ return {
561
+ total: totalOffset,
562
+ offsets: offsets
563
+ };
564
+ }
565
+
566
+ function extendWidthsForColSpans() {
567
+ let q;
568
+ let j;
569
+
570
+ for (let i = 0, l = colSpans.length; i < l; i++) {
571
+ let span = colSpans[i];
572
+
573
+ let currentMinMax = getMinMax(span.col, span.span, node._offsets);
574
+ let minDifference = span.minWidth - currentMinMax.minWidth;
575
+ let maxDifference = span.maxWidth - currentMinMax.maxWidth;
576
+
577
+ if (minDifference > 0) {
578
+ q = minDifference / span.span;
579
+
580
+ for (j = 0; j < span.span; j++) {
581
+ node.table.widths[span.col + j]._minWidth += q;
582
+ }
583
+ }
584
+
585
+ if (maxDifference > 0) {
586
+ q = maxDifference / span.span;
587
+
588
+ for (j = 0; j < span.span; j++) {
589
+ node.table.widths[span.col + j]._maxWidth += q;
590
+ }
591
+ }
592
+ }
593
+ }
594
+
595
+ function getMinMax(col, span, offsets) {
596
+ let result = { minWidth: 0, maxWidth: 0 };
597
+
598
+ for (let i = 0; i < span; i++) {
599
+ result.minWidth += node.table.widths[col + i]._minWidth + (i ? offsets.offsets[col + i] : 0);
600
+ result.maxWidth += node.table.widths[col + i]._maxWidth + (i ? offsets.offsets[col + i] : 0);
601
+ }
602
+
603
+ return result;
604
+ }
605
+
606
+ function markSpans(rowData, col, span) {
607
+ for (let i = 1; i < span; i++) {
608
+ rowData[col + i] = {
609
+ _span: true,
610
+ _minWidth: 0,
611
+ _maxWidth: 0,
612
+ rowSpan: rowData[col].rowSpan
613
+ };
614
+ }
615
+ }
616
+
617
+ function markVSpans(table, row, col, span) {
618
+ for (let i = 1; i < span; i++) {
619
+ table.body[row + i][col] = {
620
+ _span: true,
621
+ _minWidth: 0,
622
+ _maxWidth: 0,
623
+ fillColor: table.body[row][col].fillColor,
624
+ fillOpacity: table.body[row][col].fillOpacity
625
+ };
626
+ }
627
+ }
628
+
629
+ function extendTableWidths(node) {
630
+ if (!node.table.widths) {
631
+ node.table.widths = 'auto';
632
+ }
633
+
634
+ if (isString(node.table.widths)) {
635
+ node.table.widths = [node.table.widths];
636
+
637
+ while (node.table.widths.length < node.table.body[0].length) {
638
+ node.table.widths.push(node.table.widths[node.table.widths.length - 1]);
639
+ }
640
+ }
641
+
642
+ for (let i = 0, l = node.table.widths.length; i < l; i++) {
643
+ let w = node.table.widths[i];
644
+ if (isNumber(w) || isString(w)) {
645
+ node.table.widths[i] = { width: w };
646
+ }
647
+ }
648
+ }
649
+ }
650
+
651
+ measureCanvas(node) {
652
+ let w = 0;
653
+ let h = 0;
654
+
655
+ for (let i = 0, l = node.canvas.length; i < l; i++) {
656
+ let vector = node.canvas[i];
657
+
658
+ switch (vector.type) {
659
+ case 'ellipse':
660
+ w = Math.max(w, vector.x + vector.r1);
661
+ h = Math.max(h, vector.y + vector.r2);
662
+ break;
663
+ case 'rect':
664
+ w = Math.max(w, vector.x + vector.w);
665
+ h = Math.max(h, vector.y + vector.h);
666
+ break;
667
+ case 'line':
668
+ w = Math.max(w, vector.x1, vector.x2);
669
+ h = Math.max(h, vector.y1, vector.y2);
670
+ break;
671
+ case 'polyline':
672
+ for (let i2 = 0, l2 = vector.points.length; i2 < l2; i2++) {
673
+ w = Math.max(w, vector.points[i2].x);
674
+ h = Math.max(h, vector.points[i2].y);
675
+ }
676
+ break;
677
+ }
678
+ }
679
+
680
+ node._minWidth = node._maxWidth = w;
681
+ node._minHeight = node._maxHeight = h;
682
+ node._alignment = this.styleStack.getProperty('alignment');
683
+
684
+ return node;
685
+ }
686
+
687
+ measureQr(node) {
688
+ node = qrEncoder.measure(node);
689
+ node._alignment = this.styleStack.getProperty('alignment');
690
+ return node;
691
+ }
692
+ }
693
+
694
+ export default DocMeasure;