pdfmake 0.3.2 → 0.3.4

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 (94) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/LICENSE +21 -21
  3. package/README.md +75 -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 +64813 -64584
  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/3rd-party/svg-to-pdfkit/source.js +1 -1
  22. package/js/DocMeasure.js +11 -6
  23. package/js/DocumentContext.js +8 -3
  24. package/js/ElementWriter.js +42 -16
  25. package/js/LayoutBuilder.js +144 -78
  26. package/js/Line.js +16 -16
  27. package/js/OutputDocument.js +10 -10
  28. package/js/OutputDocumentServer.js +3 -3
  29. package/js/PDFDocument.js +3 -3
  30. package/js/PageElementWriter.js +15 -9
  31. package/js/Printer.js +28 -28
  32. package/js/Renderer.js +40 -8
  33. package/js/SVGMeasure.js +10 -10
  34. package/js/StyleContextStack.js +74 -51
  35. package/js/TableProcessor.js +14 -0
  36. package/js/TextBreaker.js +17 -17
  37. package/js/TextDecorator.js +12 -3
  38. package/js/TextInlines.js +34 -33
  39. package/js/base.js +4 -4
  40. package/js/browser-extensions/OutputDocumentBrowser.js +24 -24
  41. package/js/columnCalculator.js +2 -2
  42. package/js/helpers/node.js +47 -23
  43. package/js/helpers/variableType.js +18 -18
  44. package/js/qrEnc.js +38 -38
  45. package/js/virtual-fs.js +11 -11
  46. package/package.json +12 -12
  47. package/src/3rd-party/svg-to-pdfkit/LICENSE +9 -9
  48. package/src/3rd-party/svg-to-pdfkit/source.js +2745 -2745
  49. package/src/3rd-party/svg-to-pdfkit.js +3 -3
  50. package/src/DocMeasure.js +745 -738
  51. package/src/DocPreprocessor.js +283 -283
  52. package/src/DocumentContext.js +345 -338
  53. package/src/ElementWriter.js +441 -417
  54. package/src/LayoutBuilder.js +1336 -1258
  55. package/src/Line.js +114 -114
  56. package/src/OutputDocument.js +64 -64
  57. package/src/OutputDocumentServer.js +32 -32
  58. package/src/PDFDocument.js +174 -174
  59. package/src/PageElementWriter.js +187 -179
  60. package/src/PageSize.js +53 -53
  61. package/src/Printer.js +306 -306
  62. package/src/Renderer.js +445 -409
  63. package/src/SVGMeasure.js +109 -109
  64. package/src/StyleContextStack.js +208 -179
  65. package/src/TableProcessor.js +620 -602
  66. package/src/TextBreaker.js +168 -168
  67. package/src/TextDecorator.js +175 -161
  68. package/src/TextInlines.js +224 -223
  69. package/src/URLResolver.js +43 -43
  70. package/src/base.js +70 -70
  71. package/src/browser-extensions/OutputDocumentBrowser.js +80 -80
  72. package/src/browser-extensions/fonts/Roboto.js +27 -27
  73. package/src/browser-extensions/index.js +55 -55
  74. package/src/browser-extensions/pdfMake.js +1 -1
  75. package/src/browser-extensions/standard-fonts/Courier.js +27 -27
  76. package/src/browser-extensions/standard-fonts/Helvetica.js +27 -27
  77. package/src/browser-extensions/standard-fonts/Symbol.js +21 -21
  78. package/src/browser-extensions/standard-fonts/Times.js +27 -27
  79. package/src/browser-extensions/standard-fonts/ZapfDingbats.js +21 -21
  80. package/src/browser-extensions/virtual-fs-cjs.js +1 -1
  81. package/src/columnCalculator.js +154 -154
  82. package/src/helpers/node.js +134 -110
  83. package/src/helpers/tools.js +44 -44
  84. package/src/helpers/variableType.js +50 -50
  85. package/src/index.js +16 -16
  86. package/src/qrEnc.js +796 -796
  87. package/src/standardPageSizes.js +52 -52
  88. package/src/tableLayouts.js +100 -100
  89. package/src/virtual-fs.js +66 -66
  90. package/standard-fonts/Courier.js +8 -8
  91. package/standard-fonts/Helvetica.js +8 -8
  92. package/standard-fonts/Symbol.js +5 -5
  93. package/standard-fonts/Times.js +8 -8
  94. package/standard-fonts/ZapfDingbats.js +5 -5
package/src/Renderer.js CHANGED
@@ -1,409 +1,445 @@
1
- import TextDecorator from './TextDecorator';
2
- import TextInlines from './TextInlines';
3
- import { isNumber, isString } from './helpers/variableType';
4
- import SVGtoPDF from './3rd-party/svg-to-pdfkit';
5
-
6
- const findFont = (fonts, requiredFonts, defaultFont) => {
7
- for (let i = 0; i < requiredFonts.length; i++) {
8
- let requiredFont = requiredFonts[i].toLowerCase();
9
-
10
- for (let font in fonts) {
11
- if (font.toLowerCase() === requiredFont) {
12
- return font;
13
- }
14
- }
15
- }
16
-
17
- return defaultFont;
18
- };
19
-
20
- /**
21
- * Shift the "y" height of the text baseline up or down (superscript or subscript,
22
- * respectively). The exact shift can / should be changed according to standard
23
- * conventions.
24
- *
25
- * @param {number} y
26
- * @param {object} inline
27
- * @returns {number}
28
- */
29
- const offsetText = (y, inline) => {
30
- let newY = y;
31
- if (inline.sup) {
32
- newY -= inline.fontSize * 0.75;
33
- }
34
- if (inline.sub) {
35
- newY += inline.fontSize * 0.35;
36
- }
37
- return newY;
38
- };
39
-
40
- class Renderer {
41
- constructor(pdfDocument, progressCallback) {
42
- this.pdfDocument = pdfDocument;
43
- this.progressCallback = progressCallback;
44
- }
45
-
46
- renderPages(pages) {
47
- this.pdfDocument._pdfMakePages = pages; // TODO: Why?
48
-
49
- let totalItems = 0;
50
- if (this.progressCallback) {
51
- pages.forEach(page => {
52
- totalItems += page.items.length;
53
- });
54
- }
55
-
56
- let renderedItems = 0;
57
-
58
- for (let i = 0; i < pages.length; i++) {
59
- this.pdfDocument.addPage({ size: [pages[i].pageSize.width, pages[i].pageSize.height] });
60
-
61
- let page = pages[i];
62
- for (let ii = 0, il = page.items.length; ii < il; ii++) {
63
- let item = page.items[ii];
64
- switch (item.type) {
65
- case 'vector':
66
- this.renderVector(item.item);
67
- break;
68
- case 'line':
69
- this.renderLine(item.item, item.item.x, item.item.y);
70
- break;
71
- case 'image':
72
- this.renderImage(item.item);
73
- break;
74
- case 'svg':
75
- this.renderSVG(item.item);
76
- break;
77
- case 'attachment':
78
- this.renderAttachment(item.item);
79
- break;
80
- case 'beginClip':
81
- this.beginClip(item.item);
82
- break;
83
- case 'endClip':
84
- this.endClip();
85
- break;
86
- }
87
- renderedItems++;
88
- if (this.progressCallback) {
89
- this.progressCallback(renderedItems / totalItems);
90
- }
91
- }
92
- if (page.watermark) {
93
- this.renderWatermark(page);
94
- }
95
- }
96
- }
97
-
98
- renderLine(line, x, y) {
99
- function preparePageNodeRefLine(_pageNodeRef, inline) {
100
- let newWidth;
101
- let diffWidth;
102
- let textInlines = new TextInlines(null);
103
-
104
- if (_pageNodeRef.positions === undefined) {
105
- throw new Error('Page reference id not found');
106
- }
107
-
108
- let pageNumber = _pageNodeRef.positions[0].pageNumber.toString();
109
-
110
- inline.text = pageNumber;
111
- newWidth = textInlines.widthOfText(inline.text, inline);
112
- diffWidth = inline.width - newWidth;
113
- inline.width = newWidth;
114
-
115
- switch (inline.alignment) {
116
- case 'right':
117
- inline.x += diffWidth;
118
- break;
119
- case 'center':
120
- inline.x += diffWidth / 2;
121
- break;
122
- }
123
- }
124
-
125
- if (line._pageNodeRef) {
126
- preparePageNodeRefLine(line._pageNodeRef, line.inlines[0]);
127
- }
128
-
129
- x = x || 0;
130
- y = y || 0;
131
-
132
- let lineHeight = line.getHeight();
133
- let ascenderHeight = line.getAscenderHeight();
134
- let descent = lineHeight - ascenderHeight;
135
-
136
- const textDecorator = new TextDecorator(this.pdfDocument);
137
-
138
- textDecorator.drawBackground(line, x, y);
139
-
140
- //TODO: line.optimizeInlines();
141
- //TODO: lines without differently styled inlines should be written to pdf as one stream
142
- for (let i = 0, l = line.inlines.length; i < l; i++) {
143
- let inline = line.inlines[i];
144
- let shiftToBaseline = lineHeight - ((inline.font.ascender / 1000) * inline.fontSize) - descent;
145
-
146
- if (inline._pageNodeRef) {
147
- preparePageNodeRefLine(inline._pageNodeRef, inline);
148
- }
149
-
150
- let options = {
151
- lineBreak: false,
152
- textWidth: inline.width,
153
- characterSpacing: inline.characterSpacing,
154
- wordCount: 1,
155
- link: inline.link
156
- };
157
-
158
- if (inline.linkToDestination) {
159
- options.goTo = inline.linkToDestination;
160
- }
161
-
162
- if (line.id && i === 0) {
163
- options.destination = line.id;
164
- }
165
-
166
- if (inline.fontFeatures) {
167
- options.features = inline.fontFeatures;
168
- }
169
-
170
- let opacity = isNumber(inline.opacity) ? inline.opacity : 1;
171
- this.pdfDocument.opacity(opacity);
172
- this.pdfDocument.fill(inline.color || 'black');
173
-
174
- this.pdfDocument._font = inline.font;
175
- this.pdfDocument.fontSize(inline.fontSize);
176
-
177
- let shiftedY = offsetText(y + shiftToBaseline, inline);
178
- this.pdfDocument.text(inline.text, x + inline.x, shiftedY, options);
179
-
180
- if (inline.linkToPage) {
181
- this.pdfDocument.ref({ Type: 'Action', S: 'GoTo', D: [inline.linkToPage, 0, 0] }).end();
182
- this.pdfDocument.annotate(x + inline.x, shiftedY, inline.width, inline.height, { Subtype: 'Link', Dest: [inline.linkToPage - 1, 'XYZ', null, null, null] });
183
- }
184
- }
185
-
186
- // Decorations won't draw correctly for superscript
187
- textDecorator.drawDecorations(line, x, y);
188
- }
189
-
190
- renderVector(vector) {
191
- //TODO: pdf optimization (there's no need to write all properties everytime)
192
- this.pdfDocument.lineWidth(vector.lineWidth || 1);
193
- if (vector.dash) {
194
- this.pdfDocument.dash(vector.dash.length, { space: vector.dash.space || vector.dash.length, phase: vector.dash.phase || 0 });
195
- } else {
196
- this.pdfDocument.undash();
197
- }
198
- this.pdfDocument.lineJoin(vector.lineJoin || 'miter');
199
- this.pdfDocument.lineCap(vector.lineCap || 'butt');
200
-
201
- //TODO: clipping
202
-
203
- let gradient = null;
204
-
205
- switch (vector.type) {
206
- case 'ellipse':
207
- this.pdfDocument.ellipse(vector.x, vector.y, vector.r1, vector.r2);
208
-
209
- if (vector.linearGradient) {
210
- gradient = this.pdfDocument.linearGradient(vector.x - vector.r1, vector.y, vector.x + vector.r1, vector.y);
211
- }
212
- break;
213
- case 'rect':
214
- if (vector.r) {
215
- this.pdfDocument.roundedRect(vector.x, vector.y, vector.w, vector.h, vector.r);
216
- } else {
217
- this.pdfDocument.rect(vector.x, vector.y, vector.w, vector.h);
218
- }
219
-
220
- if (vector.linearGradient) {
221
- gradient = this.pdfDocument.linearGradient(vector.x, vector.y, vector.x + vector.w, vector.y);
222
- }
223
- break;
224
- case 'line':
225
- this.pdfDocument.moveTo(vector.x1, vector.y1);
226
- this.pdfDocument.lineTo(vector.x2, vector.y2);
227
- break;
228
- case 'polyline':
229
- if (vector.points.length === 0) {
230
- break;
231
- }
232
-
233
- this.pdfDocument.moveTo(vector.points[0].x, vector.points[0].y);
234
- for (let i = 1, l = vector.points.length; i < l; i++) {
235
- this.pdfDocument.lineTo(vector.points[i].x, vector.points[i].y);
236
- }
237
-
238
- if (vector.points.length > 1) {
239
- let p1 = vector.points[0];
240
- let pn = vector.points[vector.points.length - 1];
241
-
242
- if (vector.closePath || p1.x === pn.x && p1.y === pn.y) {
243
- this.pdfDocument.closePath();
244
- }
245
- }
246
- break;
247
- case 'path':
248
- this.pdfDocument.path(vector.d);
249
- break;
250
- }
251
-
252
- if (vector.linearGradient && gradient) {
253
- let step = 1 / (vector.linearGradient.length - 1);
254
-
255
- for (let i = 0; i < vector.linearGradient.length; i++) {
256
- gradient.stop(i * step, vector.linearGradient[i]);
257
- }
258
-
259
- vector.color = gradient;
260
- }
261
-
262
- let patternColor = this.pdfDocument.providePattern(vector.color);
263
- if (patternColor !== null) {
264
- vector.color = patternColor;
265
- }
266
-
267
- let fillOpacity = isNumber(vector.fillOpacity) ? vector.fillOpacity : 1;
268
- let strokeOpacity = isNumber(vector.strokeOpacity) ? vector.strokeOpacity : 1;
269
-
270
- if (vector.color && vector.lineColor) {
271
- this.pdfDocument.fillColor(vector.color, fillOpacity);
272
- this.pdfDocument.strokeColor(vector.lineColor, strokeOpacity);
273
- this.pdfDocument.fillAndStroke();
274
- } else if (vector.color) {
275
- this.pdfDocument.fillColor(vector.color, fillOpacity);
276
- this.pdfDocument.fill();
277
- } else {
278
- this.pdfDocument.strokeColor(vector.lineColor || 'black', strokeOpacity);
279
- this.pdfDocument.stroke();
280
- }
281
- }
282
-
283
- renderImage(image) {
284
- let opacity = isNumber(image.opacity) ? image.opacity : 1;
285
- this.pdfDocument.opacity(opacity);
286
- if (image.cover) {
287
- const align = image.cover.align || 'center';
288
- const valign = image.cover.valign || 'center';
289
- const width = image.cover.width ? image.cover.width : image.width;
290
- const height = image.cover.height ? image.cover.height : image.height;
291
- this.pdfDocument.save();
292
- this.pdfDocument.rect(image.x, image.y, width, height).clip();
293
- this.pdfDocument.image(image.image, image.x, image.y, { cover: [width, height], align: align, valign: valign });
294
- this.pdfDocument.restore();
295
- } else {
296
- this.pdfDocument.image(image.image, image.x, image.y, { width: image._width, height: image._height });
297
- }
298
- if (image.link) {
299
- this.pdfDocument.link(image.x, image.y, image._width, image._height, image.link);
300
- }
301
- if (image.linkToPage) {
302
- this.pdfDocument.ref({ Type: 'Action', S: 'GoTo', D: [image.linkToPage, 0, 0] }).end();
303
- this.pdfDocument.annotate(image.x, image.y, image._width, image._height, { Subtype: 'Link', Dest: [image.linkToPage - 1, 'XYZ', null, null, null] });
304
- }
305
- if (image.linkToDestination) {
306
- this.pdfDocument.goTo(image.x, image.y, image._width, image._height, image.linkToDestination);
307
- }
308
- if (image.linkToFile) {
309
- const attachment = this.pdfDocument.provideAttachment(image.linkToFile);
310
- this.pdfDocument.fileAnnotation(
311
- image.x,
312
- image.y,
313
- image._width,
314
- image._height,
315
- attachment,
316
- // add empty rectangle as file annotation appearance with the same size as the rendered image
317
- {
318
- AP: {
319
- N: {
320
- Type: 'XObject',
321
- Subtype: 'Form',
322
- FormType: 1,
323
- BBox: [image.x, image.y, image._width, image._height]
324
- }
325
- },
326
- }
327
- );
328
- }
329
- }
330
-
331
- renderSVG(svg) {
332
- let options = {
333
- width: svg._width,
334
- height: svg._height,
335
- assumePt: true,
336
- useCSS: !isString(svg.svg),
337
- ...svg.options
338
- };
339
- options.fontCallback = (family, bold, italic) => {
340
- let fontsFamily = family.split(',').map(f => f.trim().replace(/('|")/g, ''));
341
- let font = findFont(this.pdfDocument.fonts, fontsFamily, svg.font || 'Roboto');
342
-
343
- let fontFile = this.pdfDocument.getFontFile(font, bold, italic);
344
- if (fontFile === null) {
345
- let type = this.pdfDocument.getFontType(bold, italic);
346
- throw new Error(`Font '${font}' in style '${type}' is not defined in the font section of the document definition.`);
347
- }
348
-
349
- return fontFile;
350
- };
351
-
352
- SVGtoPDF(this.pdfDocument, svg.svg, svg.x, svg.y, options);
353
-
354
- if (svg.link) {
355
- this.pdfDocument.link(svg.x, svg.y, svg._width, svg._height, svg.link);
356
- }
357
- if (svg.linkToPage) {
358
- this.pdfDocument.ref({ Type: 'Action', S: 'GoTo', D: [svg.linkToPage, 0, 0] }).end();
359
- this.pdfDocument.annotate(svg.x, svg.y, svg._width, svg._height, { Subtype: 'Link', Dest: [svg.linkToPage - 1, 'XYZ', null, null, null] });
360
- }
361
- if (svg.linkToDestination) {
362
- this.pdfDocument.goTo(svg.x, svg.y, svg._width, svg._height, svg.linkToDestination);
363
- }
364
- }
365
-
366
- renderAttachment(attachment) {
367
- const file = this.pdfDocument.provideAttachment(attachment.attachment);
368
-
369
- const options = {};
370
- if (attachment.icon) {
371
- options.Name = attachment.icon;
372
- }
373
-
374
- this.pdfDocument.fileAnnotation(attachment.x, attachment.y, attachment._width, attachment._height, file, options);
375
- }
376
-
377
- beginClip(rect) {
378
- this.pdfDocument.save();
379
- this.pdfDocument.addContent(`${rect.x} ${rect.y} ${rect.width} ${rect.height} re`);
380
- this.pdfDocument.clip();
381
- }
382
-
383
- endClip() {
384
- this.pdfDocument.restore();
385
- }
386
-
387
- renderWatermark(page) {
388
- let watermark = page.watermark;
389
-
390
- this.pdfDocument.fill(watermark.color);
391
- this.pdfDocument.opacity(watermark.opacity);
392
-
393
- this.pdfDocument.save();
394
-
395
- this.pdfDocument.rotate(watermark.angle, { origin: [this.pdfDocument.page.width / 2, this.pdfDocument.page.height / 2] });
396
-
397
- let x = this.pdfDocument.page.width / 2 - watermark._size.size.width / 2;
398
- let y = this.pdfDocument.page.height / 2 - watermark._size.size.height / 2;
399
-
400
- this.pdfDocument._font = watermark.font;
401
- this.pdfDocument.fontSize(watermark.fontSize);
402
- this.pdfDocument.text(watermark.text, x, y, { lineBreak: false });
403
-
404
- this.pdfDocument.restore();
405
- }
406
-
407
- }
408
-
409
- export default Renderer;
1
+ import TextDecorator from './TextDecorator';
2
+ import TextInlines from './TextInlines';
3
+ import { isNumber, isString } from './helpers/variableType';
4
+ import SVGtoPDF from './3rd-party/svg-to-pdfkit';
5
+
6
+ const findFont = (fonts, requiredFonts, defaultFont) => {
7
+ for (let i = 0; i < requiredFonts.length; i++) {
8
+ let requiredFont = requiredFonts[i].toLowerCase();
9
+
10
+ for (let font in fonts) {
11
+ if (font.toLowerCase() === requiredFont) {
12
+ return font;
13
+ }
14
+ }
15
+ }
16
+
17
+ return defaultFont;
18
+ };
19
+
20
+ /**
21
+ * Shift the "y" height of the text baseline up or down (superscript or subscript,
22
+ * respectively). The exact shift can / should be changed according to standard
23
+ * conventions.
24
+ *
25
+ * @param {number} y
26
+ * @param {object} inline
27
+ * @returns {number}
28
+ */
29
+ const offsetText = (y, inline) => {
30
+ let newY = y;
31
+ if (inline.sup) {
32
+ newY -= inline.fontSize * 0.75;
33
+ }
34
+ if (inline.sub) {
35
+ newY += inline.fontSize * 0.35;
36
+ }
37
+ return newY;
38
+ };
39
+
40
+ class Renderer {
41
+ constructor(pdfDocument, progressCallback) {
42
+ this.pdfDocument = pdfDocument;
43
+ this.progressCallback = progressCallback;
44
+ }
45
+
46
+ renderPages(pages) {
47
+ this.pdfDocument._pdfMakePages = pages; // TODO: Why?
48
+
49
+ let totalItems = 0;
50
+ if (this.progressCallback) {
51
+ pages.forEach(page => {
52
+ totalItems += page.items.length;
53
+ });
54
+ }
55
+
56
+ let renderedItems = 0;
57
+
58
+ for (let i = 0; i < pages.length; i++) {
59
+ this.pdfDocument.addPage({ size: [pages[i].pageSize.width, pages[i].pageSize.height] });
60
+
61
+ let page = pages[i];
62
+ for (let ii = 0, il = page.items.length; ii < il; ii++) {
63
+ let item = page.items[ii];
64
+ switch (item.type) {
65
+ case 'vector':
66
+ this.renderVector(item.item);
67
+ break;
68
+ case 'line':
69
+ this.renderLine(item.item, item.item.x, item.item.y);
70
+ break;
71
+ case 'image':
72
+ this.renderImage(item.item);
73
+ break;
74
+ case 'svg':
75
+ this.renderSVG(item.item);
76
+ break;
77
+ case 'attachment':
78
+ this.renderAttachment(item.item);
79
+ break;
80
+ case 'beginClip':
81
+ this.beginClip(item.item);
82
+ break;
83
+ case 'endClip':
84
+ this.endClip();
85
+ break;
86
+ case 'beginVerticalAlignment':
87
+ this.beginVerticalAlignment(item.item);
88
+ break;
89
+ case 'endVerticalAlignment':
90
+ this.endVerticalAlignment(item.item);
91
+ break;
92
+ }
93
+ renderedItems++;
94
+ if (this.progressCallback) {
95
+ this.progressCallback(renderedItems / totalItems);
96
+ }
97
+ }
98
+ if (page.watermark) {
99
+ this.renderWatermark(page);
100
+ }
101
+ }
102
+ }
103
+
104
+ renderLine(line, x, y) {
105
+ function preparePageNodeRefLine(_pageNodeRef, inline) {
106
+ let newWidth;
107
+ let diffWidth;
108
+ let textInlines = new TextInlines(null);
109
+
110
+ if (_pageNodeRef.positions === undefined) {
111
+ throw new Error('Page reference id not found');
112
+ }
113
+
114
+ let pageNumber = _pageNodeRef.positions[0].pageNumber.toString();
115
+
116
+ inline.text = pageNumber;
117
+ newWidth = textInlines.widthOfText(inline.text, inline);
118
+ diffWidth = inline.width - newWidth;
119
+ inline.width = newWidth;
120
+
121
+ switch (inline.alignment) {
122
+ case 'right':
123
+ inline.x += diffWidth;
124
+ break;
125
+ case 'center':
126
+ inline.x += diffWidth / 2;
127
+ break;
128
+ }
129
+ }
130
+
131
+ if (line._pageNodeRef) {
132
+ preparePageNodeRefLine(line._pageNodeRef, line.inlines[0]);
133
+ }
134
+
135
+ x = x || 0;
136
+ y = y || 0;
137
+
138
+ let lineHeight = line.getHeight();
139
+ let ascenderHeight = line.getAscenderHeight();
140
+ let descent = lineHeight - ascenderHeight;
141
+
142
+ const textDecorator = new TextDecorator(this.pdfDocument);
143
+
144
+ textDecorator.drawBackground(line, x, y);
145
+
146
+ //TODO: line.optimizeInlines();
147
+ //TODO: lines without differently styled inlines should be written to pdf as one stream
148
+ for (let i = 0, l = line.inlines.length; i < l; i++) {
149
+ let inline = line.inlines[i];
150
+ let shiftToBaseline = lineHeight - ((inline.font.ascender / 1000) * inline.fontSize) - descent;
151
+
152
+ if (inline._pageNodeRef) {
153
+ preparePageNodeRefLine(inline._pageNodeRef, inline);
154
+ }
155
+
156
+ let options = {
157
+ lineBreak: false,
158
+ textWidth: inline.width,
159
+ characterSpacing: inline.characterSpacing,
160
+ wordCount: 1,
161
+ link: inline.link
162
+ };
163
+
164
+ if (inline.linkToDestination) {
165
+ options.goTo = inline.linkToDestination;
166
+ }
167
+
168
+ if (line.id && i === 0) {
169
+ options.destination = line.id;
170
+ }
171
+
172
+ if (inline.fontFeatures) {
173
+ options.features = inline.fontFeatures;
174
+ }
175
+
176
+ let opacity = isNumber(inline.opacity) ? inline.opacity : 1;
177
+ this.pdfDocument.opacity(opacity);
178
+ this.pdfDocument.fill(inline.color || 'black');
179
+
180
+ this.pdfDocument._font = inline.font;
181
+ this.pdfDocument.fontSize(inline.fontSize);
182
+
183
+ let shiftedY = offsetText(y + shiftToBaseline, inline);
184
+ this.pdfDocument.text(inline.text, x + inline.x, shiftedY, options);
185
+
186
+ if (inline.linkToPage) {
187
+ this.pdfDocument.ref({ Type: 'Action', S: 'GoTo', D: [inline.linkToPage, 0, 0] }).end();
188
+ this.pdfDocument.annotate(x + inline.x, shiftedY, inline.width, inline.height, { Subtype: 'Link', Dest: [inline.linkToPage - 1, 'XYZ', null, null, null] });
189
+ }
190
+ }
191
+
192
+ // Decorations won't draw correctly for superscript
193
+ textDecorator.drawDecorations(line, x, y);
194
+ }
195
+
196
+ renderVector(vector) {
197
+ //TODO: pdf optimization (there's no need to write all properties everytime)
198
+ this.pdfDocument.lineWidth(vector.lineWidth || 1);
199
+ if (vector.dash) {
200
+ this.pdfDocument.dash(vector.dash.length, { space: vector.dash.space || vector.dash.length, phase: vector.dash.phase || 0 });
201
+ } else {
202
+ this.pdfDocument.undash();
203
+ }
204
+ this.pdfDocument.lineJoin(vector.lineJoin || 'miter');
205
+ this.pdfDocument.lineCap(vector.lineCap || 'butt');
206
+
207
+ //TODO: clipping
208
+
209
+ let gradient = null;
210
+
211
+ switch (vector.type) {
212
+ case 'ellipse':
213
+ this.pdfDocument.ellipse(vector.x, vector.y, vector.r1, vector.r2);
214
+
215
+ if (vector.linearGradient) {
216
+ gradient = this.pdfDocument.linearGradient(vector.x - vector.r1, vector.y, vector.x + vector.r1, vector.y);
217
+ }
218
+ break;
219
+ case 'rect':
220
+ if (vector.r) {
221
+ this.pdfDocument.roundedRect(vector.x, vector.y, vector.w, vector.h, vector.r);
222
+ } else {
223
+ this.pdfDocument.rect(vector.x, vector.y, vector.w, vector.h);
224
+ }
225
+
226
+ if (vector.linearGradient) {
227
+ gradient = this.pdfDocument.linearGradient(vector.x, vector.y, vector.x + vector.w, vector.y);
228
+ }
229
+ break;
230
+ case 'line':
231
+ this.pdfDocument.moveTo(vector.x1, vector.y1);
232
+ this.pdfDocument.lineTo(vector.x2, vector.y2);
233
+ break;
234
+ case 'polyline':
235
+ if (vector.points.length === 0) {
236
+ break;
237
+ }
238
+
239
+ this.pdfDocument.moveTo(vector.points[0].x, vector.points[0].y);
240
+ for (let i = 1, l = vector.points.length; i < l; i++) {
241
+ this.pdfDocument.lineTo(vector.points[i].x, vector.points[i].y);
242
+ }
243
+
244
+ if (vector.points.length > 1) {
245
+ let p1 = vector.points[0];
246
+ let pn = vector.points[vector.points.length - 1];
247
+
248
+ if (vector.closePath || p1.x === pn.x && p1.y === pn.y) {
249
+ this.pdfDocument.closePath();
250
+ }
251
+ }
252
+ break;
253
+ case 'path':
254
+ this.pdfDocument.path(vector.d);
255
+ break;
256
+ }
257
+
258
+ if (vector.linearGradient && gradient) {
259
+ let step = 1 / (vector.linearGradient.length - 1);
260
+
261
+ for (let i = 0; i < vector.linearGradient.length; i++) {
262
+ gradient.stop(i * step, vector.linearGradient[i]);
263
+ }
264
+
265
+ vector.color = gradient;
266
+ }
267
+
268
+ let patternColor = this.pdfDocument.providePattern(vector.color);
269
+ if (patternColor !== null) {
270
+ vector.color = patternColor;
271
+ }
272
+
273
+ let fillOpacity = isNumber(vector.fillOpacity) ? vector.fillOpacity : 1;
274
+ let strokeOpacity = isNumber(vector.strokeOpacity) ? vector.strokeOpacity : 1;
275
+
276
+ if (vector.color && vector.lineColor) {
277
+ this.pdfDocument.fillColor(vector.color, fillOpacity);
278
+ this.pdfDocument.strokeColor(vector.lineColor, strokeOpacity);
279
+ this.pdfDocument.fillAndStroke();
280
+ } else if (vector.color) {
281
+ this.pdfDocument.fillColor(vector.color, fillOpacity);
282
+ this.pdfDocument.fill();
283
+ } else {
284
+ this.pdfDocument.strokeColor(vector.lineColor || 'black', strokeOpacity);
285
+ this.pdfDocument.stroke();
286
+ }
287
+ }
288
+
289
+ renderImage(image) {
290
+ let opacity = isNumber(image.opacity) ? image.opacity : 1;
291
+ this.pdfDocument.opacity(opacity);
292
+ if (image.cover) {
293
+ const align = image.cover.align || 'center';
294
+ const valign = image.cover.valign || 'center';
295
+ const width = image.cover.width ? image.cover.width : image.width;
296
+ const height = image.cover.height ? image.cover.height : image.height;
297
+ this.pdfDocument.save();
298
+ this.pdfDocument.rect(image.x, image.y, width, height).clip();
299
+ this.pdfDocument.image(image.image, image.x, image.y, { cover: [width, height], align: align, valign: valign });
300
+ this.pdfDocument.restore();
301
+ } else {
302
+ this.pdfDocument.image(image.image, image.x, image.y, { width: image._width, height: image._height });
303
+ }
304
+ if (image.link) {
305
+ this.pdfDocument.link(image.x, image.y, image._width, image._height, image.link);
306
+ }
307
+ if (image.linkToPage) {
308
+ this.pdfDocument.ref({ Type: 'Action', S: 'GoTo', D: [image.linkToPage, 0, 0] }).end();
309
+ this.pdfDocument.annotate(image.x, image.y, image._width, image._height, { Subtype: 'Link', Dest: [image.linkToPage - 1, 'XYZ', null, null, null] });
310
+ }
311
+ if (image.linkToDestination) {
312
+ this.pdfDocument.goTo(image.x, image.y, image._width, image._height, image.linkToDestination);
313
+ }
314
+ if (image.linkToFile) {
315
+ const attachment = this.pdfDocument.provideAttachment(image.linkToFile);
316
+ this.pdfDocument.fileAnnotation(
317
+ image.x,
318
+ image.y,
319
+ image._width,
320
+ image._height,
321
+ attachment,
322
+ // add empty rectangle as file annotation appearance with the same size as the rendered image
323
+ {
324
+ AP: {
325
+ N: {
326
+ Type: 'XObject',
327
+ Subtype: 'Form',
328
+ FormType: 1,
329
+ BBox: [image.x, image.y, image._width, image._height]
330
+ }
331
+ },
332
+ }
333
+ );
334
+ }
335
+ }
336
+
337
+ renderSVG(svg) {
338
+ let options = {
339
+ width: svg._width,
340
+ height: svg._height,
341
+ assumePt: true,
342
+ useCSS: !isString(svg.svg),
343
+ ...svg.options
344
+ };
345
+ options.fontCallback = (family, bold, italic) => {
346
+ let fontsFamily = family.split(',').map(f => f.trim().replace(/('|")/g, ''));
347
+ let font = findFont(this.pdfDocument.fonts, fontsFamily, svg.font || 'Roboto');
348
+
349
+ let fontFile = this.pdfDocument.getFontFile(font, bold, italic);
350
+ if (fontFile === null) {
351
+ let type = this.pdfDocument.getFontType(bold, italic);
352
+ throw new Error(`Font '${font}' in style '${type}' is not defined in the font section of the document definition.`);
353
+ }
354
+
355
+ return fontFile;
356
+ };
357
+
358
+ SVGtoPDF(this.pdfDocument, svg.svg, svg.x, svg.y, options);
359
+
360
+ if (svg.link) {
361
+ this.pdfDocument.link(svg.x, svg.y, svg._width, svg._height, svg.link);
362
+ }
363
+ if (svg.linkToPage) {
364
+ this.pdfDocument.ref({ Type: 'Action', S: 'GoTo', D: [svg.linkToPage, 0, 0] }).end();
365
+ this.pdfDocument.annotate(svg.x, svg.y, svg._width, svg._height, { Subtype: 'Link', Dest: [svg.linkToPage - 1, 'XYZ', null, null, null] });
366
+ }
367
+ if (svg.linkToDestination) {
368
+ this.pdfDocument.goTo(svg.x, svg.y, svg._width, svg._height, svg.linkToDestination);
369
+ }
370
+ }
371
+
372
+ renderAttachment(attachment) {
373
+ const file = this.pdfDocument.provideAttachment(attachment.attachment);
374
+
375
+ const options = {};
376
+ if (attachment.icon) {
377
+ options.Name = attachment.icon;
378
+ }
379
+
380
+ this.pdfDocument.fileAnnotation(attachment.x, attachment.y, attachment._width, attachment._height, file, options);
381
+ }
382
+
383
+ beginClip(rect) {
384
+ this.pdfDocument.save();
385
+ this.pdfDocument.addContent(`${rect.x} ${rect.y} ${rect.width} ${rect.height} re`);
386
+ this.pdfDocument.clip();
387
+ }
388
+
389
+ endClip() {
390
+ this.pdfDocument.restore();
391
+ }
392
+
393
+ beginVerticalAlignment(item) {
394
+ if (item.isCellContentMultiPage) {
395
+ return;
396
+ }
397
+
398
+ switch(item.verticalAlignment) {
399
+ case 'middle':
400
+ this.pdfDocument.save();
401
+ this.pdfDocument.translate(0, -(item.getNodeHeight() - item.getViewHeight()) / 2);
402
+ break;
403
+ case 'bottom':
404
+ this.pdfDocument.save();
405
+ this.pdfDocument.translate(0, -(item.getNodeHeight() - item.getViewHeight()));
406
+ break;
407
+ }
408
+ }
409
+
410
+ endVerticalAlignment(item) {
411
+ if (item.isCellContentMultiPage) {
412
+ return;
413
+ }
414
+
415
+ switch(item.verticalAlignment) {
416
+ case 'middle':
417
+ case 'bottom':
418
+ this.pdfDocument.restore();
419
+ break;
420
+ }
421
+ }
422
+
423
+ renderWatermark(page) {
424
+ let watermark = page.watermark;
425
+
426
+ this.pdfDocument.fill(watermark.color);
427
+ this.pdfDocument.opacity(watermark.opacity);
428
+
429
+ this.pdfDocument.save();
430
+
431
+ this.pdfDocument.rotate(watermark.angle, { origin: [this.pdfDocument.page.width / 2, this.pdfDocument.page.height / 2] });
432
+
433
+ let x = this.pdfDocument.page.width / 2 - watermark._size.size.width / 2;
434
+ let y = this.pdfDocument.page.height / 2 - watermark._size.size.height / 2;
435
+
436
+ this.pdfDocument._font = watermark.font;
437
+ this.pdfDocument.fontSize(watermark.fontSize);
438
+ this.pdfDocument.text(watermark.text, x, y, { lineBreak: false });
439
+
440
+ this.pdfDocument.restore();
441
+ }
442
+
443
+ }
444
+
445
+ export default Renderer;