@digicole/pdfmake-rtl 1.2.0 → 2.1.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 (100) hide show
  1. package/.vscode/tasks.json +17 -0
  2. package/CHANGELOG.md +83 -128
  3. package/LICENSE +22 -22
  4. package/README.md +188 -681
  5. package/build/fonts/Cairo/Cairo-Black.ttf +0 -0
  6. package/build/fonts/Cairo/Cairo-Bold.ttf +0 -0
  7. package/build/fonts/Cairo/Cairo-ExtraLight.ttf +0 -0
  8. package/build/fonts/Cairo/Cairo-Light.ttf +0 -0
  9. package/build/fonts/Cairo/Cairo-Regular.ttf +0 -0
  10. package/build/fonts/Cairo/Cairo-SemiBold.ttf +0 -0
  11. package/build/fonts/Cairo.js +27 -0
  12. package/build/fonts/Roboto/Roboto-Italic.ttf +0 -0
  13. package/build/fonts/Roboto/Roboto-Medium.ttf +0 -0
  14. package/build/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
  15. package/build/fonts/Roboto/Roboto-Regular.ttf +0 -0
  16. package/build/fonts/Roboto.js +27 -0
  17. package/build/pdfmake.js +63736 -71285
  18. package/build/pdfmake.js.map +1 -1
  19. package/build/pdfmake.min.js +2 -2
  20. package/build/pdfmake.min.js.map +1 -1
  21. package/build/standard-fonts/Courier.js +27 -0
  22. package/build/standard-fonts/Helvetica.js +27 -0
  23. package/build/standard-fonts/Symbol.js +21 -0
  24. package/build/standard-fonts/Times.js +27 -0
  25. package/build/standard-fonts/ZapfDingbats.js +21 -0
  26. package/build/vfs_fonts.js +11 -7
  27. package/build-vfs.js +44 -44
  28. package/fonts/Cairo/Cairo-Black.ttf +0 -0
  29. package/fonts/Cairo/Cairo-Bold.ttf +0 -0
  30. package/fonts/Cairo/Cairo-ExtraLight.ttf +0 -0
  31. package/fonts/Cairo/Cairo-Light.ttf +0 -0
  32. package/fonts/Cairo/Cairo-Regular.ttf +0 -0
  33. package/fonts/Cairo/Cairo-SemiBold.ttf +0 -0
  34. package/fonts/Cairo.js +8 -0
  35. package/fonts/Roboto/Roboto-Italic.ttf +0 -0
  36. package/fonts/Roboto/Roboto-Medium.ttf +0 -0
  37. package/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
  38. package/fonts/Roboto/Roboto-Regular.ttf +0 -0
  39. package/fonts/Roboto.js +8 -0
  40. package/index.js +26 -26
  41. package/package.json +42 -39
  42. package/src/3rd-party/svg-to-pdfkit/LICENSE +9 -9
  43. package/src/3rd-party/svg-to-pdfkit/source.js +229 -36
  44. package/src/3rd-party/svg-to-pdfkit.js +3 -3
  45. package/src/OutputDocument.js +64 -0
  46. package/src/OutputDocumentServer.js +32 -0
  47. package/src/PDFDocument.js +174 -0
  48. package/src/PageSize.js +53 -0
  49. package/src/Renderer.js +445 -0
  50. package/src/TextBreaker.js +168 -0
  51. package/src/TextInlines.js +263 -0
  52. package/src/URLResolver.js +43 -0
  53. package/src/base.js +70 -0
  54. package/src/browser-extensions/OutputDocumentBrowser.js +80 -0
  55. package/src/browser-extensions/fonts/Cairo.js +27 -0
  56. package/src/browser-extensions/fonts/Roboto.js +27 -0
  57. package/src/browser-extensions/index.js +61 -0
  58. package/src/browser-extensions/pdfMake.js +1 -355
  59. package/src/browser-extensions/standard-fonts/Courier.js +27 -0
  60. package/src/browser-extensions/standard-fonts/Helvetica.js +27 -0
  61. package/src/browser-extensions/standard-fonts/Symbol.js +21 -0
  62. package/src/browser-extensions/standard-fonts/Times.js +27 -0
  63. package/src/browser-extensions/standard-fonts/ZapfDingbats.js +21 -0
  64. package/src/browser-extensions/virtual-fs-cjs.js +1 -0
  65. package/src/columnCalculator.js +154 -157
  66. package/src/docMeasure.js +802 -810
  67. package/src/docPreprocessor.js +306 -273
  68. package/src/documentContext.js +345 -340
  69. package/src/elementWriter.js +736 -411
  70. package/src/helpers/node.js +136 -0
  71. package/src/helpers/tools.js +44 -0
  72. package/src/helpers/variableType.js +50 -0
  73. package/src/index.js +16 -0
  74. package/src/layoutBuilder.js +1393 -1197
  75. package/src/line.js +122 -104
  76. package/src/pageElementWriter.js +187 -174
  77. package/src/printer.js +370 -727
  78. package/src/qrEnc.js +796 -791
  79. package/src/rtlUtils.js +500 -485
  80. package/src/standardPageSizes.js +52 -54
  81. package/src/styleContextStack.js +208 -138
  82. package/src/svgMeasure.js +109 -70
  83. package/src/tableLayouts.js +100 -0
  84. package/src/tableProcessor.js +620 -606
  85. package/src/textDecorator.js +175 -157
  86. package/src/virtual-fs.js +66 -0
  87. package/standard-fonts/Courier.js +8 -0
  88. package/standard-fonts/Helvetica.js +8 -0
  89. package/standard-fonts/Symbol.js +5 -0
  90. package/standard-fonts/Times.js +8 -0
  91. package/standard-fonts/ZapfDingbats.js +5 -0
  92. package/index.html +0 -396
  93. package/src/browser-extensions/URLBrowserResolver.js +0 -96
  94. package/src/browser-extensions/virtual-fs.js +0 -55
  95. package/src/fontProvider.js +0 -68
  96. package/src/helpers.js +0 -138
  97. package/src/imageMeasure.js +0 -62
  98. package/src/pdfKitEngine.js +0 -21
  99. package/src/textTools.js +0 -391
  100. package/src/traversalTracker.js +0 -47
@@ -0,0 +1,174 @@
1
+ import PDFKit from 'pdfkit';
2
+
3
+ const typeName = (bold, italics) => {
4
+ let type = 'normal';
5
+ if (bold && italics) {
6
+ type = 'bolditalics';
7
+ } else if (bold) {
8
+ type = 'bold';
9
+ } else if (italics) {
10
+ type = 'italics';
11
+ }
12
+ return type;
13
+ };
14
+
15
+ class PDFDocument extends PDFKit {
16
+ constructor(fonts = {}, images = {}, patterns = {}, attachments = {}, options = {}, virtualfs = null) {
17
+ super(options);
18
+
19
+ this.fonts = {};
20
+ this.fontCache = {};
21
+ for (let font in fonts) {
22
+ if (fonts.hasOwnProperty(font)) {
23
+ let fontDef = fonts[font];
24
+
25
+ this.fonts[font] = {
26
+ normal: fontDef.normal,
27
+ bold: fontDef.bold,
28
+ italics: fontDef.italics,
29
+ bolditalics: fontDef.bolditalics
30
+ };
31
+ }
32
+ }
33
+
34
+ this.patterns = {};
35
+ for (let pattern in patterns) {
36
+ if (patterns.hasOwnProperty(pattern)) {
37
+ let patternDef = patterns[pattern];
38
+ this.patterns[pattern] = this.pattern(patternDef.boundingBox, patternDef.xStep, patternDef.yStep, patternDef.pattern, patternDef.colored);
39
+ }
40
+ }
41
+
42
+
43
+ this.images = images;
44
+ this.attachments = attachments;
45
+ this.virtualfs = virtualfs;
46
+ }
47
+
48
+ getFontType(bold, italics) {
49
+ return typeName(bold, italics);
50
+ }
51
+
52
+ getFontFile(familyName, bold, italics) {
53
+ let type = this.getFontType(bold, italics);
54
+ if (!this.fonts[familyName] || !this.fonts[familyName][type]) {
55
+ return null;
56
+ }
57
+
58
+ return this.fonts[familyName][type];
59
+ }
60
+
61
+ provideFont(familyName, bold, italics) {
62
+ let type = this.getFontType(bold, italics);
63
+ if (this.getFontFile(familyName, bold, italics) === null) {
64
+ throw new Error(`Font '${familyName}' in style '${type}' is not defined in the font section of the document definition.`);
65
+ }
66
+
67
+ this.fontCache[familyName] = this.fontCache[familyName] || {};
68
+
69
+ if (!this.fontCache[familyName][type]) {
70
+ let def = this.fonts[familyName][type];
71
+ if (!Array.isArray(def)) {
72
+ def = [def];
73
+ }
74
+
75
+ if (this.virtualfs && this.virtualfs.existsSync(def[0])) {
76
+ def[0] = this.virtualfs.readFileSync(def[0]);
77
+ }
78
+
79
+ this.fontCache[familyName][type] = this.font(...def)._font;
80
+ }
81
+
82
+ return this.fontCache[familyName][type];
83
+ }
84
+
85
+ provideImage(src) {
86
+ const realImageSrc = src => {
87
+ let image = this.images[src];
88
+
89
+ if (!image) {
90
+ return src;
91
+ }
92
+
93
+ if (this.virtualfs && this.virtualfs.existsSync(image)) {
94
+ return this.virtualfs.readFileSync(image);
95
+ }
96
+
97
+ let index = image.indexOf('base64,');
98
+ if (index < 0) {
99
+ return this.images[src];
100
+ }
101
+
102
+ return Buffer.from(image.substring(index + 7), 'base64');
103
+ };
104
+
105
+ if (this._imageRegistry[src]) {
106
+ return this._imageRegistry[src];
107
+ }
108
+
109
+ let image;
110
+
111
+ try {
112
+ image = this.openImage(realImageSrc(src));
113
+ if (!image) {
114
+ throw new Error('No image');
115
+ }
116
+ } catch (error) {
117
+ throw new Error(`Invalid image: ${error.toString()}\nImages dictionary should contain dataURL entries (or local file paths in node.js)`);
118
+ }
119
+
120
+ image.embed(this);
121
+ this._imageRegistry[src] = image;
122
+
123
+ return image;
124
+ }
125
+
126
+ /**
127
+ * @param {Array} color pdfmake format: [<pattern name>, <color>]
128
+ * @returns {Array} pdfkit format: [<pattern object>, <color>]
129
+ */
130
+ providePattern(color) {
131
+ if (Array.isArray(color) && color.length === 2) {
132
+ return [this.patterns[color[0]], color[1]];
133
+ }
134
+
135
+ return null;
136
+ }
137
+
138
+ provideAttachment(src) {
139
+ const checkRequired = obj => {
140
+ if (!obj) {
141
+ throw new Error('No attachment');
142
+ }
143
+ if (!obj.src) {
144
+ throw new Error('The "src" key is required for attachments');
145
+ }
146
+
147
+ return obj;
148
+ };
149
+
150
+ if (typeof src === 'object') {
151
+ return checkRequired(src);
152
+ }
153
+
154
+ let attachment = checkRequired(this.attachments[src]);
155
+
156
+ if (this.virtualfs && this.virtualfs.existsSync(attachment.src)) {
157
+ return this.virtualfs.readFileSync(attachment.src);
158
+ }
159
+
160
+ return attachment;
161
+ }
162
+
163
+ setOpenActionAsPrint() {
164
+ let printActionRef = this.ref({
165
+ Type: 'Action',
166
+ S: 'Named',
167
+ N: 'Print'
168
+ });
169
+ this._root.data.OpenAction = printActionRef;
170
+ printActionRef.end();
171
+ }
172
+ }
173
+
174
+ export default PDFDocument;
@@ -0,0 +1,53 @@
1
+ import sizes from './standardPageSizes';
2
+ import { isString, isNumber } from './helpers/variableType';
3
+
4
+ export function normalizePageSize(pageSize, pageOrientation) {
5
+ function isNeedSwapPageSizes(pageOrientation) {
6
+ if (isString(pageOrientation)) {
7
+ pageOrientation = pageOrientation.toLowerCase();
8
+ return ((pageOrientation === 'portrait') && (size.width > size.height)) ||
9
+ ((pageOrientation === 'landscape') && (size.width < size.height));
10
+ }
11
+ return false;
12
+ }
13
+
14
+ function pageSizeToWidthAndHeight(pageSize) {
15
+ if (isString(pageSize)) {
16
+ let size = sizes[pageSize.toUpperCase()];
17
+ if (!size) {
18
+ throw new Error(`Page size ${pageSize} not recognized`);
19
+ }
20
+ return { width: size[0], height: size[1] };
21
+ }
22
+
23
+ return pageSize;
24
+ }
25
+
26
+ // if pageSize.height is set to auto, set the height to infinity so there are no page breaks.
27
+ if (pageSize && pageSize.height === 'auto') {
28
+ pageSize.height = Infinity;
29
+ }
30
+
31
+ let size = pageSizeToWidthAndHeight(pageSize || 'A4');
32
+ if (isNeedSwapPageSizes(pageOrientation)) { // swap page sizes
33
+ size = { width: size.height, height: size.width };
34
+ }
35
+ size.orientation = size.width > size.height ? 'landscape' : 'portrait';
36
+ return size;
37
+ }
38
+
39
+ export function normalizePageMargin(margin) {
40
+ if (isNumber(margin)) {
41
+ margin = { left: margin, right: margin, top: margin, bottom: margin };
42
+ } else if (Array.isArray(margin)) {
43
+ if (margin.length === 2) {
44
+ margin = { left: margin[0], top: margin[1], right: margin[0], bottom: margin[1] };
45
+ } else if (margin.length === 4) {
46
+ margin = { left: margin[0], top: margin[1], right: margin[2], bottom: margin[3] };
47
+ } else {
48
+ throw new Error('Invalid pageMargins definition');
49
+ }
50
+ }
51
+
52
+ return margin;
53
+ }
@@ -0,0 +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
+ 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;