pdfmake 0.3.3 → 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 (92) hide show
  1. package/CHANGELOG.md +5 -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 +64552 -64404
  10. package/build/pdfmake.js.map +1 -1
  11. package/build/pdfmake.min.js +2 -2
  12. package/build/pdfmake.min.js.map +1 -1
  13. package/build/standard-fonts/Courier.js +27 -27
  14. package/build/standard-fonts/Helvetica.js +27 -27
  15. package/build/standard-fonts/Symbol.js +21 -21
  16. package/build/standard-fonts/Times.js +27 -27
  17. package/build/standard-fonts/ZapfDingbats.js +21 -21
  18. package/build/vfs_fonts.js +5 -5
  19. package/build-vfs.js +44 -44
  20. package/fonts/Roboto.js +8 -8
  21. package/js/DocMeasure.js +6 -6
  22. package/js/DocumentContext.js +8 -3
  23. package/js/ElementWriter.js +42 -16
  24. package/js/LayoutBuilder.js +141 -78
  25. package/js/Line.js +16 -16
  26. package/js/OutputDocument.js +10 -10
  27. package/js/OutputDocumentServer.js +3 -3
  28. package/js/PDFDocument.js +3 -3
  29. package/js/PageElementWriter.js +15 -9
  30. package/js/Printer.js +28 -28
  31. package/js/Renderer.js +40 -8
  32. package/js/SVGMeasure.js +10 -10
  33. package/js/StyleContextStack.js +48 -48
  34. package/js/TableProcessor.js +14 -0
  35. package/js/TextBreaker.js +17 -17
  36. package/js/TextInlines.js +33 -33
  37. package/js/base.js +4 -4
  38. package/js/browser-extensions/OutputDocumentBrowser.js +24 -24
  39. package/js/columnCalculator.js +2 -2
  40. package/js/helpers/node.js +14 -15
  41. package/js/helpers/variableType.js +18 -18
  42. package/js/qrEnc.js +38 -38
  43. package/js/virtual-fs.js +11 -11
  44. package/package.json +8 -8
  45. package/src/3rd-party/svg-to-pdfkit/LICENSE +9 -9
  46. package/src/3rd-party/svg-to-pdfkit/source.js +2745 -2745
  47. package/src/3rd-party/svg-to-pdfkit.js +3 -3
  48. package/src/DocMeasure.js +745 -745
  49. package/src/DocPreprocessor.js +283 -283
  50. package/src/DocumentContext.js +345 -338
  51. package/src/ElementWriter.js +441 -417
  52. package/src/LayoutBuilder.js +1336 -1262
  53. package/src/Line.js +114 -114
  54. package/src/OutputDocument.js +64 -64
  55. package/src/OutputDocumentServer.js +32 -32
  56. package/src/PDFDocument.js +174 -174
  57. package/src/PageElementWriter.js +187 -179
  58. package/src/PageSize.js +53 -53
  59. package/src/Printer.js +306 -306
  60. package/src/Renderer.js +445 -409
  61. package/src/SVGMeasure.js +109 -109
  62. package/src/StyleContextStack.js +208 -208
  63. package/src/TableProcessor.js +620 -602
  64. package/src/TextBreaker.js +168 -168
  65. package/src/TextDecorator.js +175 -175
  66. package/src/TextInlines.js +224 -224
  67. package/src/URLResolver.js +43 -43
  68. package/src/base.js +70 -70
  69. package/src/browser-extensions/OutputDocumentBrowser.js +80 -80
  70. package/src/browser-extensions/fonts/Roboto.js +27 -27
  71. package/src/browser-extensions/index.js +55 -55
  72. package/src/browser-extensions/pdfMake.js +1 -1
  73. package/src/browser-extensions/standard-fonts/Courier.js +27 -27
  74. package/src/browser-extensions/standard-fonts/Helvetica.js +27 -27
  75. package/src/browser-extensions/standard-fonts/Symbol.js +21 -21
  76. package/src/browser-extensions/standard-fonts/Times.js +27 -27
  77. package/src/browser-extensions/standard-fonts/ZapfDingbats.js +21 -21
  78. package/src/browser-extensions/virtual-fs-cjs.js +1 -1
  79. package/src/columnCalculator.js +154 -154
  80. package/src/helpers/node.js +134 -136
  81. package/src/helpers/tools.js +44 -44
  82. package/src/helpers/variableType.js +50 -50
  83. package/src/index.js +16 -16
  84. package/src/qrEnc.js +796 -796
  85. package/src/standardPageSizes.js +52 -52
  86. package/src/tableLayouts.js +100 -100
  87. package/src/virtual-fs.js +66 -66
  88. package/standard-fonts/Courier.js +8 -8
  89. package/standard-fonts/Helvetica.js +8 -8
  90. package/standard-fonts/Symbol.js +5 -5
  91. package/standard-fonts/Times.js +8 -8
  92. 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;