pdfmake-acroforms 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 (115) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/LICENSE +21 -0
  3. package/README.md +75 -0
  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 +67806 -0
  10. package/build/pdfmake.js.map +1 -0
  11. package/build/pdfmake.min.js +3 -0
  12. package/build/pdfmake.min.js.map +1 -0
  13. package/build/standard-fonts/Courier.js +27 -0
  14. package/build/standard-fonts/Helvetica.js +27 -0
  15. package/build/standard-fonts/Symbol.js +21 -0
  16. package/build/standard-fonts/Times.js +27 -0
  17. package/build/standard-fonts/ZapfDingbats.js +21 -0
  18. package/build/vfs_fonts.js +6 -0
  19. package/build-vfs.js +44 -0
  20. package/fonts/Roboto/Roboto-Italic.ttf +0 -0
  21. package/fonts/Roboto/Roboto-Medium.ttf +0 -0
  22. package/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
  23. package/fonts/Roboto/Roboto-Regular.ttf +0 -0
  24. package/fonts/Roboto.js +8 -0
  25. package/js/3rd-party/svg-to-pdfkit/source.js +3823 -0
  26. package/js/3rd-party/svg-to-pdfkit.js +7 -0
  27. package/js/DocMeasure.js +675 -0
  28. package/js/DocPreprocessor.js +258 -0
  29. package/js/DocumentContext.js +310 -0
  30. package/js/ElementWriter.js +399 -0
  31. package/js/LayoutBuilder.js +1202 -0
  32. package/js/Line.js +101 -0
  33. package/js/OutputDocument.js +64 -0
  34. package/js/OutputDocumentServer.js +29 -0
  35. package/js/PDFDocument.js +145 -0
  36. package/js/PageElementWriter.js +164 -0
  37. package/js/PageSize.js +74 -0
  38. package/js/Printer.js +288 -0
  39. package/js/Renderer.js +513 -0
  40. package/js/SVGMeasure.js +92 -0
  41. package/js/StyleContextStack.js +191 -0
  42. package/js/TableProcessor.js +562 -0
  43. package/js/TextBreaker.js +179 -0
  44. package/js/TextDecorator.js +152 -0
  45. package/js/TextInlines.js +212 -0
  46. package/js/URLResolver.js +43 -0
  47. package/js/base.js +59 -0
  48. package/js/browser-extensions/OutputDocumentBrowser.js +82 -0
  49. package/js/browser-extensions/fonts/Roboto.js +38 -0
  50. package/js/browser-extensions/index.js +53 -0
  51. package/js/browser-extensions/pdfMake.js +3 -0
  52. package/js/browser-extensions/standard-fonts/Courier.js +38 -0
  53. package/js/browser-extensions/standard-fonts/Helvetica.js +38 -0
  54. package/js/browser-extensions/standard-fonts/Symbol.js +23 -0
  55. package/js/browser-extensions/standard-fonts/Times.js +38 -0
  56. package/js/browser-extensions/standard-fonts/ZapfDingbats.js +23 -0
  57. package/js/browser-extensions/virtual-fs-cjs.js +3 -0
  58. package/js/columnCalculator.js +148 -0
  59. package/js/helpers/node.js +122 -0
  60. package/js/helpers/tools.js +46 -0
  61. package/js/helpers/variableType.js +59 -0
  62. package/js/index.js +15 -0
  63. package/js/qrEnc.js +721 -0
  64. package/js/standardPageSizes.js +56 -0
  65. package/js/tableLayouts.js +98 -0
  66. package/js/virtual-fs.js +60 -0
  67. package/package.json +94 -0
  68. package/src/3rd-party/svg-to-pdfkit/LICENSE +9 -0
  69. package/src/3rd-party/svg-to-pdfkit/source.js +2745 -0
  70. package/src/3rd-party/svg-to-pdfkit.js +3 -0
  71. package/src/DocMeasure.js +768 -0
  72. package/src/DocPreprocessor.js +289 -0
  73. package/src/DocumentContext.js +345 -0
  74. package/src/ElementWriter.js +468 -0
  75. package/src/LayoutBuilder.js +1366 -0
  76. package/src/Line.js +108 -0
  77. package/src/OutputDocument.js +64 -0
  78. package/src/OutputDocumentServer.js +32 -0
  79. package/src/PDFDocument.js +178 -0
  80. package/src/PageElementWriter.js +191 -0
  81. package/src/PageSize.js +53 -0
  82. package/src/Printer.js +306 -0
  83. package/src/Renderer.js +546 -0
  84. package/src/SVGMeasure.js +109 -0
  85. package/src/StyleContextStack.js +208 -0
  86. package/src/TableProcessor.js +620 -0
  87. package/src/TextBreaker.js +181 -0
  88. package/src/TextDecorator.js +175 -0
  89. package/src/TextInlines.js +229 -0
  90. package/src/URLResolver.js +43 -0
  91. package/src/base.js +70 -0
  92. package/src/browser-extensions/OutputDocumentBrowser.js +80 -0
  93. package/src/browser-extensions/fonts/Roboto.js +27 -0
  94. package/src/browser-extensions/index.js +55 -0
  95. package/src/browser-extensions/pdfMake.js +1 -0
  96. package/src/browser-extensions/standard-fonts/Courier.js +27 -0
  97. package/src/browser-extensions/standard-fonts/Helvetica.js +27 -0
  98. package/src/browser-extensions/standard-fonts/Symbol.js +21 -0
  99. package/src/browser-extensions/standard-fonts/Times.js +27 -0
  100. package/src/browser-extensions/standard-fonts/ZapfDingbats.js +21 -0
  101. package/src/browser-extensions/virtual-fs-cjs.js +1 -0
  102. package/src/columnCalculator.js +154 -0
  103. package/src/helpers/node.js +134 -0
  104. package/src/helpers/tools.js +44 -0
  105. package/src/helpers/variableType.js +50 -0
  106. package/src/index.js +16 -0
  107. package/src/qrEnc.js +796 -0
  108. package/src/standardPageSizes.js +52 -0
  109. package/src/tableLayouts.js +100 -0
  110. package/src/virtual-fs.js +66 -0
  111. package/standard-fonts/Courier.js +8 -0
  112. package/standard-fonts/Helvetica.js +8 -0
  113. package/standard-fonts/Symbol.js +5 -0
  114. package/standard-fonts/Times.js +8 -0
  115. package/standard-fonts/ZapfDingbats.js +5 -0
@@ -0,0 +1,546 @@
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
+ this.hasFormInit = false;
45
+ this.outlineMap = [];
46
+ }
47
+
48
+ renderPages(pages) {
49
+ this.pdfDocument._pdfMakePages = pages; // TODO: Why?
50
+
51
+ let totalItems = 0;
52
+ if (this.progressCallback) {
53
+ pages.forEach(page => {
54
+ totalItems += page.items.length;
55
+ });
56
+ }
57
+
58
+ let renderedItems = 0;
59
+
60
+ for (let i = 0; i < pages.length; i++) {
61
+ this.pdfDocument.addPage({ size: [pages[i].pageSize.width, pages[i].pageSize.height] });
62
+
63
+ let page = pages[i];
64
+ for (let ii = 0, il = page.items.length; ii < il; ii++) {
65
+ let item = page.items[ii];
66
+ switch (item.type) {
67
+ case 'vector':
68
+ this.renderVector(item.item);
69
+ break;
70
+ case 'line':
71
+ this.renderLine(item.item, item.item.x, item.item.y);
72
+ break;
73
+ case 'image':
74
+ this.renderImage(item.item);
75
+ break;
76
+ case 'svg':
77
+ this.renderSVG(item.item);
78
+ break;
79
+ case 'acroform':
80
+ this.renderAcroForm(item.item);
81
+ break;
82
+ case 'attachment':
83
+ this.renderAttachment(item.item);
84
+ break;
85
+ case 'beginClip':
86
+ this.beginClip(item.item);
87
+ break;
88
+ case 'endClip':
89
+ this.endClip();
90
+ break;
91
+ case 'beginVerticalAlignment':
92
+ this.beginVerticalAlignment(item.item);
93
+ break;
94
+ case 'endVerticalAlignment':
95
+ this.endVerticalAlignment(item.item);
96
+ break;
97
+ }
98
+ renderedItems++;
99
+ if (this.progressCallback) {
100
+ this.progressCallback(renderedItems / totalItems);
101
+ }
102
+ }
103
+ if (page.watermark) {
104
+ this.renderWatermark(page);
105
+ }
106
+ }
107
+ }
108
+
109
+ renderLine(line, x, y) {
110
+ function preparePageNodeRefLine(_pageNodeRef, inline) {
111
+ let newWidth;
112
+ let diffWidth;
113
+ let textInlines = new TextInlines(null);
114
+
115
+ if (_pageNodeRef.positions === undefined) {
116
+ throw new Error('Page reference id not found');
117
+ }
118
+
119
+ let pageNumber = _pageNodeRef.positions[0].pageNumber.toString();
120
+
121
+ inline.text = pageNumber;
122
+ newWidth = textInlines.widthOfText(inline.text, inline);
123
+ diffWidth = inline.width - newWidth;
124
+ inline.width = newWidth;
125
+
126
+ switch (inline.alignment) {
127
+ case 'right':
128
+ inline.x += diffWidth;
129
+ break;
130
+ case 'center':
131
+ inline.x += diffWidth / 2;
132
+ break;
133
+ }
134
+ }
135
+
136
+ if (line._outline) {
137
+ let parentOutline = this.pdfDocument.outline;
138
+ if (line._outline.parentId && this.outlineMap[line._outline.parentId]) {
139
+ parentOutline = this.outlineMap[line._outline.parentId];
140
+ }
141
+
142
+ let outline = parentOutline.addItem(line._outline.text, { expanded: line._outline.expanded });
143
+ if (line._outline.id) {
144
+ this.outlineMap[line._outline.id] = outline;
145
+ }
146
+ }
147
+
148
+ if (line._pageNodeRef) {
149
+ preparePageNodeRefLine(line._pageNodeRef, line.inlines[0]);
150
+ }
151
+
152
+ x = x || 0;
153
+ y = y || 0;
154
+
155
+ let lineHeight = line.getHeight();
156
+ let ascenderHeight = line.getAscenderHeight();
157
+ let descent = lineHeight - ascenderHeight;
158
+
159
+ const textDecorator = new TextDecorator(this.pdfDocument);
160
+
161
+ textDecorator.drawBackground(line, x, y);
162
+
163
+ //TODO: line.optimizeInlines();
164
+ //TODO: lines without differently styled inlines should be written to pdf as one stream
165
+ for (let i = 0, l = line.inlines.length; i < l; i++) {
166
+ let inline = line.inlines[i];
167
+ let shiftToBaseline = lineHeight - ((inline.font.ascender / 1000) * inline.fontSize) - descent;
168
+
169
+ if (inline.acroform) {
170
+ //TODO positioning issue
171
+ let shiftedY = y + (lineHeight - ((inline.font.ascender / 1000) * inline.height) - descent);
172
+ inline.y = shiftedY;
173
+ inline.x = x + inline.x;
174
+
175
+ this.renderAcroForm(inline);
176
+ } else {
177
+ if (inline._pageNodeRef) {
178
+ preparePageNodeRefLine(inline._pageNodeRef, inline);
179
+ }
180
+
181
+ let options = {
182
+ lineBreak: false,
183
+ textWidth: inline.width,
184
+ characterSpacing: inline.characterSpacing,
185
+ wordCount: 1,
186
+ link: inline.link
187
+ };
188
+
189
+ if (inline.linkToDestination) {
190
+ options.goTo = inline.linkToDestination;
191
+ }
192
+
193
+ if (line.id && i === 0) {
194
+ options.destination = line.id;
195
+ }
196
+
197
+ if (inline.fontFeatures) {
198
+ options.features = inline.fontFeatures;
199
+ }
200
+
201
+ let opacity = isNumber(inline.opacity) ? inline.opacity : 1;
202
+ this.pdfDocument.opacity(opacity);
203
+ this.pdfDocument.fill(inline.color || 'black');
204
+
205
+ this.pdfDocument._font = inline.font;
206
+ this.pdfDocument.fontSize(inline.fontSize);
207
+
208
+ let shiftedY = offsetText(y + shiftToBaseline, inline);
209
+ this.pdfDocument.text(inline.text, x + inline.x, shiftedY, options);
210
+
211
+ if (inline.linkToPage) {
212
+ this.pdfDocument.ref({ Type: 'Action', S: 'GoTo', D: [inline.linkToPage, 0, 0] }).end();
213
+ this.pdfDocument.annotate(x + inline.x, shiftedY, inline.width, inline.height, { Subtype: 'Link', Dest: [inline.linkToPage - 1, 'XYZ', null, null, null] });
214
+ }
215
+ }
216
+ }
217
+
218
+ // Decorations won't draw correctly for superscript
219
+ textDecorator.drawDecorations(line, x, y);
220
+ }
221
+
222
+ renderVector(vector) {
223
+ //TODO: pdf optimization (there's no need to write all properties everytime)
224
+ this.pdfDocument.lineWidth(vector.lineWidth || 1);
225
+ if (vector.dash) {
226
+ this.pdfDocument.dash(vector.dash.length, { space: vector.dash.space || vector.dash.length, phase: vector.dash.phase || 0 });
227
+ } else {
228
+ this.pdfDocument.undash();
229
+ }
230
+ this.pdfDocument.lineJoin(vector.lineJoin || 'miter');
231
+ this.pdfDocument.lineCap(vector.lineCap || 'butt');
232
+
233
+ //TODO: clipping
234
+
235
+ let gradient = null;
236
+
237
+ switch (vector.type) {
238
+ case 'ellipse':
239
+ this.pdfDocument.ellipse(vector.x, vector.y, vector.r1, vector.r2);
240
+
241
+ if (vector.linearGradient) {
242
+ gradient = this.pdfDocument.linearGradient(vector.x - vector.r1, vector.y, vector.x + vector.r1, vector.y);
243
+ }
244
+ break;
245
+ case 'rect':
246
+ if (vector.r) {
247
+ this.pdfDocument.roundedRect(vector.x, vector.y, vector.w, vector.h, vector.r);
248
+ } else {
249
+ this.pdfDocument.rect(vector.x, vector.y, vector.w, vector.h);
250
+ }
251
+
252
+ if (vector.linearGradient) {
253
+ gradient = this.pdfDocument.linearGradient(vector.x, vector.y, vector.x + vector.w, vector.y);
254
+ }
255
+ break;
256
+ case 'line':
257
+ this.pdfDocument.moveTo(vector.x1, vector.y1);
258
+ this.pdfDocument.lineTo(vector.x2, vector.y2);
259
+ break;
260
+ case 'polyline':
261
+ if (vector.points.length === 0) {
262
+ break;
263
+ }
264
+
265
+ this.pdfDocument.moveTo(vector.points[0].x, vector.points[0].y);
266
+ for (let i = 1, l = vector.points.length; i < l; i++) {
267
+ this.pdfDocument.lineTo(vector.points[i].x, vector.points[i].y);
268
+ }
269
+
270
+ if (vector.points.length > 1) {
271
+ let p1 = vector.points[0];
272
+ let pn = vector.points[vector.points.length - 1];
273
+
274
+ if (vector.closePath || p1.x === pn.x && p1.y === pn.y) {
275
+ this.pdfDocument.closePath();
276
+ }
277
+ }
278
+ break;
279
+ case 'path':
280
+ this.pdfDocument.path(vector.d);
281
+ break;
282
+ }
283
+
284
+ if (vector.linearGradient && gradient) {
285
+ let step = 1 / (vector.linearGradient.length - 1);
286
+
287
+ for (let i = 0; i < vector.linearGradient.length; i++) {
288
+ gradient.stop(i * step, vector.linearGradient[i]);
289
+ }
290
+
291
+ vector.color = gradient;
292
+ }
293
+
294
+ let patternColor = this.pdfDocument.providePattern(vector.color);
295
+ if (patternColor !== null) {
296
+ vector.color = patternColor;
297
+ }
298
+
299
+ let fillOpacity = isNumber(vector.fillOpacity) ? vector.fillOpacity : 1;
300
+ let strokeOpacity = isNumber(vector.strokeOpacity) ? vector.strokeOpacity : 1;
301
+
302
+ if (vector.color && vector.lineColor) {
303
+ this.pdfDocument.fillColor(vector.color, fillOpacity);
304
+ this.pdfDocument.strokeColor(vector.lineColor, strokeOpacity);
305
+ this.pdfDocument.fillAndStroke();
306
+ } else if (vector.color) {
307
+ this.pdfDocument.fillColor(vector.color, fillOpacity);
308
+ this.pdfDocument.fill();
309
+ } else {
310
+ this.pdfDocument.strokeColor(vector.lineColor || 'black', strokeOpacity);
311
+ this.pdfDocument.stroke();
312
+ }
313
+ }
314
+
315
+ renderAcroForm(node) {
316
+ const { font, bold, italics } = node;
317
+ let { type, options } = node.acroform;
318
+
319
+ if (options == null) {
320
+ options = {};
321
+ }
322
+
323
+ if (this.hasFormInit == false) {
324
+ this.pdfDocument.initForm();
325
+ this.hasFormInit = true;
326
+ }
327
+
328
+ const setFont = () => {
329
+ if (typeof font === "string") {
330
+ this.pdfDocument._font = this.pdfDocument.provideFont(font, bold, italics);
331
+ } else {
332
+ this.pdfDocument._font = font;
333
+ }
334
+ // if (this.hasFormInit) {
335
+ // this.pdfDocument.addFontToAcroFormDict();
336
+ // }
337
+ };
338
+
339
+ const id = node.acroform.id;
340
+
341
+ if (id == null) {
342
+ throw new Error(`Acroform field ${id} requires an ID`);
343
+ }
344
+
345
+ let width = node.width || node.availableWidth || (!isNaN(node._calcWidth) && node._calcWidth) || node._minWidth;
346
+ if (node.width == '*') {
347
+ width = node.availableWidth;
348
+ }
349
+
350
+ if (width == null) {
351
+ throw new Error(`Form ${type} width is undefined`);
352
+ }
353
+
354
+ let resolvedType;
355
+
356
+ setFont();
357
+ switch (type) {
358
+ case "text":
359
+ case "formText":
360
+ resolvedType = "formText";
361
+ break;
362
+ case "button":
363
+ case "formPushButton":
364
+ resolvedType = "formPushButton";
365
+ break;
366
+ case "list":
367
+ case "formList":
368
+ resolvedType = "formList";
369
+ break;
370
+ case "combo":
371
+ case "formCombo":
372
+ resolvedType = "formCombo";
373
+ break;
374
+ case "checkbox":
375
+ case "formCheckbox":
376
+ resolvedType = "formCheckbox";
377
+ break;
378
+ case "radio":
379
+ case "formRadio":
380
+ case "formRadioButton":
381
+ resolvedType = "formRadioButton";
382
+ break;
383
+ default:
384
+ throw new Error(`Unrecognized acroform type: ${type}`);
385
+ }
386
+
387
+ this.pdfDocument[resolvedType](id, node.x, node.y, width, node.height, options);
388
+ }
389
+
390
+ renderImage(image) {
391
+ let opacity = isNumber(image.opacity) ? image.opacity : 1;
392
+ this.pdfDocument.opacity(opacity);
393
+ if (image.cover) {
394
+ const align = image.cover.align || 'center';
395
+ const valign = image.cover.valign || 'center';
396
+ const width = image.cover.width ? image.cover.width : image.width;
397
+ const height = image.cover.height ? image.cover.height : image.height;
398
+ this.pdfDocument.save();
399
+ this.pdfDocument.rect(image.x, image.y, width, height).clip();
400
+ this.pdfDocument.image(image.image, image.x, image.y, { cover: [width, height], align: align, valign: valign });
401
+ this.pdfDocument.restore();
402
+ } else {
403
+ this.pdfDocument.image(image.image, image.x, image.y, { width: image._width, height: image._height });
404
+ }
405
+ if (image.link) {
406
+ this.pdfDocument.link(image.x, image.y, image._width, image._height, image.link);
407
+ }
408
+ if (image.linkToPage) {
409
+ this.pdfDocument.ref({ Type: 'Action', S: 'GoTo', D: [image.linkToPage, 0, 0] }).end();
410
+ this.pdfDocument.annotate(image.x, image.y, image._width, image._height, { Subtype: 'Link', Dest: [image.linkToPage - 1, 'XYZ', null, null, null] });
411
+ }
412
+ if (image.linkToDestination) {
413
+ this.pdfDocument.goTo(image.x, image.y, image._width, image._height, image.linkToDestination);
414
+ }
415
+ if (image.linkToFile) {
416
+ const attachment = this.pdfDocument.provideAttachment(image.linkToFile);
417
+ this.pdfDocument.fileAnnotation(
418
+ image.x,
419
+ image.y,
420
+ image._width,
421
+ image._height,
422
+ attachment,
423
+ // add empty rectangle as file annotation appearance with the same size as the rendered image
424
+ {
425
+ AP: {
426
+ N: {
427
+ Type: 'XObject',
428
+ Subtype: 'Form',
429
+ FormType: 1,
430
+ BBox: [image.x, image.y, image._width, image._height]
431
+ }
432
+ },
433
+ }
434
+ );
435
+ }
436
+ }
437
+
438
+ renderSVG(svg) {
439
+ let options = {
440
+ width: svg._width,
441
+ height: svg._height,
442
+ assumePt: true,
443
+ useCSS: !isString(svg.svg),
444
+ ...svg.options
445
+ };
446
+ options.fontCallback = (family, bold, italic) => {
447
+ let fontsFamily = family.split(',').map(f => f.trim().replace(/('|")/g, ''));
448
+ let font = findFont(this.pdfDocument.fonts, fontsFamily, svg.font || 'Roboto');
449
+
450
+ let fontFile = this.pdfDocument.getFontFile(font, bold, italic);
451
+ if (fontFile === null) {
452
+ let type = this.pdfDocument.getFontType(bold, italic);
453
+ throw new Error(`Font '${font}' in style '${type}' is not defined in the font section of the document definition.`);
454
+ }
455
+
456
+ return fontFile;
457
+ };
458
+
459
+ SVGtoPDF(this.pdfDocument, svg.svg, svg.x, svg.y, options);
460
+
461
+ if (svg.link) {
462
+ this.pdfDocument.link(svg.x, svg.y, svg._width, svg._height, svg.link);
463
+ }
464
+ if (svg.linkToPage) {
465
+ this.pdfDocument.ref({ Type: 'Action', S: 'GoTo', D: [svg.linkToPage, 0, 0] }).end();
466
+ this.pdfDocument.annotate(svg.x, svg.y, svg._width, svg._height, { Subtype: 'Link', Dest: [svg.linkToPage - 1, 'XYZ', null, null, null] });
467
+ }
468
+ if (svg.linkToDestination) {
469
+ this.pdfDocument.goTo(svg.x, svg.y, svg._width, svg._height, svg.linkToDestination);
470
+ }
471
+ }
472
+
473
+ renderAttachment(attachment) {
474
+ const file = this.pdfDocument.provideAttachment(attachment.attachment);
475
+
476
+ const options = {};
477
+ if (attachment.icon) {
478
+ options.Name = attachment.icon;
479
+ }
480
+
481
+ this.pdfDocument.fileAnnotation(attachment.x, attachment.y, attachment._width, attachment._height, file, options);
482
+ }
483
+
484
+ beginClip(rect) {
485
+ this.pdfDocument.save();
486
+ this.pdfDocument.addContent(`${rect.x} ${rect.y} ${rect.width} ${rect.height} re`);
487
+ this.pdfDocument.clip();
488
+ }
489
+
490
+ endClip() {
491
+ this.pdfDocument.restore();
492
+ }
493
+
494
+ beginVerticalAlignment(item) {
495
+ if (item.isCellContentMultiPage) {
496
+ return;
497
+ }
498
+
499
+ switch(item.verticalAlignment) {
500
+ case 'middle':
501
+ this.pdfDocument.save();
502
+ this.pdfDocument.translate(0, -(item.getNodeHeight() - item.getViewHeight()) / 2);
503
+ break;
504
+ case 'bottom':
505
+ this.pdfDocument.save();
506
+ this.pdfDocument.translate(0, -(item.getNodeHeight() - item.getViewHeight()));
507
+ break;
508
+ }
509
+ }
510
+
511
+ endVerticalAlignment(item) {
512
+ if (item.isCellContentMultiPage) {
513
+ return;
514
+ }
515
+
516
+ switch(item.verticalAlignment) {
517
+ case 'middle':
518
+ case 'bottom':
519
+ this.pdfDocument.restore();
520
+ break;
521
+ }
522
+ }
523
+
524
+ renderWatermark(page) {
525
+ let watermark = page.watermark;
526
+
527
+ this.pdfDocument.fill(watermark.color);
528
+ this.pdfDocument.opacity(watermark.opacity);
529
+
530
+ this.pdfDocument.save();
531
+
532
+ this.pdfDocument.rotate(watermark.angle, { origin: [this.pdfDocument.page.width / 2, this.pdfDocument.page.height / 2] });
533
+
534
+ let x = this.pdfDocument.page.width / 2 - watermark._size.size.width / 2;
535
+ let y = this.pdfDocument.page.height / 2 - watermark._size.size.height / 2;
536
+
537
+ this.pdfDocument._font = watermark.font;
538
+ this.pdfDocument.fontSize(watermark.fontSize);
539
+ this.pdfDocument.text(watermark.text, x, y, { lineBreak: false });
540
+
541
+ this.pdfDocument.restore();
542
+ }
543
+
544
+ }
545
+
546
+ export default Renderer;
@@ -0,0 +1,109 @@
1
+ import { XmlDocument } from "xmldoc";
2
+ import { isString } from './helpers/variableType';
3
+
4
+ /**
5
+ * Strip unit postfix, parse number, but return undefined instead of NaN for bad input
6
+ *
7
+ * @param {string} textVal
8
+ * @returns {?number}
9
+ */
10
+ const stripUnits = textVal => {
11
+ let n = parseFloat(textVal);
12
+ if (typeof n !== 'number' || isNaN(n)) {
13
+ return undefined;
14
+ }
15
+ return n;
16
+ };
17
+
18
+ /**
19
+ * Make sure it's valid XML and the root tag is <svg/>, returns xmldoc DOM
20
+ *
21
+ * @param {string} svgString
22
+ * @returns {object}
23
+ */
24
+ const parseSVG = (svgString) => {
25
+ let doc;
26
+
27
+ try {
28
+ doc = new XmlDocument(svgString);
29
+ } catch (err) {
30
+ throw new Error('Invalid svg document (' + err + ')');
31
+ }
32
+
33
+ if (doc.name !== "svg") {
34
+ throw new Error('Invalid svg document (expected <svg>)');
35
+ }
36
+
37
+ return doc;
38
+ };
39
+
40
+ class SVGMeasure {
41
+ constructor() {
42
+
43
+ }
44
+
45
+ measureSVG(svg) {
46
+ let width, height, viewBox;
47
+
48
+ if (isString(svg)) {
49
+ let doc = parseSVG(svg);
50
+
51
+ width = doc.attr.width;
52
+ height = doc.attr.height;
53
+ viewBox = doc.attr.viewBox;
54
+ } else if (typeof SVGElement !== 'undefined' && svg instanceof SVGElement && typeof getComputedStyle === 'function') {
55
+ width = svg.getAttribute("width");
56
+ height = svg.getAttribute("height");
57
+ viewBox = svg.getAttribute("viewBox");
58
+ } else {
59
+ throw new Error('Invalid SVG document');
60
+ }
61
+
62
+ let docWidth = stripUnits(width);
63
+ let docHeight = stripUnits(height);
64
+
65
+ if ((docWidth === undefined || docHeight === undefined) && typeof viewBox === 'string') {
66
+ let viewBoxParts = viewBox.split(/[,\s]+/);
67
+ if (viewBoxParts.length !== 4) {
68
+ throw new Error("Unexpected svg viewBox format, should have 4 entries but found: '" + viewBox + "'");
69
+ }
70
+ if (docWidth === undefined) {
71
+ docWidth = stripUnits(viewBoxParts[2]);
72
+ }
73
+ if (docHeight === undefined) {
74
+ docHeight = stripUnits(viewBoxParts[3]);
75
+ }
76
+ }
77
+
78
+ return {
79
+ width: docWidth,
80
+ height: docHeight
81
+ };
82
+ }
83
+
84
+ writeDimensions(svg, dimensions) {
85
+ if (isString(svg)) {
86
+ let doc = parseSVG(svg);
87
+
88
+ if (typeof doc.attr.viewBox !== 'string') {
89
+ doc.attr.viewBox = `0 0 ${stripUnits(doc.attr.width)} ${stripUnits(doc.attr.height)}`;
90
+ }
91
+
92
+ doc.attr.width = "" + dimensions.width;
93
+ doc.attr.height = "" + dimensions.height;
94
+
95
+ return doc.toString();
96
+ }
97
+
98
+ if (!svg.hasAttribute('viewBox')) {
99
+ svg.setAttribute('viewBox', `0 0 ${stripUnits(svg.getAttribute('width'))} ${stripUnits(svg.getAttribute('height'))}`);
100
+ }
101
+
102
+ svg.setAttribute('width', "" + dimensions.width);
103
+ svg.setAttribute('height', "" + dimensions.height);
104
+
105
+ return svg;
106
+ }
107
+ }
108
+
109
+ export default SVGMeasure;