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,3823 @@
1
+ "use strict";
2
+
3
+ var SVGtoPDF = function (doc, svg, x, y, options) {
4
+ "use strict";
5
+
6
+ const NamedColors = {
7
+ aliceblue: [240, 248, 255],
8
+ antiquewhite: [250, 235, 215],
9
+ aqua: [0, 255, 255],
10
+ aquamarine: [127, 255, 212],
11
+ azure: [240, 255, 255],
12
+ beige: [245, 245, 220],
13
+ bisque: [255, 228, 196],
14
+ black: [0, 0, 0],
15
+ blanchedalmond: [255, 235, 205],
16
+ blue: [0, 0, 255],
17
+ blueviolet: [138, 43, 226],
18
+ brown: [165, 42, 42],
19
+ burlywood: [222, 184, 135],
20
+ cadetblue: [95, 158, 160],
21
+ chartreuse: [127, 255, 0],
22
+ chocolate: [210, 105, 30],
23
+ coral: [255, 127, 80],
24
+ cornflowerblue: [100, 149, 237],
25
+ cornsilk: [255, 248, 220],
26
+ crimson: [220, 20, 60],
27
+ cyan: [0, 255, 255],
28
+ darkblue: [0, 0, 139],
29
+ darkcyan: [0, 139, 139],
30
+ darkgoldenrod: [184, 134, 11],
31
+ darkgray: [169, 169, 169],
32
+ darkgrey: [169, 169, 169],
33
+ darkgreen: [0, 100, 0],
34
+ darkkhaki: [189, 183, 107],
35
+ darkmagenta: [139, 0, 139],
36
+ darkolivegreen: [85, 107, 47],
37
+ darkorange: [255, 140, 0],
38
+ darkorchid: [153, 50, 204],
39
+ darkred: [139, 0, 0],
40
+ darksalmon: [233, 150, 122],
41
+ darkseagreen: [143, 188, 143],
42
+ darkslateblue: [72, 61, 139],
43
+ darkslategray: [47, 79, 79],
44
+ darkslategrey: [47, 79, 79],
45
+ darkturquoise: [0, 206, 209],
46
+ darkviolet: [148, 0, 211],
47
+ deeppink: [255, 20, 147],
48
+ deepskyblue: [0, 191, 255],
49
+ dimgray: [105, 105, 105],
50
+ dimgrey: [105, 105, 105],
51
+ dodgerblue: [30, 144, 255],
52
+ firebrick: [178, 34, 34],
53
+ floralwhite: [255, 250, 240],
54
+ forestgreen: [34, 139, 34],
55
+ fuchsia: [255, 0, 255],
56
+ gainsboro: [220, 220, 220],
57
+ ghostwhite: [248, 248, 255],
58
+ gold: [255, 215, 0],
59
+ goldenrod: [218, 165, 32],
60
+ gray: [128, 128, 128],
61
+ grey: [128, 128, 128],
62
+ green: [0, 128, 0],
63
+ greenyellow: [173, 255, 47],
64
+ honeydew: [240, 255, 240],
65
+ hotpink: [255, 105, 180],
66
+ indianred: [205, 92, 92],
67
+ indigo: [75, 0, 130],
68
+ ivory: [255, 255, 240],
69
+ khaki: [240, 230, 140],
70
+ lavender: [230, 230, 250],
71
+ lavenderblush: [255, 240, 245],
72
+ lawngreen: [124, 252, 0],
73
+ lemonchiffon: [255, 250, 205],
74
+ lightblue: [173, 216, 230],
75
+ lightcoral: [240, 128, 128],
76
+ lightcyan: [224, 255, 255],
77
+ lightgoldenrodyellow: [250, 250, 210],
78
+ lightgray: [211, 211, 211],
79
+ lightgrey: [211, 211, 211],
80
+ lightgreen: [144, 238, 144],
81
+ lightpink: [255, 182, 193],
82
+ lightsalmon: [255, 160, 122],
83
+ lightseagreen: [32, 178, 170],
84
+ lightskyblue: [135, 206, 250],
85
+ lightslategray: [119, 136, 153],
86
+ lightslategrey: [119, 136, 153],
87
+ lightsteelblue: [176, 196, 222],
88
+ lightyellow: [255, 255, 224],
89
+ lime: [0, 255, 0],
90
+ limegreen: [50, 205, 50],
91
+ linen: [250, 240, 230],
92
+ magenta: [255, 0, 255],
93
+ maroon: [128, 0, 0],
94
+ mediumaquamarine: [102, 205, 170],
95
+ mediumblue: [0, 0, 205],
96
+ mediumorchid: [186, 85, 211],
97
+ mediumpurple: [147, 112, 219],
98
+ mediumseagreen: [60, 179, 113],
99
+ mediumslateblue: [123, 104, 238],
100
+ mediumspringgreen: [0, 250, 154],
101
+ mediumturquoise: [72, 209, 204],
102
+ mediumvioletred: [199, 21, 133],
103
+ midnightblue: [25, 25, 112],
104
+ mintcream: [245, 255, 250],
105
+ mistyrose: [255, 228, 225],
106
+ moccasin: [255, 228, 181],
107
+ navajowhite: [255, 222, 173],
108
+ navy: [0, 0, 128],
109
+ oldlace: [253, 245, 230],
110
+ olive: [128, 128, 0],
111
+ olivedrab: [107, 142, 35],
112
+ orange: [255, 165, 0],
113
+ orangered: [255, 69, 0],
114
+ orchid: [218, 112, 214],
115
+ palegoldenrod: [238, 232, 170],
116
+ palegreen: [152, 251, 152],
117
+ paleturquoise: [175, 238, 238],
118
+ palevioletred: [219, 112, 147],
119
+ papayawhip: [255, 239, 213],
120
+ peachpuff: [255, 218, 185],
121
+ peru: [205, 133, 63],
122
+ pink: [255, 192, 203],
123
+ plum: [221, 160, 221],
124
+ powderblue: [176, 224, 230],
125
+ purple: [128, 0, 128],
126
+ rebeccapurple: [102, 51, 153],
127
+ red: [255, 0, 0],
128
+ rosybrown: [188, 143, 143],
129
+ royalblue: [65, 105, 225],
130
+ saddlebrown: [139, 69, 19],
131
+ salmon: [250, 128, 114],
132
+ sandybrown: [244, 164, 96],
133
+ seagreen: [46, 139, 87],
134
+ seashell: [255, 245, 238],
135
+ sienna: [160, 82, 45],
136
+ silver: [192, 192, 192],
137
+ skyblue: [135, 206, 235],
138
+ slateblue: [106, 90, 205],
139
+ slategray: [112, 128, 144],
140
+ slategrey: [112, 128, 144],
141
+ snow: [255, 250, 250],
142
+ springgreen: [0, 255, 127],
143
+ steelblue: [70, 130, 180],
144
+ tan: [210, 180, 140],
145
+ teal: [0, 128, 128],
146
+ thistle: [216, 191, 216],
147
+ tomato: [255, 99, 71],
148
+ turquoise: [64, 224, 208],
149
+ violet: [238, 130, 238],
150
+ wheat: [245, 222, 179],
151
+ white: [255, 255, 255],
152
+ whitesmoke: [245, 245, 245],
153
+ yellow: [255, 255, 0]
154
+ };
155
+ const DefaultColors = {
156
+ black: [NamedColors.black, 1],
157
+ white: [NamedColors.white, 1],
158
+ transparent: [NamedColors.black, 0]
159
+ };
160
+ const Entities = {
161
+ quot: 34,
162
+ amp: 38,
163
+ lt: 60,
164
+ gt: 62,
165
+ apos: 39,
166
+ OElig: 338,
167
+ oelig: 339,
168
+ Scaron: 352,
169
+ scaron: 353,
170
+ Yuml: 376,
171
+ circ: 710,
172
+ tilde: 732,
173
+ ensp: 8194,
174
+ emsp: 8195,
175
+ thinsp: 8201,
176
+ zwnj: 8204,
177
+ zwj: 8205,
178
+ lrm: 8206,
179
+ rlm: 8207,
180
+ ndash: 8211,
181
+ mdash: 8212,
182
+ lsquo: 8216,
183
+ rsquo: 8217,
184
+ sbquo: 8218,
185
+ ldquo: 8220,
186
+ rdquo: 8221,
187
+ bdquo: 8222,
188
+ dagger: 8224,
189
+ Dagger: 8225,
190
+ permil: 8240,
191
+ lsaquo: 8249,
192
+ rsaquo: 8250,
193
+ euro: 8364,
194
+ nbsp: 160,
195
+ iexcl: 161,
196
+ cent: 162,
197
+ pound: 163,
198
+ curren: 164,
199
+ yen: 165,
200
+ brvbar: 166,
201
+ sect: 167,
202
+ uml: 168,
203
+ copy: 169,
204
+ ordf: 170,
205
+ laquo: 171,
206
+ not: 172,
207
+ shy: 173,
208
+ reg: 174,
209
+ macr: 175,
210
+ deg: 176,
211
+ plusmn: 177,
212
+ sup2: 178,
213
+ sup3: 179,
214
+ acute: 180,
215
+ micro: 181,
216
+ para: 182,
217
+ middot: 183,
218
+ cedil: 184,
219
+ sup1: 185,
220
+ ordm: 186,
221
+ raquo: 187,
222
+ frac14: 188,
223
+ frac12: 189,
224
+ frac34: 190,
225
+ iquest: 191,
226
+ Agrave: 192,
227
+ Aacute: 193,
228
+ Acirc: 194,
229
+ Atilde: 195,
230
+ Auml: 196,
231
+ Aring: 197,
232
+ AElig: 198,
233
+ Ccedil: 199,
234
+ Egrave: 200,
235
+ Eacute: 201,
236
+ Ecirc: 202,
237
+ Euml: 203,
238
+ Igrave: 204,
239
+ Iacute: 205,
240
+ Icirc: 206,
241
+ Iuml: 207,
242
+ ETH: 208,
243
+ Ntilde: 209,
244
+ Ograve: 210,
245
+ Oacute: 211,
246
+ Ocirc: 212,
247
+ Otilde: 213,
248
+ Ouml: 214,
249
+ times: 215,
250
+ Oslash: 216,
251
+ Ugrave: 217,
252
+ Uacute: 218,
253
+ Ucirc: 219,
254
+ Uuml: 220,
255
+ Yacute: 221,
256
+ THORN: 222,
257
+ szlig: 223,
258
+ agrave: 224,
259
+ aacute: 225,
260
+ acirc: 226,
261
+ atilde: 227,
262
+ auml: 228,
263
+ aring: 229,
264
+ aelig: 230,
265
+ ccedil: 231,
266
+ egrave: 232,
267
+ eacute: 233,
268
+ ecirc: 234,
269
+ euml: 235,
270
+ igrave: 236,
271
+ iacute: 237,
272
+ icirc: 238,
273
+ iuml: 239,
274
+ eth: 240,
275
+ ntilde: 241,
276
+ ograve: 242,
277
+ oacute: 243,
278
+ ocirc: 244,
279
+ otilde: 245,
280
+ ouml: 246,
281
+ divide: 247,
282
+ oslash: 248,
283
+ ugrave: 249,
284
+ uacute: 250,
285
+ ucirc: 251,
286
+ uuml: 252,
287
+ yacute: 253,
288
+ thorn: 254,
289
+ yuml: 255,
290
+ fnof: 402,
291
+ Alpha: 913,
292
+ Beta: 914,
293
+ Gamma: 915,
294
+ Delta: 916,
295
+ Epsilon: 917,
296
+ Zeta: 918,
297
+ Eta: 919,
298
+ Theta: 920,
299
+ Iota: 921,
300
+ Kappa: 922,
301
+ Lambda: 923,
302
+ Mu: 924,
303
+ Nu: 925,
304
+ Xi: 926,
305
+ Omicron: 927,
306
+ Pi: 928,
307
+ Rho: 929,
308
+ Sigma: 931,
309
+ Tau: 932,
310
+ Upsilon: 933,
311
+ Phi: 934,
312
+ Chi: 935,
313
+ Psi: 936,
314
+ Omega: 937,
315
+ alpha: 945,
316
+ beta: 946,
317
+ gamma: 947,
318
+ delta: 948,
319
+ epsilon: 949,
320
+ zeta: 950,
321
+ eta: 951,
322
+ theta: 952,
323
+ iota: 953,
324
+ kappa: 954,
325
+ lambda: 955,
326
+ mu: 956,
327
+ nu: 957,
328
+ xi: 958,
329
+ omicron: 959,
330
+ pi: 960,
331
+ rho: 961,
332
+ sigmaf: 962,
333
+ sigma: 963,
334
+ tau: 964,
335
+ upsilon: 965,
336
+ phi: 966,
337
+ chi: 967,
338
+ psi: 968,
339
+ omega: 969,
340
+ thetasym: 977,
341
+ upsih: 978,
342
+ piv: 982,
343
+ bull: 8226,
344
+ hellip: 8230,
345
+ prime: 8242,
346
+ Prime: 8243,
347
+ oline: 8254,
348
+ frasl: 8260,
349
+ weierp: 8472,
350
+ image: 8465,
351
+ real: 8476,
352
+ trade: 8482,
353
+ alefsym: 8501,
354
+ larr: 8592,
355
+ uarr: 8593,
356
+ rarr: 8594,
357
+ darr: 8595,
358
+ harr: 8596,
359
+ crarr: 8629,
360
+ lArr: 8656,
361
+ uArr: 8657,
362
+ rArr: 8658,
363
+ dArr: 8659,
364
+ hArr: 8660,
365
+ forall: 8704,
366
+ part: 8706,
367
+ exist: 8707,
368
+ empty: 8709,
369
+ nabla: 8711,
370
+ isin: 8712,
371
+ notin: 8713,
372
+ ni: 8715,
373
+ prod: 8719,
374
+ sum: 8721,
375
+ minus: 8722,
376
+ lowast: 8727,
377
+ radic: 8730,
378
+ prop: 8733,
379
+ infin: 8734,
380
+ ang: 8736,
381
+ and: 8743,
382
+ or: 8744,
383
+ cap: 8745,
384
+ cup: 8746,
385
+ int: 8747,
386
+ there4: 8756,
387
+ sim: 8764,
388
+ cong: 8773,
389
+ asymp: 8776,
390
+ ne: 8800,
391
+ equiv: 8801,
392
+ le: 8804,
393
+ ge: 8805,
394
+ sub: 8834,
395
+ sup: 8835,
396
+ nsub: 8836,
397
+ sube: 8838,
398
+ supe: 8839,
399
+ oplus: 8853,
400
+ otimes: 8855,
401
+ perp: 8869,
402
+ sdot: 8901,
403
+ lceil: 8968,
404
+ rceil: 8969,
405
+ lfloor: 8970,
406
+ rfloor: 8971,
407
+ lang: 9001,
408
+ rang: 9002,
409
+ loz: 9674,
410
+ spades: 9824,
411
+ clubs: 9827,
412
+ hearts: 9829,
413
+ diams: 9830
414
+ };
415
+ const PathArguments = {
416
+ A: 7,
417
+ a: 7,
418
+ C: 6,
419
+ c: 6,
420
+ H: 1,
421
+ h: 1,
422
+ L: 2,
423
+ l: 2,
424
+ M: 2,
425
+ m: 2,
426
+ Q: 4,
427
+ q: 4,
428
+ S: 4,
429
+ s: 4,
430
+ T: 2,
431
+ t: 2,
432
+ V: 1,
433
+ v: 1,
434
+ Z: 0,
435
+ z: 0
436
+ };
437
+ const PathFlags = {
438
+ A3: true,
439
+ A4: true,
440
+ a3: true,
441
+ a4: true
442
+ };
443
+ const Properties = {
444
+ 'color': {
445
+ inherit: true,
446
+ initial: undefined
447
+ },
448
+ 'visibility': {
449
+ inherit: true,
450
+ initial: 'visible',
451
+ values: {
452
+ 'hidden': 'hidden',
453
+ 'collapse': 'hidden',
454
+ 'visible': 'visible'
455
+ }
456
+ },
457
+ 'fill': {
458
+ inherit: true,
459
+ initial: DefaultColors.black
460
+ },
461
+ 'stroke': {
462
+ inherit: true,
463
+ initial: 'none'
464
+ },
465
+ 'stop-color': {
466
+ inherit: false,
467
+ initial: DefaultColors.black
468
+ },
469
+ 'fill-opacity': {
470
+ inherit: true,
471
+ initial: 1
472
+ },
473
+ 'stroke-opacity': {
474
+ inherit: true,
475
+ initial: 1
476
+ },
477
+ 'stop-opacity': {
478
+ inherit: false,
479
+ initial: 1
480
+ },
481
+ 'fill-rule': {
482
+ inherit: true,
483
+ initial: 'nonzero',
484
+ values: {
485
+ 'nonzero': 'nonzero',
486
+ 'evenodd': 'evenodd'
487
+ }
488
+ },
489
+ 'clip-rule': {
490
+ inherit: true,
491
+ initial: 'nonzero',
492
+ values: {
493
+ 'nonzero': 'nonzero',
494
+ 'evenodd': 'evenodd'
495
+ }
496
+ },
497
+ 'stroke-width': {
498
+ inherit: true,
499
+ initial: 1
500
+ },
501
+ 'stroke-dasharray': {
502
+ inherit: true,
503
+ initial: []
504
+ },
505
+ 'stroke-dashoffset': {
506
+ inherit: true,
507
+ initial: 0
508
+ },
509
+ 'stroke-miterlimit': {
510
+ inherit: true,
511
+ initial: 4
512
+ },
513
+ 'stroke-linejoin': {
514
+ inherit: true,
515
+ initial: 'miter',
516
+ values: {
517
+ 'miter': 'miter',
518
+ 'round': 'round',
519
+ 'bevel': 'bevel'
520
+ }
521
+ },
522
+ 'stroke-linecap': {
523
+ inherit: true,
524
+ initial: 'butt',
525
+ values: {
526
+ 'butt': 'butt',
527
+ 'round': 'round',
528
+ 'square': 'square'
529
+ }
530
+ },
531
+ 'font-size': {
532
+ inherit: true,
533
+ initial: 16,
534
+ values: {
535
+ 'xx-small': 9,
536
+ 'x-small': 10,
537
+ 'small': 13,
538
+ 'medium': 16,
539
+ 'large': 18,
540
+ 'x-large': 24,
541
+ 'xx-large': 32
542
+ }
543
+ },
544
+ 'font-family': {
545
+ inherit: true,
546
+ initial: 'sans-serif'
547
+ },
548
+ 'font-weight': {
549
+ inherit: true,
550
+ initial: 'normal',
551
+ values: {
552
+ '600': 'bold',
553
+ '700': 'bold',
554
+ '800': 'bold',
555
+ '900': 'bold',
556
+ 'bold': 'bold',
557
+ 'bolder': 'bold',
558
+ '500': 'normal',
559
+ '400': 'normal',
560
+ '300': 'normal',
561
+ '200': 'normal',
562
+ '100': 'normal',
563
+ 'normal': 'normal',
564
+ 'lighter': 'normal'
565
+ }
566
+ },
567
+ 'font-style': {
568
+ inherit: true,
569
+ initial: 'normal',
570
+ values: {
571
+ 'italic': 'italic',
572
+ 'oblique': 'italic',
573
+ 'normal': 'normal'
574
+ }
575
+ },
576
+ 'text-anchor': {
577
+ inherit: true,
578
+ initial: 'start',
579
+ values: {
580
+ 'start': 'start',
581
+ 'middle': 'middle',
582
+ 'end': 'end'
583
+ }
584
+ },
585
+ 'direction': {
586
+ inherit: true,
587
+ initial: 'ltr',
588
+ values: {
589
+ 'ltr': 'ltr',
590
+ 'rtl': 'rtl'
591
+ }
592
+ },
593
+ 'dominant-baseline': {
594
+ inherit: true,
595
+ initial: 'baseline',
596
+ values: {
597
+ 'auto': 'baseline',
598
+ 'baseline': 'baseline',
599
+ 'before-edge': 'before-edge',
600
+ 'text-before-edge': 'before-edge',
601
+ 'middle': 'middle',
602
+ 'central': 'central',
603
+ 'after-edge': 'after-edge',
604
+ 'text-after-edge': 'after-edge',
605
+ 'ideographic': 'ideographic',
606
+ 'alphabetic': 'alphabetic',
607
+ 'hanging': 'hanging',
608
+ 'mathematical': 'mathematical'
609
+ }
610
+ },
611
+ 'alignment-baseline': {
612
+ inherit: false,
613
+ initial: undefined,
614
+ values: {
615
+ 'auto': 'baseline',
616
+ 'baseline': 'baseline',
617
+ 'before-edge': 'before-edge',
618
+ 'text-before-edge': 'before-edge',
619
+ 'middle': 'middle',
620
+ 'central': 'central',
621
+ 'after-edge': 'after-edge',
622
+ 'text-after-edge': 'after-edge',
623
+ 'ideographic': 'ideographic',
624
+ 'alphabetic': 'alphabetic',
625
+ 'hanging': 'hanging',
626
+ 'mathematical': 'mathematical'
627
+ }
628
+ },
629
+ 'baseline-shift': {
630
+ inherit: true,
631
+ initial: 'baseline',
632
+ values: {
633
+ 'baseline': 'baseline',
634
+ 'sub': 'sub',
635
+ 'super': 'super'
636
+ }
637
+ },
638
+ 'word-spacing': {
639
+ inherit: true,
640
+ initial: 0,
641
+ values: {
642
+ normal: 0
643
+ }
644
+ },
645
+ 'letter-spacing': {
646
+ inherit: true,
647
+ initial: 0,
648
+ values: {
649
+ normal: 0
650
+ }
651
+ },
652
+ 'text-decoration': {
653
+ inherit: false,
654
+ initial: 'none',
655
+ values: {
656
+ 'none': 'none',
657
+ 'underline': 'underline',
658
+ 'overline': 'overline',
659
+ 'line-through': 'line-through'
660
+ }
661
+ },
662
+ 'xml:space': {
663
+ inherit: true,
664
+ initial: 'default',
665
+ css: 'white-space',
666
+ values: {
667
+ 'preserve': 'preserve',
668
+ 'default': 'default',
669
+ 'pre': 'preserve',
670
+ 'pre-line': 'preserve',
671
+ 'pre-wrap': 'preserve',
672
+ 'nowrap': 'default'
673
+ }
674
+ },
675
+ 'marker-start': {
676
+ inherit: true,
677
+ initial: 'none'
678
+ },
679
+ 'marker-mid': {
680
+ inherit: true,
681
+ initial: 'none'
682
+ },
683
+ 'marker-end': {
684
+ inherit: true,
685
+ initial: 'none'
686
+ },
687
+ 'opacity': {
688
+ inherit: false,
689
+ initial: 1
690
+ },
691
+ 'transform': {
692
+ inherit: false,
693
+ initial: [1, 0, 0, 1, 0, 0]
694
+ },
695
+ 'display': {
696
+ inherit: false,
697
+ initial: 'inline',
698
+ values: {
699
+ 'none': 'none',
700
+ 'inline': 'inline',
701
+ 'block': 'inline'
702
+ }
703
+ },
704
+ 'clip-path': {
705
+ inherit: false,
706
+ initial: 'none'
707
+ },
708
+ 'mask': {
709
+ inherit: false,
710
+ initial: 'none'
711
+ },
712
+ 'overflow': {
713
+ inherit: false,
714
+ initial: 'hidden',
715
+ values: {
716
+ 'hidden': 'hidden',
717
+ 'scroll': 'hidden',
718
+ 'visible': 'visible'
719
+ }
720
+ },
721
+ 'vector-effect': {
722
+ inherit: true,
723
+ initial: 'none',
724
+ values: {
725
+ 'none': 'none',
726
+ 'non-scaling-stroke': 'non-scaling-stroke'
727
+ }
728
+ }
729
+ };
730
+ function docBeginGroup(bbox) {
731
+ let group = new function PDFGroup() {}();
732
+ group.name = 'G' + (doc._groupCount = (doc._groupCount || 0) + 1);
733
+ group.resources = doc.ref();
734
+ group.xobj = doc.ref({
735
+ Type: 'XObject',
736
+ Subtype: 'Form',
737
+ FormType: 1,
738
+ BBox: bbox,
739
+ Group: {
740
+ S: 'Transparency',
741
+ CS: 'DeviceRGB',
742
+ I: true,
743
+ K: false
744
+ },
745
+ Resources: group.resources
746
+ });
747
+ group.xobj.write('');
748
+ group.savedMatrix = doc._ctm;
749
+ group.savedPage = doc.page;
750
+ groupStack.push(group);
751
+ doc._ctm = [1, 0, 0, 1, 0, 0];
752
+ doc.page = {
753
+ width: doc.page.width,
754
+ height: doc.page.height,
755
+ write: function (data) {
756
+ group.xobj.write(data);
757
+ },
758
+ fonts: {},
759
+ xobjects: {},
760
+ ext_gstates: {},
761
+ patterns: {}
762
+ };
763
+ return group;
764
+ }
765
+ function docEndGroup(group) {
766
+ if (group !== groupStack.pop()) {
767
+ throw 'Group not matching';
768
+ }
769
+ if (Object.keys(doc.page.fonts).length) {
770
+ group.resources.data.Font = doc.page.fonts;
771
+ }
772
+ if (Object.keys(doc.page.xobjects).length) {
773
+ group.resources.data.XObject = doc.page.xobjects;
774
+ }
775
+ if (Object.keys(doc.page.ext_gstates).length) {
776
+ group.resources.data.ExtGState = doc.page.ext_gstates;
777
+ }
778
+ if (Object.keys(doc.page.patterns).length) {
779
+ group.resources.data.Pattern = doc.page.patterns;
780
+ }
781
+ group.resources.end();
782
+ group.xobj.end();
783
+ doc._ctm = group.savedMatrix;
784
+ doc.page = group.savedPage;
785
+ }
786
+ function docInsertGroup(group) {
787
+ doc.page.xobjects[group.name] = group.xobj;
788
+ doc.addContent('/' + group.name + ' Do');
789
+ }
790
+ function docApplyMask(group, clip) {
791
+ let name = 'M' + (doc._maskCount = (doc._maskCount || 0) + 1);
792
+ let gstate = doc.ref({
793
+ Type: 'ExtGState',
794
+ CA: 1,
795
+ ca: 1,
796
+ BM: 'Normal',
797
+ SMask: {
798
+ S: 'Luminosity',
799
+ G: group.xobj,
800
+ BC: clip ? [0, 0, 0] : [1, 1, 1]
801
+ }
802
+ });
803
+ gstate.end();
804
+ doc.page.ext_gstates[name] = gstate;
805
+ doc.addContent('/' + name + ' gs');
806
+ }
807
+ function docCreatePattern(group, dx, dy, matrix) {
808
+ let pattern = {
809
+ type: 'PDFPattern',
810
+ group: group,
811
+ dx: dx,
812
+ dy: dy,
813
+ matrix: matrix || [1, 0, 0, 1, 0, 0]
814
+ };
815
+ return pattern;
816
+ }
817
+ function docUsePattern(pattern, stroke) {
818
+ let name = 'P' + (doc._patternCount = (doc._patternCount || 0) + 1);
819
+ let ref = doc.ref({
820
+ Type: 'Pattern',
821
+ PatternType: 1,
822
+ PaintType: 1,
823
+ TilingType: 2,
824
+ BBox: [0, 0, pattern.dx, pattern.dy],
825
+ XStep: pattern.dx,
826
+ YStep: pattern.dy,
827
+ Matrix: multiplyMatrix(doc._ctm, pattern.matrix),
828
+ Resources: {
829
+ ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI'],
830
+ XObject: function () {
831
+ let temp = {};
832
+ temp[pattern.group.name] = pattern.group.xobj;
833
+ return temp;
834
+ }()
835
+ }
836
+ });
837
+ ref.write('/' + pattern.group.name + ' Do');
838
+ ref.end();
839
+ doc.page.patterns[name] = ref;
840
+ if (stroke) {
841
+ doc.addContent('/Pattern CS');
842
+ doc.addContent('/' + name + ' SCN');
843
+ } else {
844
+ doc.addContent('/Pattern cs');
845
+ doc.addContent('/' + name + ' scn');
846
+ }
847
+ }
848
+ function docBeginText(font, size) {
849
+ if (!doc.page.fonts[font.id]) {
850
+ doc.page.fonts[font.id] = font.ref();
851
+ }
852
+ doc.addContent('BT').addContent('/' + font.id + ' ' + size + ' Tf');
853
+ }
854
+ function docSetTextMatrix(a, b, c, d, e, f) {
855
+ doc.addContent(validateNumber(a) + ' ' + validateNumber(b) + ' ' + validateNumber(-c) + ' ' + validateNumber(-d) + ' ' + validateNumber(e) + ' ' + validateNumber(f) + ' Tm');
856
+ }
857
+ function docSetTextMode(fill, stroke) {
858
+ let mode = fill && stroke ? 2 : stroke ? 1 : fill ? 0 : 3;
859
+ doc.addContent(mode + ' Tr');
860
+ }
861
+ function docWriteGlyphs(positions, font) {
862
+ let commands = [];
863
+ let commandStr = '';
864
+ const skew = font.fauxItalic ? -0.25 : 0;
865
+
866
+ // Add the given character to the 'TJ' command string.
867
+ function addChar(char) {
868
+ commandStr += char.glyph;
869
+ if (char.kern === 0) return;
870
+ commands.push(`<${commandStr}> ${validateNumber(char.kern)}`);
871
+ commandStr = '';
872
+ }
873
+ ;
874
+
875
+ // Flush the current TJ command string to the output stream.
876
+ function flush() {
877
+ if (commandStr.length) {
878
+ commands.push(`<${commandStr}> 0`);
879
+ commandStr = '';
880
+ }
881
+ if (commands.length) {
882
+ doc.addContent(`[${commands.join(' ')}] TJ`);
883
+ commands = [];
884
+ }
885
+ }
886
+ ;
887
+ for (let i = 0; i < positions.length; i++) {
888
+ const pos = positions[i];
889
+ if (pos.hidden || isEqual(pos.width, 0)) {
890
+ flush();
891
+ continue;
892
+ }
893
+ if (pos.continuous) {
894
+ addChar(pos);
895
+ continue;
896
+ }
897
+
898
+ // If this character is non-continuous, flush the command buffer.
899
+ flush();
900
+
901
+ // Start a new TJ command after writing a Text Matrix (Tm)
902
+ const cos = Math.cos(pos.rotate);
903
+ const sin = Math.sin(pos.rotate);
904
+ docSetTextMatrix(cos * pos.scale, sin * pos.scale, cos * skew - sin, sin * skew + cos, pos.x, pos.y);
905
+ addChar(pos);
906
+ }
907
+ ;
908
+
909
+ // Flush any remaining characters in the buffer.
910
+ flush();
911
+ }
912
+ function docEndText() {
913
+ doc.addContent('ET');
914
+ }
915
+ function docFillColor(color) {
916
+ if (color[0].type === 'PDFPattern') {
917
+ doc.fillOpacity(color[1]);
918
+ docUsePattern(color[0], false);
919
+ } else {
920
+ doc.fillColor(color[0], color[1]);
921
+ }
922
+ }
923
+ function docStrokeColor(color) {
924
+ if (color[0].type === 'PDFPattern') {
925
+ doc.strokeOpacity(color[1]);
926
+ docUsePattern(color[0], true);
927
+ } else {
928
+ doc.strokeColor(color[0], color[1]);
929
+ }
930
+ }
931
+ // PDFKit doesn't accept any 0s in the dash array, but that's perfectly
932
+ // valid in SVG. So this function applys a dash array and offset, detecting
933
+ // any 0s in the dash array and updating it and the dash offset as needed to
934
+ // remove the zeros, but preserve the end result.
935
+ //
936
+ // `dashArray` must have an even number of elements
937
+ function docApplyDash(dashArray, dashOffset) {
938
+ let index;
939
+ // Anytime there's a 0 that isn't the first or last element of the array,
940
+ // we can remove it by combining the previous or next value. If it's a
941
+ // dash, then it's a zero-length dash between two spaces, so the dash can
942
+ // be eliminated and spaces combined by summing them, replacing all three
943
+ // values with the sum of the two spaces. If the 0 value is a space, then
944
+ // it's a zero-length space between two dashes, and the dashes can be
945
+ // similarly combined. So first we run that logic iteratively to remove
946
+ // all the 0s from the dash array that aren't the first or last element.
947
+ // Note that because we replace 3 values with one value, this doesn't
948
+ // change the even-ness of the length of dashArray.
949
+ while ((index = dashArray.slice(1, -1).indexOf(0)) !== -1) {
950
+ let actualIndex = index + 1;
951
+ let replacementValue = dashArray[actualIndex - 1] + dashArray[actualIndex + 1];
952
+ dashArray = dashArray.slice(0, actualIndex - 1).concat([replacementValue]).concat(dashArray.slice(actualIndex + 2));
953
+ }
954
+
955
+ // The stroke array only having two elements (a dash value and space
956
+ // value) is a special case.
957
+ if (dashArray.length === 2) {
958
+ if (dashArray[0] === 0) {
959
+ // Regardless of the space value, the dash length is zero, so we're
960
+ // not actually drawing a stroke. We can't describe that in a
961
+ // doc.dash() call in a way that PDFKit will accept, so we set the
962
+ // stroke opacity to zero as our best approximation.
963
+ doc.strokeOpacity(0);
964
+ return;
965
+ } else if (dashArray[1] === 0) {
966
+ // Regardless of the dash value, the space value is zero, meaning
967
+ // we're actually drawing a solid stroke, not a dashed one. We can
968
+ // make this happen by just emptying out the dash array.
969
+ dashArray = [];
970
+ }
971
+ } else {
972
+ if (dashArray[0] === 0) {
973
+ // The first dash is zero-length. We fix this by combining the first
974
+ // space (just after the first dash) with the last space and updating
975
+ // the dash offset accordingly. For example, if we had
976
+ //
977
+ // [ 0 4 3 2 5 1 ] (dash offset 0)
978
+ //
979
+ // ␣␣␣␣---␣␣-----␣
980
+ // ⎸
981
+ //
982
+ // we'd end up with
983
+ //
984
+ // [ 3 2 5 5 ] (dash offset -4)
985
+ //
986
+ // ---␣␣-----␣␣␣␣␣
987
+ // ⎸
988
+ //
989
+ // Another example where the dash array also ends with a 0:
990
+ //
991
+ // [ 0 4 3 2 5 0 ] (dash offset 0)
992
+ //
993
+ // ␣␣␣␣---␣␣-----
994
+ // ⎸
995
+ //
996
+ // we'd end up with
997
+ //
998
+ // [ 3 2 5 4 ] (dash offset -4)
999
+ //
1000
+ // ---␣␣-----␣␣␣␣
1001
+ // ⎸
1002
+ dashOffset -= dashArray[1];
1003
+ dashArray[dashArray.length - 1] += dashArray[1];
1004
+ dashArray = dashArray.slice(2);
1005
+ }
1006
+ if (dashArray[dashArray.length - 1] === 0) {
1007
+ // The last space is zero-length. We fix this by combining the last dash
1008
+ // (just before the last space) with the first dash and updating the
1009
+ // dash offset accordingly. For example, if we had
1010
+ //
1011
+ // [ 1 4 3 2 5 0 ] (dash offset 0)
1012
+ //
1013
+ // -␣␣␣␣---␣␣-----
1014
+ // ⎸
1015
+ //
1016
+ // we'd end up with
1017
+ //
1018
+ // [ 6 4 3 2 ] (dash offset 5)
1019
+ //
1020
+ // ------␣␣␣␣---␣␣
1021
+ // ⎸
1022
+ //
1023
+ dashOffset += dashArray[dashArray.length - 2];
1024
+ dashArray[0] += dashArray[dashArray.length - 2];
1025
+ dashArray = dashArray.slice(0, -2);
1026
+ }
1027
+ }
1028
+
1029
+ // Ensure the dash offset is non-negative (because of crbug.com/660850).
1030
+ // First compute the total length of the dash array so we can add it to
1031
+ // dash offset until dash offset is non-negative.
1032
+ let length = 0;
1033
+ for (let i = 0; i < dashArray.length; i++) {
1034
+ length += dashArray[i];
1035
+ }
1036
+ if (length > 0) {
1037
+ while (dashOffset < 0) {
1038
+ dashOffset += length;
1039
+ }
1040
+ }
1041
+ doc.dash(dashArray, {
1042
+ phase: dashOffset
1043
+ });
1044
+ }
1045
+ function docInsertLink(x, y, w, h, url) {
1046
+ let ref = doc.ref({
1047
+ Type: 'Annot',
1048
+ Subtype: 'Link',
1049
+ Rect: [x, y, w, h],
1050
+ Border: [0, 0, 0],
1051
+ A: {
1052
+ S: 'URI',
1053
+ URI: new String(url)
1054
+ }
1055
+ });
1056
+ ref.end();
1057
+ links.push(ref);
1058
+ }
1059
+ function parseXml(xml) {
1060
+ let SvgNode = function (tag, type, value, error) {
1061
+ this.error = error;
1062
+ this.nodeName = tag;
1063
+ this.nodeValue = value;
1064
+ this.nodeType = type;
1065
+ this.attributes = Object.create(null);
1066
+ this.childNodes = [];
1067
+ this.parentNode = null;
1068
+ this.id = '';
1069
+ this.textContent = '';
1070
+ this.classList = [];
1071
+ };
1072
+ SvgNode.prototype.getAttribute = function (attr) {
1073
+ return this.attributes[attr] != null ? this.attributes[attr] : null;
1074
+ };
1075
+ SvgNode.prototype.getElementById = function (id) {
1076
+ let result = null;
1077
+ (function recursive(node) {
1078
+ if (result) {
1079
+ return;
1080
+ }
1081
+ if (node.nodeType === 1) {
1082
+ if (node.id === id) {
1083
+ result = node;
1084
+ }
1085
+ for (let i = 0; i < node.childNodes.length; i++) {
1086
+ recursive(node.childNodes[i]);
1087
+ }
1088
+ }
1089
+ })(this);
1090
+ return result;
1091
+ };
1092
+ SvgNode.prototype.getElementsByTagName = function (tag) {
1093
+ let result = [];
1094
+ (function recursive(node) {
1095
+ if (node.nodeType === 1) {
1096
+ if (node.nodeName === tag) {
1097
+ result.push(node);
1098
+ }
1099
+ for (let i = 0; i < node.childNodes.length; i++) {
1100
+ recursive(node.childNodes[i]);
1101
+ }
1102
+ }
1103
+ })(this);
1104
+ return result;
1105
+ };
1106
+ let parser = new StringParser(xml.trim()),
1107
+ result,
1108
+ child,
1109
+ error = false;
1110
+ let recursive = function () {
1111
+ let temp, child;
1112
+ if (temp = parser.match(/^<([\w:.-]+)\s*/, true)) {
1113
+ // Opening tag
1114
+ let node = new SvgNode(temp[1], 1, null, error);
1115
+ while (temp = parser.match(/^([\w:.-]+)(?:\s*=\s*"([^"]*)"|\s*=\s*'([^']*)')?\s*/, true)) {
1116
+ // Attribute
1117
+ let attr = temp[1],
1118
+ value = decodeEntities(temp[2] || temp[3] || '');
1119
+ if (!node.attributes[attr]) {
1120
+ node.attributes[attr] = value;
1121
+ if (attr === 'id') {
1122
+ node.id = value;
1123
+ }
1124
+ if (attr === 'class') {
1125
+ node.classList = value.split(' ');
1126
+ }
1127
+ } else {
1128
+ warningCallback('parseXml: duplicate attribute "' + attr + '"');
1129
+ error = true;
1130
+ }
1131
+ }
1132
+ if (parser.match(/^>/)) {
1133
+ // End of opening tag
1134
+ while (child = recursive()) {
1135
+ node.childNodes.push(child);
1136
+ child.parentNode = node;
1137
+ node.textContent += child.nodeType === 3 || child.nodeType === 4 ? child.nodeValue : child.textContent;
1138
+ }
1139
+ if (temp = parser.match(/^<\/([\w:.-]+)\s*>/, true)) {
1140
+ // Closing tag
1141
+ if (temp[1] === node.nodeName) {
1142
+ return node;
1143
+ } else {
1144
+ warningCallback('parseXml: tag not matching, opening "' + node.nodeName + '" & closing "' + temp[1] + '"');
1145
+ error = true;
1146
+ return node;
1147
+ }
1148
+ } else {
1149
+ warningCallback('parseXml: tag not matching, opening "' + node.nodeName + '" & not closing');
1150
+ error = true;
1151
+ return node;
1152
+ }
1153
+ } else if (parser.match(/^\/>/)) {
1154
+ // Self-closing tag
1155
+ return node;
1156
+ } else {
1157
+ warningCallback('parseXml: tag could not be parsed "' + node.nodeName + '"');
1158
+ error = true;
1159
+ }
1160
+ } else if (temp = parser.match(/^<!--[\s\S]*?-->/)) {
1161
+ // Comment
1162
+ return new SvgNode(null, 8, temp, error);
1163
+ } else if (temp = parser.match(/^<\?[\s\S]*?\?>/)) {
1164
+ // Processing instructions
1165
+ return new SvgNode(null, 7, temp, error);
1166
+ } else if (temp = parser.match(/^<!DOCTYPE\s*([\s\S]*?)>/)) {
1167
+ // Doctype
1168
+ return new SvgNode(null, 10, temp, error);
1169
+ } else if (temp = parser.match(/^<!\[CDATA\[([\s\S]*?)\]\]>/, true)) {
1170
+ // Cdata node
1171
+ return new SvgNode('#cdata-section', 4, temp[1], error);
1172
+ } else if (temp = parser.match(/^([^<]+)/, true)) {
1173
+ // Text node
1174
+ return new SvgNode('#text', 3, decodeEntities(temp[1]), error);
1175
+ }
1176
+ };
1177
+ while (child = recursive()) {
1178
+ if (child.nodeType === 1 && !result) {
1179
+ result = child;
1180
+ } else if (child.nodeType === 1 || child.nodeType === 3 && child.nodeValue.trim() !== '') {
1181
+ warningCallback('parseXml: data after document end has been discarded');
1182
+ }
1183
+ }
1184
+ if (parser.matchAll()) {
1185
+ warningCallback('parseXml: parsing error');
1186
+ }
1187
+ return result;
1188
+ }
1189
+ ;
1190
+ function decodeEntities(str) {
1191
+ return str.replace(/&(?:#([0-9]+)|#[xX]([0-9A-Fa-f]+)|([0-9A-Za-z]+));/g, function (mt, m0, m1, m2) {
1192
+ if (m0) {
1193
+ return String.fromCharCode(parseInt(m0, 10));
1194
+ } else if (m1) {
1195
+ return String.fromCharCode(parseInt(m1, 16));
1196
+ } else if (m2 && Entities[m2]) {
1197
+ return String.fromCharCode(Entities[m2]);
1198
+ } else {
1199
+ return mt;
1200
+ }
1201
+ });
1202
+ }
1203
+ function parseColor(raw) {
1204
+ let temp, result;
1205
+ raw = (raw || '').trim();
1206
+ if (temp = NamedColors[raw]) {
1207
+ result = [temp.slice(), 1];
1208
+ } else if (temp = raw.match(/^cmyk\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9.]+)\s*\)$/i)) {
1209
+ temp[1] = parseInt(temp[1]);
1210
+ temp[2] = parseInt(temp[2]);
1211
+ temp[3] = parseInt(temp[3]);
1212
+ temp[4] = parseFloat(temp[4]);
1213
+ if (temp[1] <= 100 && temp[2] <= 100 && temp[3] <= 100 && temp[4] <= 100) {
1214
+ result = [temp.slice(1, 5), 1];
1215
+ }
1216
+ } else if (temp = raw.match(/^rgba\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9.]+)\s*\)$/i)) {
1217
+ temp[1] = parseInt(temp[1]);
1218
+ temp[2] = parseInt(temp[2]);
1219
+ temp[3] = parseInt(temp[3]);
1220
+ temp[4] = parseFloat(temp[4]);
1221
+ if (temp[1] < 256 && temp[2] < 256 && temp[3] < 256 && temp[4] <= 1) {
1222
+ result = [temp.slice(1, 4), temp[4]];
1223
+ }
1224
+ } else if (temp = raw.match(/^rgb\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)$/i)) {
1225
+ temp[1] = parseInt(temp[1]);
1226
+ temp[2] = parseInt(temp[2]);
1227
+ temp[3] = parseInt(temp[3]);
1228
+ if (temp[1] < 256 && temp[2] < 256 && temp[3] < 256) {
1229
+ result = [temp.slice(1, 4), 1];
1230
+ }
1231
+ } else if (temp = raw.match(/^rgb\(\s*([0-9.]+)%\s*,\s*([0-9.]+)%\s*,\s*([0-9.]+)%\s*\)$/i)) {
1232
+ temp[1] = 2.55 * parseFloat(temp[1]);
1233
+ temp[2] = 2.55 * parseFloat(temp[2]);
1234
+ temp[3] = 2.55 * parseFloat(temp[3]);
1235
+ if (temp[1] < 256 && temp[2] < 256 && temp[3] < 256) {
1236
+ result = [temp.slice(1, 4), 1];
1237
+ }
1238
+ } else if (temp = raw.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i)) {
1239
+ result = [[parseInt(temp[1], 16), parseInt(temp[2], 16), parseInt(temp[3], 16)], 1];
1240
+ } else if (temp = raw.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i)) {
1241
+ result = [[0x11 * parseInt(temp[1], 16), 0x11 * parseInt(temp[2], 16), 0x11 * parseInt(temp[3], 16)], 1];
1242
+ }
1243
+ return colorCallback ? colorCallback(result, raw) : result;
1244
+ }
1245
+ function opacityToColor(color, opacity, isMask) {
1246
+ let newColor = color[0].slice(),
1247
+ newOpacity = color[1] * opacity;
1248
+ if (isMask) {
1249
+ for (let i = 0; i < color.length; i++) {
1250
+ newColor[i] *= newOpacity;
1251
+ }
1252
+ return [newColor, 1];
1253
+ } else {
1254
+ return [newColor, newOpacity];
1255
+ }
1256
+ }
1257
+ function multiplyMatrix() {
1258
+ function multiply(a, b) {
1259
+ return [a[0] * b[0] + a[2] * b[1], a[1] * b[0] + a[3] * b[1], a[0] * b[2] + a[2] * b[3], a[1] * b[2] + a[3] * b[3], a[0] * b[4] + a[2] * b[5] + a[4], a[1] * b[4] + a[3] * b[5] + a[5]];
1260
+ }
1261
+ let result = arguments[0];
1262
+ for (let i = 1; i < arguments.length; i++) {
1263
+ result = multiply(result, arguments[i]);
1264
+ }
1265
+ return result;
1266
+ }
1267
+ function transformPoint(p, m) {
1268
+ return [m[0] * p[0] + m[2] * p[1] + m[4], m[1] * p[0] + m[3] * p[1] + m[5]];
1269
+ }
1270
+ function getGlobalMatrix() {
1271
+ let ctm = doc._ctm;
1272
+ for (let i = groupStack.length - 1; i >= 0; i--) {
1273
+ ctm = multiplyMatrix(groupStack[i].savedMatrix, ctm);
1274
+ }
1275
+ return ctm;
1276
+ }
1277
+ function getPageBBox() {
1278
+ return new SvgShape().M(0, 0).L(doc.page.width, 0).L(doc.page.width, doc.page.height).L(0, doc.page.height).transform(inverseMatrix(getGlobalMatrix())).getBoundingBox();
1279
+ }
1280
+ function getPageScale() {
1281
+ const bbox = getPageBBox();
1282
+ const width = doc.page.width;
1283
+ return width / bbox[2];
1284
+ }
1285
+ function inverseMatrix(m) {
1286
+ let dt = m[0] * m[3] - m[1] * m[2];
1287
+ return [m[3] / dt, -m[1] / dt, -m[2] / dt, m[0] / dt, (m[2] * m[5] - m[3] * m[4]) / dt, (m[1] * m[4] - m[0] * m[5]) / dt];
1288
+ }
1289
+ function validateMatrix(m) {
1290
+ let m0 = validateNumber(m[0]),
1291
+ m1 = validateNumber(m[1]),
1292
+ m2 = validateNumber(m[2]),
1293
+ m3 = validateNumber(m[3]),
1294
+ m4 = validateNumber(m[4]),
1295
+ m5 = validateNumber(m[5]);
1296
+ if (isNotEqual(m0 * m3 - m1 * m2, 0)) {
1297
+ return [m0, m1, m2, m3, m4, m5];
1298
+ }
1299
+ }
1300
+ function solveEquation(curve) {
1301
+ let a = curve[2] || 0,
1302
+ b = curve[1] || 0,
1303
+ c = curve[0] || 0;
1304
+ if (isEqual(a, 0) && isEqual(b, 0)) {
1305
+ return [];
1306
+ } else if (isEqual(a, 0)) {
1307
+ return [-c / b];
1308
+ } else {
1309
+ let d = b * b - 4 * a * c;
1310
+ if (isNotEqual(d, 0) && d > 0) {
1311
+ return [(-b + Math.sqrt(d)) / (2 * a), (-b - Math.sqrt(d)) / (2 * a)];
1312
+ } else if (isEqual(d, 0)) {
1313
+ return [-b / (2 * a)];
1314
+ } else {
1315
+ return [];
1316
+ }
1317
+ }
1318
+ }
1319
+ function getCurveValue(t, curve) {
1320
+ return (curve[0] || 0) + (curve[1] || 0) * t + (curve[2] || 0) * t * t + (curve[3] || 0) * t * t * t;
1321
+ }
1322
+ function isEqual(number, ref) {
1323
+ return Math.abs(number - ref) < 1e-10;
1324
+ }
1325
+ function isNotEqual(number, ref) {
1326
+ return Math.abs(number - ref) >= 1e-10;
1327
+ }
1328
+ function validateNumber(n) {
1329
+ return n > -1e21 && n < 1e21 ? Math.round(n * 1e6) / 1e6 : 0;
1330
+ }
1331
+ function isArrayLike(v) {
1332
+ return typeof v === 'object' && v !== null && typeof v.length === 'number';
1333
+ }
1334
+ function parseTranform(v) {
1335
+ let parser = new StringParser((v || '').trim()),
1336
+ result = [1, 0, 0, 1, 0, 0],
1337
+ temp;
1338
+ while (temp = parser.match(/^([A-Za-z]+)\s*[(]([^(]+)[)]/, true)) {
1339
+ let func = temp[1],
1340
+ nums = [],
1341
+ parser2 = new StringParser(temp[2].trim()),
1342
+ temp2;
1343
+ while (temp2 = parser2.matchNumber()) {
1344
+ nums.push(Number(temp2));
1345
+ parser2.matchSeparator();
1346
+ }
1347
+ if (func === 'matrix' && nums.length === 6) {
1348
+ result = multiplyMatrix(result, [nums[0], nums[1], nums[2], nums[3], nums[4], nums[5]]);
1349
+ } else if (func === 'translate' && nums.length === 2) {
1350
+ result = multiplyMatrix(result, [1, 0, 0, 1, nums[0], nums[1]]);
1351
+ } else if (func === 'translate' && nums.length === 1) {
1352
+ result = multiplyMatrix(result, [1, 0, 0, 1, nums[0], 0]);
1353
+ } else if (func === 'scale' && nums.length === 2) {
1354
+ result = multiplyMatrix(result, [nums[0], 0, 0, nums[1], 0, 0]);
1355
+ } else if (func === 'scale' && nums.length === 1) {
1356
+ result = multiplyMatrix(result, [nums[0], 0, 0, nums[0], 0, 0]);
1357
+ } else if (func === 'rotate' && nums.length === 3) {
1358
+ let a = nums[0] * Math.PI / 180;
1359
+ result = multiplyMatrix(result, [1, 0, 0, 1, nums[1], nums[2]], [Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0], [1, 0, 0, 1, -nums[1], -nums[2]]);
1360
+ } else if (func === 'rotate' && nums.length === 1) {
1361
+ let a = nums[0] * Math.PI / 180;
1362
+ result = multiplyMatrix(result, [Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]);
1363
+ } else if (func === 'skewX' && nums.length === 1) {
1364
+ let a = nums[0] * Math.PI / 180;
1365
+ result = multiplyMatrix(result, [1, 0, Math.tan(a), 1, 0, 0]);
1366
+ } else if (func === 'skewY' && nums.length === 1) {
1367
+ let a = nums[0] * Math.PI / 180;
1368
+ result = multiplyMatrix(result, [1, Math.tan(a), 0, 1, 0, 0]);
1369
+ } else {
1370
+ return;
1371
+ }
1372
+ parser.matchSeparator();
1373
+ }
1374
+ if (parser.matchAll()) {
1375
+ return;
1376
+ }
1377
+ return result;
1378
+ }
1379
+ function parseAspectRatio(aspectRatio, availWidth, availHeight, elemWidth, elemHeight, initAlign) {
1380
+ let temp = (aspectRatio || '').trim().match(/^(none)$|^x(Min|Mid|Max)Y(Min|Mid|Max)(?:\s+(meet|slice))?$/) || [],
1381
+ ratioType = temp[1] || temp[4] || 'meet',
1382
+ xAlign = temp[2] || 'Mid',
1383
+ yAlign = temp[3] || 'Mid',
1384
+ scaleX = availWidth / elemWidth,
1385
+ scaleY = availHeight / elemHeight,
1386
+ dx = {
1387
+ 'Min': 0,
1388
+ 'Mid': 0.5,
1389
+ 'Max': 1
1390
+ }[xAlign] - (initAlign || 0),
1391
+ dy = {
1392
+ 'Min': 0,
1393
+ 'Mid': 0.5,
1394
+ 'Max': 1
1395
+ }[yAlign] - (initAlign || 0);
1396
+ if (ratioType === 'slice') {
1397
+ scaleY = scaleX = Math.max(scaleX, scaleY);
1398
+ } else if (ratioType === 'meet') {
1399
+ scaleY = scaleX = Math.min(scaleX, scaleY);
1400
+ }
1401
+ return [scaleX, 0, 0, scaleY, dx * (availWidth - elemWidth * scaleX), dy * (availHeight - elemHeight * scaleY)];
1402
+ }
1403
+ function parseStyleAttr(v) {
1404
+ let result = Object.create(null);
1405
+ v = (v || '').trim().split(/;/);
1406
+ for (let i = 0; i < v.length; i++) {
1407
+ let key = (v[i].split(':')[0] || '').trim(),
1408
+ value = (v[i].split(':')[1] || '').trim();
1409
+ if (key) {
1410
+ result[key] = value;
1411
+ }
1412
+ }
1413
+ if (result['marker']) {
1414
+ if (!result['marker-start']) {
1415
+ result['marker-start'] = result['marker'];
1416
+ }
1417
+ if (!result['marker-mid']) {
1418
+ result['marker-mid'] = result['marker'];
1419
+ }
1420
+ if (!result['marker-end']) {
1421
+ result['marker-end'] = result['marker'];
1422
+ }
1423
+ }
1424
+ if (result['font']) {
1425
+ let fontFamily = null,
1426
+ fontSize = null,
1427
+ fontStyle = "normal",
1428
+ fontWeight = "normal",
1429
+ fontVariant = "normal";
1430
+ let parts = result['font'].split(/\s+/);
1431
+ for (let i = 0; i < parts.length; i++) {
1432
+ switch (parts[i]) {
1433
+ case "normal":
1434
+ break;
1435
+ case "italic":
1436
+ case "oblique":
1437
+ fontStyle = parts[i];
1438
+ break;
1439
+ case "small-caps":
1440
+ fontVariant = parts[i];
1441
+ break;
1442
+ case "bold":
1443
+ case "bolder":
1444
+ case "lighter":
1445
+ case "100":
1446
+ case "200":
1447
+ case "300":
1448
+ case "400":
1449
+ case "500":
1450
+ case "600":
1451
+ case "700":
1452
+ case "800":
1453
+ case "900":
1454
+ fontWeight = parts[i];
1455
+ break;
1456
+ default:
1457
+ if (!fontSize) {
1458
+ fontSize = parts[i].split('/')[0];
1459
+ } else {
1460
+ if (!fontFamily) {
1461
+ fontFamily = parts[i];
1462
+ } else {
1463
+ fontFamily += ' ' + parts[i];
1464
+ }
1465
+ }
1466
+ break;
1467
+ }
1468
+ }
1469
+ if (!result['font-style']) {
1470
+ result['font-style'] = fontStyle;
1471
+ }
1472
+ if (!result['font-variant']) {
1473
+ result['font-variant'] = fontVariant;
1474
+ }
1475
+ if (!result['font-weight']) {
1476
+ result['font-weight'] = fontWeight;
1477
+ }
1478
+ if (!result['font-size']) {
1479
+ result['font-size'] = fontSize;
1480
+ }
1481
+ if (!result['font-family']) {
1482
+ result['font-family'] = fontFamily;
1483
+ }
1484
+ }
1485
+ return result;
1486
+ }
1487
+ function parseSelector(v) {
1488
+ let parts = v.split(/(?=[.#])/g),
1489
+ ids = [],
1490
+ classes = [],
1491
+ tags = [],
1492
+ temp;
1493
+ for (let i = 0; i < parts.length; i++) {
1494
+ if (temp = parts[i].match(/^[#]([_A-Za-z0-9-]+)$/)) {
1495
+ ids.push(temp[1]);
1496
+ } else if (temp = parts[i].match(/^[.]([_A-Za-z0-9-]+)$/)) {
1497
+ classes.push(temp[1]);
1498
+ } else if (temp = parts[i].match(/^([_A-Za-z0-9-]+)$/)) {
1499
+ tags.push(temp[1]);
1500
+ } else if (parts[i] !== '*') {
1501
+ return;
1502
+ }
1503
+ }
1504
+ return {
1505
+ tags: tags,
1506
+ ids: ids,
1507
+ classes: classes,
1508
+ specificity: ids.length * 10000 + classes.length * 100 + tags.length
1509
+ };
1510
+ }
1511
+ function parseStyleSheet(v) {
1512
+ let parser = new StringParser(v.trim()),
1513
+ rules = [],
1514
+ rule;
1515
+ while (rule = parser.match(/^\s*([^\{\}]*?)\s*\{([^\{\}]*?)\}/, true)) {
1516
+ let selectors = rule[1].split(/\s*,\s*/g),
1517
+ css = parseStyleAttr(rule[2]);
1518
+ for (let i = 0; i < selectors.length; i++) {
1519
+ let selector = parseSelector(selectors[i]);
1520
+ if (selector) {
1521
+ rules.push({
1522
+ selector: selector,
1523
+ css: css
1524
+ });
1525
+ }
1526
+ }
1527
+ }
1528
+ return rules;
1529
+ }
1530
+ function matchesSelector(elem, selector) {
1531
+ if (elem.nodeType !== 1) {
1532
+ return false;
1533
+ }
1534
+ for (let i = 0; i < selector.tags.length; i++) {
1535
+ if (selector.tags[i] !== elem.nodeName) {
1536
+ return false;
1537
+ }
1538
+ }
1539
+ for (let i = 0; i < selector.ids.length; i++) {
1540
+ if (selector.ids[i] !== elem.id) {
1541
+ return false;
1542
+ }
1543
+ }
1544
+ for (let i = 0; i < selector.classes.length; i++) {
1545
+ if (elem.classList.indexOf(selector.classes[i]) === -1) {
1546
+ return false;
1547
+ }
1548
+ }
1549
+ return true;
1550
+ }
1551
+ function getStyle(elem) {
1552
+ let result = Object.create(null);
1553
+ let specificities = Object.create(null);
1554
+ for (let i = 0; i < styleRules.length; i++) {
1555
+ let rule = styleRules[i];
1556
+ if (matchesSelector(elem, rule.selector)) {
1557
+ for (let key in rule.css) {
1558
+ if (!(specificities[key] > rule.selector.specificity)) {
1559
+ result[key] = rule.css[key];
1560
+ specificities[key] = rule.selector.specificity;
1561
+ }
1562
+ }
1563
+ }
1564
+ }
1565
+ return result;
1566
+ }
1567
+ function combineArrays(array1, array2) {
1568
+ return array1.concat(array2.slice(array1.length));
1569
+ }
1570
+ function getAscent(font, size) {
1571
+ return Math.max(font.ascender, (font.bbox[3] || font.bbox.maxY) * (font.scale || 1)) * size / 1000;
1572
+ }
1573
+ function getDescent(font, size) {
1574
+ return Math.min(font.descender, (font.bbox[1] || font.bbox.minY) * (font.scale || 1)) * size / 1000;
1575
+ }
1576
+ function getXHeight(font, size) {
1577
+ return (font.xHeight || 0.5 * (font.ascender - font.descender)) * size / 1000;
1578
+ }
1579
+ function getBaseline(font, size, baseline, shift) {
1580
+ let dy1, dy2;
1581
+ switch (baseline) {
1582
+ case 'middle':
1583
+ dy1 = 0.5 * getXHeight(font, size);
1584
+ break;
1585
+ case 'central':
1586
+ dy1 = 0.5 * (getDescent(font, size) + getAscent(font, size));
1587
+ break;
1588
+ case 'after-edge':
1589
+ case 'text-after-edge':
1590
+ dy1 = getDescent(font, size);
1591
+ break;
1592
+ case 'alphabetic':
1593
+ case 'auto':
1594
+ case 'baseline':
1595
+ dy1 = 0;
1596
+ break;
1597
+ case 'mathematical':
1598
+ dy1 = 0.5 * getAscent(font, size);
1599
+ break;
1600
+ case 'hanging':
1601
+ dy1 = 0.8 * getAscent(font, size);
1602
+ break;
1603
+ case 'before-edge':
1604
+ case 'text-before-edge':
1605
+ dy1 = getAscent(font, size);
1606
+ break;
1607
+ default:
1608
+ dy1 = 0;
1609
+ break;
1610
+ }
1611
+ switch (shift) {
1612
+ case 'baseline':
1613
+ dy2 = 0;
1614
+ break;
1615
+ case 'super':
1616
+ dy2 = 0.6 * size;
1617
+ break;
1618
+ case 'sub':
1619
+ dy2 = -0.6 * size;
1620
+ break;
1621
+ default:
1622
+ dy2 = shift;
1623
+ break;
1624
+ }
1625
+ return dy1 - dy2;
1626
+ }
1627
+ function getTextPos(font, size, text) {
1628
+ let encoded = font.encode('' + text),
1629
+ hex = encoded[0],
1630
+ pos = encoded[1],
1631
+ data = [];
1632
+ for (let i = 0; i < hex.length; i++) {
1633
+ let unicode = font.unicode ? font.unicode[parseInt(hex[i], 16)] : [text.charCodeAt(i)];
1634
+ data.push({
1635
+ glyph: hex[i],
1636
+ unicode: unicode,
1637
+ kern: pos[i].advanceWidth - pos[i].xAdvance,
1638
+ width: pos[i].advanceWidth * size / 1000,
1639
+ xOffset: pos[i].xOffset * size / 1000,
1640
+ yOffset: pos[i].yOffset * size / 1000,
1641
+ xAdvance: pos[i].xAdvance * size / 1000,
1642
+ yAdvance: pos[i].yAdvance * size / 1000
1643
+ });
1644
+ }
1645
+ return data;
1646
+ }
1647
+ function createSVGElement(obj, inherits) {
1648
+ switch (obj.nodeName) {
1649
+ case 'use':
1650
+ return new SvgElemUse(obj, inherits);
1651
+ case 'symbol':
1652
+ return new SvgElemSymbol(obj, inherits);
1653
+ case 'g':
1654
+ return new SvgElemGroup(obj, inherits);
1655
+ case 'a':
1656
+ return new SvgElemLink(obj, inherits);
1657
+ case 'svg':
1658
+ return new SvgElemSvg(obj, inherits);
1659
+ case 'image':
1660
+ return new SVGElemImage(obj, inherits);
1661
+ case 'rect':
1662
+ return new SvgElemRect(obj, inherits);
1663
+ case 'circle':
1664
+ return new SvgElemCircle(obj, inherits);
1665
+ case 'ellipse':
1666
+ return new SvgElemEllipse(obj, inherits);
1667
+ case 'line':
1668
+ return new SvgElemLine(obj, inherits);
1669
+ case 'polyline':
1670
+ return new SvgElemPolyline(obj, inherits);
1671
+ case 'polygon':
1672
+ return new SvgElemPolygon(obj, inherits);
1673
+ case 'path':
1674
+ return new SvgElemPath(obj, inherits);
1675
+ case 'text':
1676
+ return new SvgElemText(obj, inherits);
1677
+ case 'tspan':
1678
+ return new SvgElemTspan(obj, inherits);
1679
+ case 'textPath':
1680
+ return new SvgElemTextPath(obj, inherits);
1681
+ case '#text':
1682
+ case '#cdata-section':
1683
+ return new SvgElemTextNode(obj, inherits);
1684
+ default:
1685
+ return new SvgElem(obj, inherits);
1686
+ }
1687
+ }
1688
+ var StringParser = function (str) {
1689
+ this.match = function (exp, all) {
1690
+ let temp = str.match(exp);
1691
+ if (!temp || temp.index !== 0) {
1692
+ return;
1693
+ }
1694
+ str = str.substring(temp[0].length);
1695
+ return all ? temp : temp[0];
1696
+ };
1697
+ this.matchSeparator = function () {
1698
+ return this.match(/^(?:\s*,\s*|\s*|)/);
1699
+ };
1700
+ this.matchSpace = function () {
1701
+ return this.match(/^(?:\s*)/);
1702
+ };
1703
+ this.matchLengthUnit = function () {
1704
+ return this.match(/^(?:px|pt|cm|mm|in|pc|em|ex|%|)/);
1705
+ };
1706
+ this.matchNumber = function () {
1707
+ return this.match(/^(?:[-+]?(?:[0-9]+[.][0-9]+|[0-9]+[.]|[.][0-9]+|[0-9]+)(?:[eE][-+]?[0-9]+)?)/);
1708
+ };
1709
+ this.matchAll = function () {
1710
+ return this.match(/^[\s\S]+/);
1711
+ };
1712
+ };
1713
+ var BezierSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
1714
+ let divisions = 6 * precision;
1715
+ let equationX = [p1x, -3 * p1x + 3 * c1x, 3 * p1x - 6 * c1x + 3 * c2x, -p1x + 3 * c1x - 3 * c2x + p2x];
1716
+ let equationY = [p1y, -3 * p1y + 3 * c1y, 3 * p1y - 6 * c1y + 3 * c2y, -p1y + 3 * c1y - 3 * c2y + p2y];
1717
+ let derivativeX = [-3 * p1x + 3 * c1x, 6 * p1x - 12 * c1x + 6 * c2x, -3 * p1x + 9 * c1x - 9 * c2x + 3 * p2x];
1718
+ let derivativeY = [-3 * p1y + 3 * c1y, 6 * p1y - 12 * c1y + 6 * c2y, -3 * p1y + 9 * c1y - 9 * c2y + 3 * p2y];
1719
+ let lengthMap = [0];
1720
+ for (let i = 1; i <= divisions; i++) {
1721
+ let t = (i - 0.5) / divisions;
1722
+ let dx = getCurveValue(t, derivativeX) / divisions,
1723
+ dy = getCurveValue(t, derivativeY) / divisions,
1724
+ l = Math.sqrt(dx * dx + dy * dy);
1725
+ lengthMap[i] = lengthMap[i - 1] + l;
1726
+ }
1727
+ this.totalLength = lengthMap[divisions];
1728
+ this.startPoint = [p1x, p1y, isEqual(p1x, c1x) && isEqual(p1y, c1y) ? Math.atan2(c2y - c1y, c2x - c1x) : Math.atan2(c1y - p1y, c1x - p1x)];
1729
+ this.endPoint = [p2x, p2y, isEqual(c2x, p2x) && isEqual(c2y, p2y) ? Math.atan2(c2y - c1y, c2x - c1x) : Math.atan2(p2y - c2y, p2x - c2x)];
1730
+ this.getBoundingBox = function () {
1731
+ let temp;
1732
+ let minX = getCurveValue(0, equationX),
1733
+ minY = getCurveValue(0, equationY),
1734
+ maxX = getCurveValue(1, equationX),
1735
+ maxY = getCurveValue(1, equationY);
1736
+ if (minX > maxX) {
1737
+ temp = maxX;
1738
+ maxX = minX;
1739
+ minX = temp;
1740
+ }
1741
+ if (minY > maxY) {
1742
+ temp = maxY;
1743
+ maxY = minY;
1744
+ minY = temp;
1745
+ }
1746
+ let rootsX = solveEquation(derivativeX);
1747
+ for (let i = 0; i < rootsX.length; i++) {
1748
+ if (rootsX[i] >= 0 && rootsX[i] <= 1) {
1749
+ let x = getCurveValue(rootsX[i], equationX);
1750
+ if (x < minX) {
1751
+ minX = x;
1752
+ }
1753
+ if (x > maxX) {
1754
+ maxX = x;
1755
+ }
1756
+ }
1757
+ }
1758
+ let rootsY = solveEquation(derivativeY);
1759
+ for (let i = 0; i < rootsY.length; i++) {
1760
+ if (rootsY[i] >= 0 && rootsY[i] <= 1) {
1761
+ let y = getCurveValue(rootsY[i], equationY);
1762
+ if (y < minY) {
1763
+ minY = y;
1764
+ }
1765
+ if (y > maxY) {
1766
+ maxY = y;
1767
+ }
1768
+ }
1769
+ }
1770
+ return [minX, minY, maxX, maxY];
1771
+ };
1772
+ this.getPointAtLength = function (l) {
1773
+ if (isEqual(l, 0)) {
1774
+ return this.startPoint;
1775
+ }
1776
+ if (isEqual(l, this.totalLength)) {
1777
+ return this.endPoint;
1778
+ }
1779
+ if (l < 0 || l > this.totalLength) {
1780
+ return;
1781
+ }
1782
+ for (let i = 1; i <= divisions; i++) {
1783
+ let l1 = lengthMap[i - 1],
1784
+ l2 = lengthMap[i];
1785
+ if (l1 <= l && l <= l2) {
1786
+ let t = (i - (l2 - l) / (l2 - l1)) / divisions,
1787
+ x = getCurveValue(t, equationX),
1788
+ y = getCurveValue(t, equationY),
1789
+ dx = getCurveValue(t, derivativeX),
1790
+ dy = getCurveValue(t, derivativeY);
1791
+ return [x, y, Math.atan2(dy, dx)];
1792
+ }
1793
+ }
1794
+ };
1795
+ };
1796
+ var LineSegment = function (p1x, p1y, p2x, p2y) {
1797
+ this.totalLength = Math.sqrt((p2x - p1x) * (p2x - p1x) + (p2y - p1y) * (p2y - p1y));
1798
+ this.startPoint = [p1x, p1y, Math.atan2(p2y - p1y, p2x - p1x)];
1799
+ this.endPoint = [p2x, p2y, Math.atan2(p2y - p1y, p2x - p1x)];
1800
+ this.getBoundingBox = function () {
1801
+ return [Math.min(this.startPoint[0], this.endPoint[0]), Math.min(this.startPoint[1], this.endPoint[1]), Math.max(this.startPoint[0], this.endPoint[0]), Math.max(this.startPoint[1], this.endPoint[1])];
1802
+ };
1803
+ this.getPointAtLength = function (l) {
1804
+ if (l >= 0 && l <= this.totalLength) {
1805
+ let r = l / this.totalLength || 0,
1806
+ x = this.startPoint[0] + r * (this.endPoint[0] - this.startPoint[0]),
1807
+ y = this.startPoint[1] + r * (this.endPoint[1] - this.startPoint[1]);
1808
+ return [x, y, this.startPoint[2]];
1809
+ }
1810
+ };
1811
+ };
1812
+ var SvgShape = function () {
1813
+ this.pathCommands = [];
1814
+ this.pathSegments = [];
1815
+ this.startPoint = null;
1816
+ this.endPoint = null;
1817
+ this.totalLength = 0;
1818
+ let startX = 0,
1819
+ startY = 0,
1820
+ currX = 0,
1821
+ currY = 0,
1822
+ lastCom,
1823
+ lastCtrlX,
1824
+ lastCtrlY;
1825
+ this.move = function (x, y) {
1826
+ startX = currX = x;
1827
+ startY = currY = y;
1828
+ return null;
1829
+ };
1830
+ this.line = function (x, y) {
1831
+ let segment = new LineSegment(currX, currY, x, y);
1832
+ currX = x;
1833
+ currY = y;
1834
+ return segment;
1835
+ };
1836
+ this.curve = function (c1x, c1y, c2x, c2y, x, y) {
1837
+ let segment = new BezierSegment(currX, currY, c1x, c1y, c2x, c2y, x, y);
1838
+ currX = x;
1839
+ currY = y;
1840
+ return segment;
1841
+ };
1842
+ this.close = function () {
1843
+ let segment = new LineSegment(currX, currY, startX, startY);
1844
+ currX = startX;
1845
+ currY = startY;
1846
+ return segment;
1847
+ };
1848
+ this.addCommand = function (data) {
1849
+ this.pathCommands.push(data);
1850
+ let segment = this[data[0]].apply(this, data.slice(3));
1851
+ if (segment) {
1852
+ segment.hasStart = data[1];
1853
+ segment.hasEnd = data[2];
1854
+ this.startPoint = this.startPoint || segment.startPoint;
1855
+ this.endPoint = segment.endPoint;
1856
+ this.pathSegments.push(segment);
1857
+ this.totalLength += segment.totalLength;
1858
+ }
1859
+ };
1860
+ this.M = function (x, y) {
1861
+ this.addCommand(['move', true, true, x, y]);
1862
+ lastCom = 'M';
1863
+ return this;
1864
+ };
1865
+ this.m = function (x, y) {
1866
+ return this.M(currX + x, currY + y);
1867
+ };
1868
+ this.Z = this.z = function () {
1869
+ this.addCommand(['close', true, true]);
1870
+ lastCom = 'Z';
1871
+ return this;
1872
+ };
1873
+ this.L = function (x, y) {
1874
+ this.addCommand(['line', true, true, x, y]);
1875
+ lastCom = 'L';
1876
+ return this;
1877
+ };
1878
+ this.l = function (x, y) {
1879
+ return this.L(currX + x, currY + y);
1880
+ };
1881
+ this.H = function (x) {
1882
+ return this.L(x, currY);
1883
+ };
1884
+ this.h = function (x) {
1885
+ return this.L(currX + x, currY);
1886
+ };
1887
+ this.V = function (y) {
1888
+ return this.L(currX, y);
1889
+ };
1890
+ this.v = function (y) {
1891
+ return this.L(currX, currY + y);
1892
+ };
1893
+ this.C = function (c1x, c1y, c2x, c2y, x, y) {
1894
+ this.addCommand(['curve', true, true, c1x, c1y, c2x, c2y, x, y]);
1895
+ lastCom = 'C';
1896
+ lastCtrlX = c2x;
1897
+ lastCtrlY = c2y;
1898
+ return this;
1899
+ };
1900
+ this.c = function (c1x, c1y, c2x, c2y, x, y) {
1901
+ return this.C(currX + c1x, currY + c1y, currX + c2x, currY + c2y, currX + x, currY + y);
1902
+ };
1903
+ this.S = function (c1x, c1y, x, y) {
1904
+ return this.C(currX + (lastCom === 'C' ? currX - lastCtrlX : 0), currY + (lastCom === 'C' ? currY - lastCtrlY : 0), c1x, c1y, x, y);
1905
+ };
1906
+ this.s = function (c1x, c1y, x, y) {
1907
+ return this.C(currX + (lastCom === 'C' ? currX - lastCtrlX : 0), currY + (lastCom === 'C' ? currY - lastCtrlY : 0), currX + c1x, currY + c1y, currX + x, currY + y);
1908
+ };
1909
+ this.Q = function (cx, cy, x, y) {
1910
+ let c1x = currX + 2 / 3 * (cx - currX),
1911
+ c1y = currY + 2 / 3 * (cy - currY),
1912
+ c2x = x + 2 / 3 * (cx - x),
1913
+ c2y = y + 2 / 3 * (cy - y);
1914
+ this.addCommand(['curve', true, true, c1x, c1y, c2x, c2y, x, y]);
1915
+ lastCom = 'Q';
1916
+ lastCtrlX = cx;
1917
+ lastCtrlY = cy;
1918
+ return this;
1919
+ };
1920
+ this.q = function (c1x, c1y, x, y) {
1921
+ return this.Q(currX + c1x, currY + c1y, currX + x, currY + y);
1922
+ };
1923
+ this.T = function (x, y) {
1924
+ return this.Q(currX + (lastCom === 'Q' ? currX - lastCtrlX : 0), currY + (lastCom === 'Q' ? currY - lastCtrlY : 0), x, y);
1925
+ };
1926
+ this.t = function (x, y) {
1927
+ return this.Q(currX + (lastCom === 'Q' ? currX - lastCtrlX : 0), currY + (lastCom === 'Q' ? currY - lastCtrlY : 0), currX + x, currY + y);
1928
+ };
1929
+ this.A = function (rx, ry, fi, fa, fs, x, y) {
1930
+ if (isEqual(rx, 0) || isEqual(ry, 0)) {
1931
+ this.addCommand(['line', true, true, x, y]);
1932
+ } else {
1933
+ fi = fi * (Math.PI / 180);
1934
+ rx = Math.abs(rx);
1935
+ ry = Math.abs(ry);
1936
+ fa = 1 * !!fa;
1937
+ fs = 1 * !!fs;
1938
+ let x1 = Math.cos(fi) * (currX - x) / 2 + Math.sin(fi) * (currY - y) / 2,
1939
+ y1 = Math.cos(fi) * (currY - y) / 2 - Math.sin(fi) * (currX - x) / 2,
1940
+ lambda = x1 * x1 / (rx * rx) + y1 * y1 / (ry * ry);
1941
+ if (lambda > 1) {
1942
+ rx *= Math.sqrt(lambda);
1943
+ ry *= Math.sqrt(lambda);
1944
+ }
1945
+ let r = Math.sqrt(Math.max(0, rx * rx * ry * ry - rx * rx * y1 * y1 - ry * ry * x1 * x1) / (rx * rx * y1 * y1 + ry * ry * x1 * x1)),
1946
+ x2 = (fa === fs ? -1 : 1) * r * rx * y1 / ry,
1947
+ y2 = (fa === fs ? 1 : -1) * r * ry * x1 / rx;
1948
+ let cx = Math.cos(fi) * x2 - Math.sin(fi) * y2 + (currX + x) / 2,
1949
+ cy = Math.sin(fi) * x2 + Math.cos(fi) * y2 + (currY + y) / 2,
1950
+ th1 = Math.atan2((y1 - y2) / ry, (x1 - x2) / rx),
1951
+ th2 = Math.atan2((-y1 - y2) / ry, (-x1 - x2) / rx);
1952
+ if (fs === 0 && th2 - th1 > 0) {
1953
+ th2 -= 2 * Math.PI;
1954
+ } else if (fs === 1 && th2 - th1 < 0) {
1955
+ th2 += 2 * Math.PI;
1956
+ }
1957
+ let segms = Math.ceil(Math.abs(th2 - th1) / (Math.PI / precision));
1958
+ for (let i = 0; i < segms; i++) {
1959
+ let th3 = th1 + i * (th2 - th1) / segms,
1960
+ th4 = th1 + (i + 1) * (th2 - th1) / segms,
1961
+ t = 4 / 3 * Math.tan((th4 - th3) / 4);
1962
+ let c1x = cx + Math.cos(fi) * rx * (Math.cos(th3) - t * Math.sin(th3)) - Math.sin(fi) * ry * (Math.sin(th3) + t * Math.cos(th3)),
1963
+ c1y = cy + Math.sin(fi) * rx * (Math.cos(th3) - t * Math.sin(th3)) + Math.cos(fi) * ry * (Math.sin(th3) + t * Math.cos(th3)),
1964
+ c2x = cx + Math.cos(fi) * rx * (Math.cos(th4) + t * Math.sin(th4)) - Math.sin(fi) * ry * (Math.sin(th4) - t * Math.cos(th4)),
1965
+ c2y = cy + Math.sin(fi) * rx * (Math.cos(th4) + t * Math.sin(th4)) + Math.cos(fi) * ry * (Math.sin(th4) - t * Math.cos(th4)),
1966
+ endX = cx + Math.cos(fi) * rx * Math.cos(th4) - Math.sin(fi) * ry * Math.sin(th4),
1967
+ endY = cy + Math.sin(fi) * rx * Math.cos(th4) + Math.cos(fi) * ry * Math.sin(th4);
1968
+ this.addCommand(['curve', i === 0, i === segms - 1, c1x, c1y, c2x, c2y, endX, endY]);
1969
+ }
1970
+ }
1971
+ lastCom = 'A';
1972
+ return this;
1973
+ };
1974
+ this.a = function (rx, ry, fi, fa, fs, x, y) {
1975
+ return this.A(rx, ry, fi, fa, fs, currX + x, currY + y);
1976
+ };
1977
+ this.path = function (d) {
1978
+ let command,
1979
+ value,
1980
+ temp,
1981
+ parser = new StringParser((d || '').trim());
1982
+ while (command = parser.match(/^[astvzqmhlcASTVZQMHLC]/)) {
1983
+ parser.matchSeparator();
1984
+ let values = [];
1985
+ while (value = PathFlags[command + values.length] ? parser.match(/^[01]/) : parser.matchNumber()) {
1986
+ parser.matchSeparator();
1987
+ if (values.length === PathArguments[command]) {
1988
+ this[command].apply(this, values);
1989
+ values = [];
1990
+ if (command === 'M') {
1991
+ command = 'L';
1992
+ } else if (command === 'm') {
1993
+ command = 'l';
1994
+ }
1995
+ }
1996
+ values.push(Number(value));
1997
+ }
1998
+ if (values.length === PathArguments[command]) {
1999
+ this[command].apply(this, values);
2000
+ } else {
2001
+ warningCallback('SvgPath: command ' + command + ' with ' + values.length + ' numbers');
2002
+ return;
2003
+ }
2004
+ }
2005
+ if (temp = parser.matchAll()) {
2006
+ warningCallback('SvgPath: unexpected string ' + temp);
2007
+ }
2008
+ return this;
2009
+ };
2010
+ this.getBoundingBox = function () {
2011
+ let bbox = [Infinity, Infinity, -Infinity, -Infinity];
2012
+ function addBounds(bbox1) {
2013
+ if (bbox1[0] < bbox[0]) {
2014
+ bbox[0] = bbox1[0];
2015
+ }
2016
+ if (bbox1[2] > bbox[2]) {
2017
+ bbox[2] = bbox1[2];
2018
+ }
2019
+ if (bbox1[1] < bbox[1]) {
2020
+ bbox[1] = bbox1[1];
2021
+ }
2022
+ if (bbox1[3] > bbox[3]) {
2023
+ bbox[3] = bbox1[3];
2024
+ }
2025
+ }
2026
+ for (let i = 0; i < this.pathSegments.length; i++) {
2027
+ addBounds(this.pathSegments[i].getBoundingBox());
2028
+ }
2029
+ if (bbox[0] === Infinity) {
2030
+ bbox[0] = 0;
2031
+ }
2032
+ if (bbox[1] === Infinity) {
2033
+ bbox[1] = 0;
2034
+ }
2035
+ if (bbox[2] === -Infinity) {
2036
+ bbox[2] = 0;
2037
+ }
2038
+ if (bbox[3] === -Infinity) {
2039
+ bbox[3] = 0;
2040
+ }
2041
+ return bbox;
2042
+ };
2043
+ this.getPointAtLength = function (l) {
2044
+ if (l >= 0 && l <= this.totalLength) {
2045
+ let temp;
2046
+ for (let i = 0; i < this.pathSegments.length; i++) {
2047
+ if (temp = this.pathSegments[i].getPointAtLength(l)) {
2048
+ return temp;
2049
+ }
2050
+ l -= this.pathSegments[i].totalLength;
2051
+ }
2052
+ return this.endPoint;
2053
+ }
2054
+ };
2055
+ this.transform = function (m) {
2056
+ this.pathSegments = [];
2057
+ this.startPoint = null;
2058
+ this.endPoint = null;
2059
+ this.totalLength = 0;
2060
+ for (let i = 0; i < this.pathCommands.length; i++) {
2061
+ let data = this.pathCommands.shift();
2062
+ for (let j = 3; j < data.length; j += 2) {
2063
+ let p = transformPoint([data[j], data[j + 1]], m);
2064
+ data[j] = p[0];
2065
+ data[j + 1] = p[1];
2066
+ }
2067
+ this.addCommand(data);
2068
+ }
2069
+ return this;
2070
+ };
2071
+ this.mergeShape = function (shape) {
2072
+ for (let i = 0; i < shape.pathCommands.length; i++) {
2073
+ this.addCommand(shape.pathCommands[i].slice());
2074
+ }
2075
+ return this;
2076
+ };
2077
+ this.clone = function () {
2078
+ return new SvgShape().mergeShape(this);
2079
+ };
2080
+ this.insertInDocument = function () {
2081
+ for (let i = 0; i < this.pathCommands.length; i++) {
2082
+ let command = this.pathCommands[i][0],
2083
+ values = this.pathCommands[i].slice(3);
2084
+ switch (command) {
2085
+ case 'move':
2086
+ doc.moveTo(values[0], values[1]);
2087
+ break;
2088
+ case 'line':
2089
+ doc.lineTo(values[0], values[1]);
2090
+ break;
2091
+ case 'curve':
2092
+ doc.bezierCurveTo(values[0], values[1], values[2], values[3], values[4], values[5]);
2093
+ break;
2094
+ case 'close':
2095
+ doc.closePath();
2096
+ break;
2097
+ }
2098
+ }
2099
+ };
2100
+ this.getSubPaths = function () {
2101
+ let subPaths = [],
2102
+ shape = new SvgShape();
2103
+ for (let i = 0; i < this.pathCommands.length; i++) {
2104
+ let data = this.pathCommands[i],
2105
+ command = this.pathCommands[i][0];
2106
+ if (command === 'move' && i !== 0) {
2107
+ subPaths.push(shape);
2108
+ shape = new SvgShape();
2109
+ }
2110
+ shape.addCommand(data);
2111
+ }
2112
+ subPaths.push(shape);
2113
+ return subPaths;
2114
+ };
2115
+ this.getMarkers = function () {
2116
+ let markers = [],
2117
+ subPaths = this.getSubPaths();
2118
+ for (let i = 0; i < subPaths.length; i++) {
2119
+ let subPath = subPaths[i],
2120
+ subPathMarkers = [];
2121
+ for (let j = 0; j < subPath.pathSegments.length; j++) {
2122
+ let segment = subPath.pathSegments[j];
2123
+ if (isNotEqual(segment.totalLength, 0) || j === 0 || j === subPath.pathSegments.length - 1) {
2124
+ if (segment.hasStart) {
2125
+ let startMarker = segment.getPointAtLength(0),
2126
+ prevEndMarker = subPathMarkers.pop();
2127
+ if (prevEndMarker) {
2128
+ startMarker[2] = 0.5 * (prevEndMarker[2] + startMarker[2]);
2129
+ }
2130
+ subPathMarkers.push(startMarker);
2131
+ }
2132
+ if (segment.hasEnd) {
2133
+ let endMarker = segment.getPointAtLength(segment.totalLength);
2134
+ subPathMarkers.push(endMarker);
2135
+ }
2136
+ }
2137
+ }
2138
+ markers = markers.concat(subPathMarkers);
2139
+ }
2140
+ return markers;
2141
+ };
2142
+ };
2143
+ var SvgElem = function (obj, inherits) {
2144
+ let styleCache = Object.create(null);
2145
+ let childrenCache = null;
2146
+ this.name = obj.nodeName;
2147
+ this.isOuterElement = obj === svg || !obj.parentNode;
2148
+ this.inherits = inherits || (!this.isOuterElement ? createSVGElement(obj.parentNode, null) : null);
2149
+ this.stack = this.inherits ? this.inherits.stack.concat(obj) : [obj];
2150
+ this.style = parseStyleAttr(typeof obj.getAttribute === 'function' && obj.getAttribute('style'));
2151
+ this.css = useCSS ? getComputedStyle(obj) : getStyle(obj);
2152
+ this.allowedChildren = [];
2153
+ this.attr = function (key) {
2154
+ if (typeof obj.getAttribute === 'function') {
2155
+ return obj.getAttribute(key);
2156
+ }
2157
+ };
2158
+ this.resolveUrl = function (value) {
2159
+ let temp = (value || '').match(/^\s*(?:url\("(.*)#(.*)"\)|url\('(.*)#(.*)'\)|url\((.*)#(.*)\)|(.*)#(.*))\s*$/) || [];
2160
+ let file = temp[1] || temp[3] || temp[5] || temp[7],
2161
+ id = temp[2] || temp[4] || temp[6] || temp[8];
2162
+ if (id) {
2163
+ if (!file) {
2164
+ let svgObj = svg.getElementById(id);
2165
+ if (svgObj) {
2166
+ if (this.stack.indexOf(svgObj) === -1) {
2167
+ return svgObj;
2168
+ } else {
2169
+ warningCallback('SVGtoPDF: loop of circular references for id "' + id + '"');
2170
+ return;
2171
+ }
2172
+ }
2173
+ }
2174
+ if (documentCallback) {
2175
+ let svgs = documentCache[file];
2176
+ if (!svgs) {
2177
+ svgs = documentCallback(file);
2178
+ if (!isArrayLike(svgs)) {
2179
+ svgs = [svgs];
2180
+ }
2181
+ for (let i = 0; i < svgs.length; i++) {
2182
+ if (typeof svgs[i] === 'string') {
2183
+ svgs[i] = parseXml(svgs[i]);
2184
+ }
2185
+ }
2186
+ documentCache[file] = svgs;
2187
+ }
2188
+ for (let i = 0; i < svgs.length; i++) {
2189
+ let svgObj = svgs[i].getElementById(id);
2190
+ if (svgObj) {
2191
+ if (this.stack.indexOf(svgObj) === -1) {
2192
+ return svgObj;
2193
+ } else {
2194
+ warningCallback('SVGtoPDF: loop of circular references for id "' + file + '#' + id + '"');
2195
+ return;
2196
+ }
2197
+ }
2198
+ }
2199
+ }
2200
+ }
2201
+ };
2202
+ this.computeUnits = function (value, unit, percent, isFontSize) {
2203
+ if (unit === '%') {
2204
+ return parseFloat(value) / 100 * (isFontSize || percent != null ? percent : this.getViewport());
2205
+ } else if (unit === 'ex' || unit === 'em') {
2206
+ return value * {
2207
+ 'em': 1,
2208
+ 'ex': 0.5
2209
+ }[unit] * (isFontSize ? percent : this.get('font-size'));
2210
+ } else {
2211
+ return value * {
2212
+ '': 1,
2213
+ 'px': 1,
2214
+ 'pt': 96 / 72,
2215
+ 'cm': 96 / 2.54,
2216
+ 'mm': 96 / 25.4,
2217
+ 'in': 96,
2218
+ 'pc': 96 / 6
2219
+ }[unit];
2220
+ }
2221
+ };
2222
+ this.computeLength = function (value, percent, initial, isFontSize) {
2223
+ let parser = new StringParser((value || '').trim()),
2224
+ temp1,
2225
+ temp2;
2226
+ if (typeof (temp1 = parser.matchNumber()) === 'string' && typeof (temp2 = parser.matchLengthUnit()) === 'string' && !parser.matchAll()) {
2227
+ return this.computeUnits(temp1, temp2, percent, isFontSize);
2228
+ }
2229
+ return initial;
2230
+ };
2231
+ this.computeLengthList = function (value, percent, strict) {
2232
+ let parser = new StringParser((value || '').trim()),
2233
+ result = [],
2234
+ temp1,
2235
+ temp2;
2236
+ while (typeof (temp1 = parser.matchNumber()) === 'string' && typeof (temp2 = parser.matchLengthUnit()) === 'string') {
2237
+ result.push(this.computeUnits(temp1, temp2, percent));
2238
+ parser.matchSeparator();
2239
+ }
2240
+ if (strict && parser.matchAll()) {
2241
+ return;
2242
+ }
2243
+ return result;
2244
+ };
2245
+ this.getLength = function (key, percent, initial) {
2246
+ return this.computeLength(this.attr(key), percent, initial);
2247
+ };
2248
+ this.getLengthList = function (key, percent) {
2249
+ return this.computeLengthList(this.attr(key), percent);
2250
+ };
2251
+ this.getUrl = function (key) {
2252
+ return this.resolveUrl(this.attr(key));
2253
+ };
2254
+ this.getNumberList = function (key) {
2255
+ let parser = new StringParser((this.attr(key) || '').trim()),
2256
+ result = [],
2257
+ temp;
2258
+ while (temp = parser.matchNumber()) {
2259
+ result.push(Number(temp));
2260
+ parser.matchSeparator();
2261
+ }
2262
+ result.error = parser.matchAll();
2263
+ return result;
2264
+ };
2265
+ this.getViewbox = function (key, initial) {
2266
+ let viewBox = this.getNumberList(key);
2267
+ if (viewBox.length === 4 && viewBox[2] >= 0 && viewBox[3] >= 0) {
2268
+ return viewBox;
2269
+ }
2270
+ return initial;
2271
+ };
2272
+ this.getPercent = function (key, initial) {
2273
+ let value = this.attr(key);
2274
+ let parser = new StringParser((value || '').trim()),
2275
+ temp1,
2276
+ temp2;
2277
+ let number = parser.matchNumber();
2278
+ if (!number) {
2279
+ return initial;
2280
+ }
2281
+ if (parser.match('%')) {
2282
+ number *= 0.01;
2283
+ }
2284
+ if (parser.matchAll()) {
2285
+ return initial;
2286
+ }
2287
+ return Math.max(0, Math.min(1, number));
2288
+ };
2289
+ this.chooseValue = function (args) {
2290
+ for (let i = 0; i < arguments.length; i++) {
2291
+ if (arguments[i] != null && arguments[i] === arguments[i]) {
2292
+ return arguments[i];
2293
+ }
2294
+ }
2295
+ return arguments[arguments.length - 1];
2296
+ };
2297
+ this.get = function (key) {
2298
+ if (styleCache[key] !== undefined) {
2299
+ return styleCache[key];
2300
+ }
2301
+ let keyInfo = Properties[key] || {},
2302
+ value,
2303
+ result;
2304
+ for (let i = 0; i < 3; i++) {
2305
+ switch (i) {
2306
+ case 0:
2307
+ if (key !== 'transform') {
2308
+ // the CSS transform behaves strangely
2309
+ value = this.css[keyInfo.css || key];
2310
+ }
2311
+ break;
2312
+ case 1:
2313
+ value = this.style[key];
2314
+ break;
2315
+ case 2:
2316
+ value = this.attr(key);
2317
+ break;
2318
+ }
2319
+ if (value === 'inherit') {
2320
+ result = this.inherits ? this.inherits.get(key) : keyInfo.initial;
2321
+ if (result != null) {
2322
+ return styleCache[key] = result;
2323
+ }
2324
+ }
2325
+ if (keyInfo.values != null) {
2326
+ result = keyInfo.values[value];
2327
+ if (result != null) {
2328
+ return styleCache[key] = result;
2329
+ }
2330
+ }
2331
+ if (value != null) {
2332
+ let parsed;
2333
+ switch (key) {
2334
+ case 'font-size':
2335
+ result = this.computeLength(value, this.inherits ? this.inherits.get(key) : keyInfo.initial, undefined, true);
2336
+ break;
2337
+ case 'baseline-shift':
2338
+ result = this.computeLength(value, this.get('font-size'));
2339
+ break;
2340
+ case 'font-family':
2341
+ result = value || undefined;
2342
+ break;
2343
+ case 'opacity':
2344
+ case 'stroke-opacity':
2345
+ case 'fill-opacity':
2346
+ case 'stop-opacity':
2347
+ parsed = parseFloat(value);
2348
+ if (!isNaN(parsed)) {
2349
+ result = Math.max(0, Math.min(1, parsed));
2350
+ }
2351
+ break;
2352
+ case 'transform':
2353
+ result = parseTranform(value);
2354
+ break;
2355
+ case 'stroke-dasharray':
2356
+ if (value === 'none') {
2357
+ result = [];
2358
+ } else if (parsed = this.computeLengthList(value, this.getViewport(), true)) {
2359
+ let sum = 0,
2360
+ error = false;
2361
+ for (let j = 0; j < parsed.length; j++) {
2362
+ if (parsed[j] < 0) {
2363
+ error = true;
2364
+ }
2365
+ sum += parsed[j];
2366
+ }
2367
+ if (!error) {
2368
+ if (parsed.length % 2 === 1) {
2369
+ parsed = parsed.concat(parsed);
2370
+ }
2371
+ result = sum === 0 ? [] : parsed;
2372
+ }
2373
+ }
2374
+ break;
2375
+ case 'color':
2376
+ if (value === 'none' || value === 'transparent') {
2377
+ result = 'none';
2378
+ } else {
2379
+ result = parseColor(value);
2380
+ }
2381
+ break;
2382
+ case 'fill':
2383
+ case 'stroke':
2384
+ if (value === 'none' || value === 'transparent') {
2385
+ result = 'none';
2386
+ } else if (value === 'currentColor') {
2387
+ result = this.get('color');
2388
+ } else if (parsed = parseColor(value)) {
2389
+ return parsed;
2390
+ } else if (parsed = (value || '').split(' ')) {
2391
+ let object = this.resolveUrl(parsed[0]),
2392
+ fallbackColor = parseColor(parsed[1]);
2393
+ if (object == null) {
2394
+ result = fallbackColor;
2395
+ } else if (object.nodeName === 'linearGradient' || object.nodeName === 'radialGradient') {
2396
+ result = new SvgElemGradient(object, null, fallbackColor);
2397
+ } else if (object.nodeName === 'pattern') {
2398
+ result = new SvgElemPattern(object, null, fallbackColor);
2399
+ } else {
2400
+ result = fallbackColor;
2401
+ }
2402
+ }
2403
+ break;
2404
+ case 'stop-color':
2405
+ if (value === 'none' || value === 'transparent') {
2406
+ result = 'none';
2407
+ } else if (value === 'currentColor') {
2408
+ result = this.get('color');
2409
+ } else {
2410
+ result = parseColor(value);
2411
+ }
2412
+ break;
2413
+ case 'marker-start':
2414
+ case 'marker-mid':
2415
+ case 'marker-end':
2416
+ case 'clip-path':
2417
+ case 'mask':
2418
+ if (value === 'none') {
2419
+ result = 'none';
2420
+ } else {
2421
+ result = this.resolveUrl(value);
2422
+ }
2423
+ break;
2424
+ case 'stroke-width':
2425
+ parsed = this.computeLength(value, this.getViewport());
2426
+ if (parsed != null && parsed >= 0) {
2427
+ result = parsed;
2428
+ }
2429
+ break;
2430
+ case 'stroke-miterlimit':
2431
+ parsed = parseFloat(value);
2432
+ if (parsed != null && parsed >= 1) {
2433
+ result = parsed;
2434
+ }
2435
+ break;
2436
+ case 'word-spacing':
2437
+ case 'letter-spacing':
2438
+ result = this.computeLength(value, this.getViewport());
2439
+ break;
2440
+ case 'stroke-dashoffset':
2441
+ result = this.computeLength(value, this.getViewport());
2442
+ break;
2443
+ }
2444
+ if (result != null) {
2445
+ return styleCache[key] = result;
2446
+ }
2447
+ }
2448
+ }
2449
+ return styleCache[key] = keyInfo.inherit && this.inherits ? this.inherits.get(key) : keyInfo.initial;
2450
+ };
2451
+ this.getChildren = function () {
2452
+ if (childrenCache != null) {
2453
+ return childrenCache;
2454
+ }
2455
+ let children = [];
2456
+ for (let i = 0; i < obj.childNodes.length; i++) {
2457
+ let child = obj.childNodes[i];
2458
+ if (!child.error && this.allowedChildren.indexOf(child.nodeName) !== -1) {
2459
+ children.push(createSVGElement(child, this));
2460
+ }
2461
+ }
2462
+ return childrenCache = children;
2463
+ };
2464
+ this.getParentVWidth = function () {
2465
+ return this.inherits ? this.inherits.getVWidth() : viewportWidth;
2466
+ };
2467
+ this.getParentVHeight = function () {
2468
+ return this.inherits ? this.inherits.getVHeight() : viewportHeight;
2469
+ };
2470
+ this.getParentViewport = function () {
2471
+ return Math.sqrt(0.5 * this.getParentVWidth() * this.getParentVWidth() + 0.5 * this.getParentVHeight() * this.getParentVHeight());
2472
+ };
2473
+ this.getVWidth = function () {
2474
+ return this.getParentVWidth();
2475
+ };
2476
+ this.getVHeight = function () {
2477
+ return this.getParentVHeight();
2478
+ };
2479
+ this.getViewport = function () {
2480
+ return Math.sqrt(0.5 * this.getVWidth() * this.getVWidth() + 0.5 * this.getVHeight() * this.getVHeight());
2481
+ };
2482
+ this.getBoundingBox = function () {
2483
+ let shape = this.getBoundingShape();
2484
+ return shape.getBoundingBox();
2485
+ };
2486
+ };
2487
+ var SvgElemStylable = function (obj, inherits) {
2488
+ SvgElem.call(this, obj, inherits);
2489
+ this.transform = function () {
2490
+ doc.transform.apply(doc, this.getTransformation());
2491
+ };
2492
+ this.clip = function () {
2493
+ if (this.get('clip-path') !== 'none') {
2494
+ let clipPath = new SvgElemClipPath(this.get('clip-path'), null);
2495
+ clipPath.useMask(clipPath.attr('clipPathUnits') === 'objectBoundingBox' ? this.getBoundingBox() : null);
2496
+ return true;
2497
+ }
2498
+ };
2499
+ this.mask = function () {
2500
+ if (this.get('mask') !== 'none') {
2501
+ let mask = new SvgElemMask(this.get('mask'), null);
2502
+ mask.useMask(this.getBoundingBox());
2503
+ return true;
2504
+ }
2505
+ };
2506
+ this.getFill = function (isClip, isMask) {
2507
+ let opacity = this.get('opacity'),
2508
+ fill = this.get('fill'),
2509
+ fillOpacity = this.get('fill-opacity');
2510
+ if (isClip) {
2511
+ return DefaultColors.white;
2512
+ }
2513
+ if (fill !== 'none' && opacity && fillOpacity) {
2514
+ if (fill instanceof SvgElemGradient || fill instanceof SvgElemPattern) {
2515
+ return fill.getPaint(this.getBoundingBox(), fillOpacity * opacity, isClip, isMask);
2516
+ }
2517
+ return opacityToColor(fill, fillOpacity * opacity, isMask);
2518
+ }
2519
+ };
2520
+ this.getStroke = function (isClip, isMask) {
2521
+ let opacity = this.get('opacity'),
2522
+ stroke = this.get('stroke'),
2523
+ strokeOpacity = this.get('stroke-opacity');
2524
+ if (isClip || isEqual(this.get('stroke-width'), 0)) {
2525
+ return;
2526
+ }
2527
+ if (stroke !== 'none' && opacity && strokeOpacity) {
2528
+ if (stroke instanceof SvgElemGradient || stroke instanceof SvgElemPattern) {
2529
+ return stroke.getPaint(this.getBoundingBox(), strokeOpacity * opacity, isClip, isMask);
2530
+ }
2531
+ return opacityToColor(stroke, strokeOpacity * opacity, isMask);
2532
+ }
2533
+ };
2534
+ };
2535
+ var SvgElemHasChildren = function (obj, inherits) {
2536
+ SvgElemStylable.call(this, obj, inherits);
2537
+ this.allowedChildren = ['use', 'g', 'a', 'svg', 'image', 'rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'path', 'text'];
2538
+ this.getBoundingShape = function () {
2539
+ let shape = new SvgShape(),
2540
+ children = this.getChildren();
2541
+ for (let i = 0; i < children.length; i++) {
2542
+ if (children[i].get('display') !== 'none') {
2543
+ if (typeof children[i].getBoundingShape === 'function') {
2544
+ let childShape = children[i].getBoundingShape().clone();
2545
+ if (typeof children[i].getTransformation === 'function') {
2546
+ childShape.transform(children[i].getTransformation());
2547
+ }
2548
+ shape.mergeShape(childShape);
2549
+ }
2550
+ }
2551
+ }
2552
+ return shape;
2553
+ };
2554
+ this.drawChildren = function (isClip, isMask) {
2555
+ let children = this.getChildren();
2556
+ for (let i = 0; i < children.length; i++) {
2557
+ if (children[i].get('display') !== 'none') {
2558
+ if (typeof children[i].drawInDocument === 'function') {
2559
+ children[i].drawInDocument(isClip, isMask);
2560
+ }
2561
+ }
2562
+ }
2563
+ };
2564
+ };
2565
+ var SvgElemContainer = function (obj, inherits) {
2566
+ SvgElemHasChildren.call(this, obj, inherits);
2567
+ this.drawContent = function (isClip, isMask) {
2568
+ this.transform();
2569
+ let clipped = this.clip(),
2570
+ masked = this.mask(),
2571
+ group;
2572
+ if ((this.get('opacity') < 1 || clipped || masked) && !isClip) {
2573
+ group = docBeginGroup(getPageBBox());
2574
+ }
2575
+ this.drawChildren(isClip, isMask);
2576
+ if (group) {
2577
+ docEndGroup(group);
2578
+ doc.fillOpacity(this.get('opacity'));
2579
+ docInsertGroup(group);
2580
+ }
2581
+ };
2582
+ };
2583
+ var SvgElemUse = function (obj, inherits) {
2584
+ SvgElemContainer.call(this, obj, inherits);
2585
+ let x = this.getLength('x', this.getVWidth(), 0),
2586
+ y = this.getLength('y', this.getVHeight(), 0),
2587
+ child = this.getUrl('href') || this.getUrl('xlink:href');
2588
+ if (child) {
2589
+ child = createSVGElement(child, this);
2590
+ }
2591
+ this.getChildren = function () {
2592
+ return child ? [child] : [];
2593
+ };
2594
+ this.drawInDocument = function (isClip, isMask) {
2595
+ doc.save();
2596
+ this.drawContent(isClip, isMask);
2597
+ doc.restore();
2598
+ };
2599
+ this.getTransformation = function () {
2600
+ return multiplyMatrix(this.get('transform'), [1, 0, 0, 1, x, y]);
2601
+ };
2602
+ };
2603
+ var SvgElemSymbol = function (obj, inherits) {
2604
+ SvgElemContainer.call(this, obj, inherits);
2605
+ let width = this.getLength('width', this.getParentVWidth(), this.getParentVWidth()),
2606
+ height = this.getLength('height', this.getParentVHeight(), this.getParentVHeight());
2607
+ if (inherits instanceof SvgElemUse) {
2608
+ width = inherits.getLength('width', inherits.getParentVWidth(), width);
2609
+ height = inherits.getLength('height', inherits.getParentVHeight(), height);
2610
+ }
2611
+ let aspectRatio = (this.attr('preserveAspectRatio') || '').trim(),
2612
+ viewBox = this.getViewbox('viewBox', [0, 0, width, height]);
2613
+ this.getVWidth = function () {
2614
+ return viewBox[2];
2615
+ };
2616
+ this.getVHeight = function () {
2617
+ return viewBox[3];
2618
+ };
2619
+ this.drawInDocument = function (isClip, isMask) {
2620
+ doc.save();
2621
+ this.drawContent(isClip, isMask);
2622
+ doc.restore();
2623
+ };
2624
+ this.getTransformation = function () {
2625
+ return multiplyMatrix(parseAspectRatio(aspectRatio, width, height, viewBox[2], viewBox[3]), [1, 0, 0, 1, -viewBox[0], -viewBox[1]]);
2626
+ };
2627
+ };
2628
+ var SvgElemGroup = function (obj, inherits) {
2629
+ SvgElemContainer.call(this, obj, inherits);
2630
+ this.drawInDocument = function (isClip, isMask) {
2631
+ doc.save();
2632
+ if (this.link && !isClip && !isMask) {
2633
+ this.addLink();
2634
+ }
2635
+ this.drawContent(isClip, isMask);
2636
+ doc.restore();
2637
+ };
2638
+ this.getTransformation = function () {
2639
+ return this.get('transform');
2640
+ };
2641
+ };
2642
+ var SvgElemLink = function (obj, inherits) {
2643
+ if (inherits && inherits.isText) {
2644
+ SvgElemTspan.call(this, obj, inherits);
2645
+ this.allowedChildren = ['textPath', 'tspan', '#text', '#cdata-section', 'a'];
2646
+ } else {
2647
+ SvgElemGroup.call(this, obj, inherits);
2648
+ }
2649
+ this.link = this.attr('href') || this.attr('xlink:href');
2650
+ this.addLink = function () {
2651
+ if (this.link.match(/^(?:[a-z][a-z0-9+.-]*:|\/\/)?/i) && this.getChildren().length) {
2652
+ let bbox = this.getBoundingShape().transform(getGlobalMatrix()).getBoundingBox();
2653
+ docInsertLink(bbox[0], bbox[1], bbox[2], bbox[3], this.link);
2654
+ }
2655
+ };
2656
+ };
2657
+ var SvgElemSvg = function (obj, inherits) {
2658
+ SvgElemContainer.call(this, obj, inherits);
2659
+ let width = this.getLength('width', this.getParentVWidth(), this.getParentVWidth()),
2660
+ height = this.getLength('height', this.getParentVHeight(), this.getParentVHeight()),
2661
+ x = this.getLength('x', this.getParentVWidth(), 0),
2662
+ y = this.getLength('y', this.getParentVHeight(), 0);
2663
+ if (inherits instanceof SvgElemUse) {
2664
+ width = inherits.getLength('width', inherits.getParentVWidth(), width);
2665
+ height = inherits.getLength('height', inherits.getParentVHeight(), height);
2666
+ }
2667
+ let aspectRatio = this.attr('preserveAspectRatio'),
2668
+ viewBox = this.getViewbox('viewBox', [0, 0, width, height]);
2669
+ if (this.isOuterElement && preserveAspectRatio) {
2670
+ x = y = 0;
2671
+ width = viewportWidth;
2672
+ height = viewportHeight;
2673
+ aspectRatio = preserveAspectRatio;
2674
+ }
2675
+ this.getVWidth = function () {
2676
+ return viewBox[2];
2677
+ };
2678
+ this.getVHeight = function () {
2679
+ return viewBox[3];
2680
+ };
2681
+ this.drawInDocument = function (isClip, isMask) {
2682
+ doc.save();
2683
+ if (this.get('overflow') === 'hidden') {
2684
+ new SvgShape().M(x, y).L(x + width, y).L(x + width, y + height).L(x, y + height).Z().transform(this.get('transform')).insertInDocument();
2685
+ doc.clip();
2686
+ }
2687
+ this.drawContent(isClip, isMask);
2688
+ doc.restore();
2689
+ };
2690
+ this.getTransformation = function () {
2691
+ return multiplyMatrix(this.get('transform'), [1, 0, 0, 1, x, y], parseAspectRatio(aspectRatio, width, height, viewBox[2], viewBox[3]), [1, 0, 0, 1, -viewBox[0], -viewBox[1]]);
2692
+ };
2693
+ };
2694
+ var SVGElemImage = function (obj, inherits) {
2695
+ SvgElemStylable.call(this, obj, inherits);
2696
+ let link = imageCallback(this.attr('href') || this.attr('xlink:href') || ''),
2697
+ x = this.getLength('x', this.getVWidth(), 0),
2698
+ y = this.getLength('y', this.getVHeight(), 0),
2699
+ width = this.getLength('width', this.getVWidth(), 'auto'),
2700
+ height = this.getLength('height', this.getVHeight(), 'auto'),
2701
+ image;
2702
+ try {
2703
+ image = doc.openImage(link);
2704
+ } catch (e) {
2705
+ warningCallback('SVGElemImage: failed to open image "' + link + '" in PDFKit');
2706
+ }
2707
+ if (image) {
2708
+ if (width === 'auto' && height !== 'auto') {
2709
+ width = height * image.width / image.height;
2710
+ } else if (height === 'auto' && width !== 'auto') {
2711
+ height = width * image.height / image.width;
2712
+ } else if (width === 'auto' && height === 'auto') {
2713
+ width = image.width;
2714
+ height = image.height;
2715
+ }
2716
+ }
2717
+ if (width === 'auto' || width < 0) {
2718
+ width = 0;
2719
+ }
2720
+ if (height === 'auto' || height < 0) {
2721
+ height = 0;
2722
+ }
2723
+ this.getTransformation = function () {
2724
+ return this.get('transform');
2725
+ };
2726
+ this.getBoundingShape = function () {
2727
+ return new SvgShape().M(x, y).L(x + width, y).M(x + width, y + height).L(x, y + height);
2728
+ };
2729
+ this.drawInDocument = function (isClip, isMask) {
2730
+ if (this.get('visibility') === 'hidden' || !image) {
2731
+ return;
2732
+ }
2733
+ doc.save();
2734
+ this.transform();
2735
+ if (this.get('overflow') === 'hidden') {
2736
+ doc.rect(x, y, width, height).clip();
2737
+ }
2738
+ this.clip();
2739
+ this.mask();
2740
+ doc.translate(x, y);
2741
+ doc.transform.apply(doc, parseAspectRatio(this.attr('preserveAspectRatio'), width, height, image ? image.width : width, image ? image.height : height));
2742
+ if (!isClip) {
2743
+ doc.fillOpacity(this.get('opacity'));
2744
+ doc.image(image, 0, 0);
2745
+ } else {
2746
+ doc.rect(0, 0, image.width, image.height);
2747
+ docFillColor(DefaultColors.white).fill();
2748
+ }
2749
+ doc.restore();
2750
+ };
2751
+ };
2752
+ var SvgElemPattern = function (obj, inherits, fallback) {
2753
+ SvgElemHasChildren.call(this, obj, inherits);
2754
+ this.ref = function () {
2755
+ let ref = this.getUrl('href') || this.getUrl('xlink:href');
2756
+ if (ref && ref.nodeName === obj.nodeName) {
2757
+ return new SvgElemPattern(ref, inherits, fallback);
2758
+ }
2759
+ }.call(this);
2760
+ let _attr = this.attr;
2761
+ this.attr = function (key) {
2762
+ let attr = _attr.call(this, key);
2763
+ if (attr != null || key === 'href' || key === 'xlink:href') {
2764
+ return attr;
2765
+ }
2766
+ return this.ref ? this.ref.attr(key) : null;
2767
+ };
2768
+ let _getChildren = this.getChildren;
2769
+ this.getChildren = function () {
2770
+ let children = _getChildren.call(this);
2771
+ if (children.length > 0) {
2772
+ return children;
2773
+ }
2774
+ return this.ref ? this.ref.getChildren() : [];
2775
+ };
2776
+ this.getPaint = function (bBox, gOpacity, isClip, isMask) {
2777
+ let bBoxUnitsPattern = this.attr('patternUnits') !== 'userSpaceOnUse',
2778
+ bBoxUnitsContent = this.attr('patternContentUnits') === 'objectBoundingBox',
2779
+ x = this.getLength('x', bBoxUnitsPattern ? 1 : this.getParentVWidth(), 0),
2780
+ y = this.getLength('y', bBoxUnitsPattern ? 1 : this.getParentVHeight(), 0),
2781
+ width = this.getLength('width', bBoxUnitsPattern ? 1 : this.getParentVWidth(), 0),
2782
+ height = this.getLength('height', bBoxUnitsPattern ? 1 : this.getParentVHeight(), 0);
2783
+ if (bBoxUnitsContent && !bBoxUnitsPattern) {
2784
+ // Use the same units for pattern & pattern content
2785
+ x = (x - bBox[0]) / (bBox[2] - bBox[0]) || 0;
2786
+ y = (y - bBox[1]) / (bBox[3] - bBox[1]) || 0;
2787
+ width = width / (bBox[2] - bBox[0]) || 0;
2788
+ height = height / (bBox[3] - bBox[1]) || 0;
2789
+ } else if (!bBoxUnitsContent && bBoxUnitsPattern) {
2790
+ x = bBox[0] + x * (bBox[2] - bBox[0]);
2791
+ y = bBox[1] + y * (bBox[3] - bBox[1]);
2792
+ width = width * (bBox[2] - bBox[0]);
2793
+ height = height * (bBox[3] - bBox[1]);
2794
+ }
2795
+ let viewBox = this.getViewbox('viewBox', [0, 0, width, height]),
2796
+ aspectRatio = (this.attr('preserveAspectRatio') || '').trim(),
2797
+ aspectRatioMatrix = multiplyMatrix(parseAspectRatio(aspectRatio, width, height, viewBox[2], viewBox[3], 0), [1, 0, 0, 1, -viewBox[0], -viewBox[1]]),
2798
+ matrix = parseTranform(this.attr('patternTransform'));
2799
+ if (bBoxUnitsContent) {
2800
+ matrix = multiplyMatrix([bBox[2] - bBox[0], 0, 0, bBox[3] - bBox[1], bBox[0], bBox[1]], matrix);
2801
+ }
2802
+ matrix = multiplyMatrix(matrix, [1, 0, 0, 1, x, y]);
2803
+ if ((matrix = validateMatrix(matrix)) && (aspectRatioMatrix = validateMatrix(aspectRatioMatrix)) && (width = validateNumber(width)) && (height = validateNumber(height))) {
2804
+ let group = docBeginGroup([0, 0, width, height]);
2805
+ doc.transform.apply(doc, aspectRatioMatrix);
2806
+ this.drawChildren(isClip, isMask);
2807
+ docEndGroup(group);
2808
+ return [docCreatePattern(group, width, height, matrix), gOpacity];
2809
+ } else {
2810
+ return fallback ? [fallback[0], fallback[1] * gOpacity] : undefined;
2811
+ }
2812
+ };
2813
+ this.getVWidth = function () {
2814
+ let bBoxUnitsPattern = this.attr('patternUnits') !== 'userSpaceOnUse',
2815
+ width = this.getLength('width', bBoxUnitsPattern ? 1 : this.getParentVWidth(), 0);
2816
+ return this.getViewbox('viewBox', [0, 0, width, 0])[2];
2817
+ };
2818
+ this.getVHeight = function () {
2819
+ let bBoxUnitsPattern = this.attr('patternUnits') !== 'userSpaceOnUse',
2820
+ height = this.getLength('height', bBoxUnitsPattern ? 1 : this.getParentVHeight(), 0);
2821
+ return this.getViewbox('viewBox', [0, 0, 0, height])[3];
2822
+ };
2823
+ };
2824
+ var SvgElemGradient = function (obj, inherits, fallback) {
2825
+ SvgElem.call(this, obj, inherits);
2826
+ this.allowedChildren = ['stop'];
2827
+ this.ref = function () {
2828
+ let ref = this.getUrl('href') || this.getUrl('xlink:href');
2829
+ if (ref && ref.nodeName === obj.nodeName) {
2830
+ return new SvgElemGradient(ref, inherits, fallback);
2831
+ }
2832
+ }.call(this);
2833
+ let _attr = this.attr;
2834
+ this.attr = function (key) {
2835
+ let attr = _attr.call(this, key);
2836
+ if (attr != null || key === 'href' || key === 'xlink:href') {
2837
+ return attr;
2838
+ }
2839
+ return this.ref ? this.ref.attr(key) : null;
2840
+ };
2841
+ let _getChildren = this.getChildren;
2842
+ this.getChildren = function () {
2843
+ let children = _getChildren.call(this);
2844
+ if (children.length > 0) {
2845
+ return children;
2846
+ }
2847
+ return this.ref ? this.ref.getChildren() : [];
2848
+ };
2849
+ this.getPaint = function (bBox, gOpacity, isClip, isMask) {
2850
+ let children = this.getChildren();
2851
+ if (children.length === 0) {
2852
+ return;
2853
+ }
2854
+ if (children.length === 1) {
2855
+ let child = children[0],
2856
+ stopColor = child.get('stop-color');
2857
+ if (stopColor === 'none') {
2858
+ return;
2859
+ }
2860
+ return opacityToColor(stopColor, child.get('stop-opacity') * gOpacity, isMask);
2861
+ }
2862
+ let bBoxUnits = this.attr('gradientUnits') !== 'userSpaceOnUse',
2863
+ matrix = parseTranform(this.attr('gradientTransform')),
2864
+ spread = this.attr('spreadMethod'),
2865
+ grad,
2866
+ x1,
2867
+ x2,
2868
+ y1,
2869
+ y2,
2870
+ r2,
2871
+ nAfter = 0,
2872
+ nBefore = 0,
2873
+ nTotal = 1;
2874
+ if (bBoxUnits) {
2875
+ matrix = multiplyMatrix([bBox[2] - bBox[0], 0, 0, bBox[3] - bBox[1], bBox[0], bBox[1]], matrix);
2876
+ }
2877
+ if (matrix = validateMatrix(matrix)) {
2878
+ if (this.name === 'linearGradient') {
2879
+ x1 = this.getLength('x1', bBoxUnits ? 1 : this.getVWidth(), 0);
2880
+ x2 = this.getLength('x2', bBoxUnits ? 1 : this.getVWidth(), bBoxUnits ? 1 : this.getVWidth());
2881
+ y1 = this.getLength('y1', bBoxUnits ? 1 : this.getVHeight(), 0);
2882
+ y2 = this.getLength('y2', bBoxUnits ? 1 : this.getVHeight(), 0);
2883
+ } else {
2884
+ x2 = this.getLength('cx', bBoxUnits ? 1 : this.getVWidth(), bBoxUnits ? 0.5 : 0.5 * this.getVWidth());
2885
+ y2 = this.getLength('cy', bBoxUnits ? 1 : this.getVHeight(), bBoxUnits ? 0.5 : 0.5 * this.getVHeight());
2886
+ r2 = this.getLength('r', bBoxUnits ? 1 : this.getViewport(), bBoxUnits ? 0.5 : 0.5 * this.getViewport());
2887
+ x1 = this.getLength('fx', bBoxUnits ? 1 : this.getVWidth(), x2);
2888
+ y1 = this.getLength('fy', bBoxUnits ? 1 : this.getVHeight(), y2);
2889
+ if (r2 < 0) {
2890
+ warningCallback('SvgElemGradient: negative r value');
2891
+ }
2892
+ let d = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)),
2893
+ multiplier = 1;
2894
+ if (d > r2) {
2895
+ // according to specification
2896
+ multiplier = r2 / d;
2897
+ x1 = x2 + (x1 - x2) * multiplier;
2898
+ y1 = y2 + (y1 - y2) * multiplier;
2899
+ }
2900
+ r2 = Math.max(r2, d * multiplier * (1 + 1e-6)); // fix for edge-case gradients see issue #84
2901
+ }
2902
+ if (spread === 'reflect' || spread === 'repeat') {
2903
+ let inv = inverseMatrix(matrix),
2904
+ corner1 = transformPoint([bBox[0], bBox[1]], inv),
2905
+ corner2 = transformPoint([bBox[2], bBox[1]], inv),
2906
+ corner3 = transformPoint([bBox[2], bBox[3]], inv),
2907
+ corner4 = transformPoint([bBox[0], bBox[3]], inv);
2908
+ if (this.name === 'linearGradient') {
2909
+ // See file 'gradient-repeat-maths.png'
2910
+ nAfter = Math.max((corner1[0] - x2) * (x2 - x1) + (corner1[1] - y2) * (y2 - y1), (corner2[0] - x2) * (x2 - x1) + (corner2[1] - y2) * (y2 - y1), (corner3[0] - x2) * (x2 - x1) + (corner3[1] - y2) * (y2 - y1), (corner4[0] - x2) * (x2 - x1) + (corner4[1] - y2) * (y2 - y1)) / (Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
2911
+ nBefore = Math.max((corner1[0] - x1) * (x1 - x2) + (corner1[1] - y1) * (y1 - y2), (corner2[0] - x1) * (x1 - x2) + (corner2[1] - y1) * (y1 - y2), (corner3[0] - x1) * (x1 - x2) + (corner3[1] - y1) * (y1 - y2), (corner4[0] - x1) * (x1 - x2) + (corner4[1] - y1) * (y1 - y2)) / (Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
2912
+ } else {
2913
+ nAfter = Math.sqrt(Math.max(Math.pow(corner1[0] - x2, 2) + Math.pow(corner1[1] - y2, 2), Math.pow(corner2[0] - x2, 2) + Math.pow(corner2[1] - y2, 2), Math.pow(corner3[0] - x2, 2) + Math.pow(corner3[1] - y2, 2), Math.pow(corner4[0] - x2, 2) + Math.pow(corner4[1] - y2, 2))) / r2 - 1;
2914
+ }
2915
+ nAfter = Math.ceil(nAfter + 0.5); // Add a little more because the stroke can extend outside of the bounding box
2916
+ nBefore = Math.ceil(nBefore + 0.5);
2917
+ nTotal = nBefore + 1 + nAfter; // How many times the gradient needs to be repeated to fill the object bounding box
2918
+ }
2919
+ if (this.name === 'linearGradient') {
2920
+ grad = doc.linearGradient(x1 - nBefore * (x2 - x1), y1 - nBefore * (y2 - y1), x2 + nAfter * (x2 - x1), y2 + nAfter * (y2 - y1));
2921
+ } else {
2922
+ grad = doc.radialGradient(x1, y1, 0, x2, y2, r2 + nAfter * r2);
2923
+ }
2924
+ for (let n = 0; n < nTotal; n++) {
2925
+ let offset = 0,
2926
+ inOrder = spread !== 'reflect' || (n - nBefore) % 2 === 0;
2927
+ for (let i = 0; i < children.length; i++) {
2928
+ let child = children[inOrder ? i : children.length - 1 - i],
2929
+ stopColor = child.get('stop-color');
2930
+ if (stopColor === 'none') {
2931
+ stopColor = DefaultColors.transparent;
2932
+ }
2933
+ stopColor = opacityToColor(stopColor, child.get('stop-opacity') * gOpacity, isMask);
2934
+ offset = Math.max(offset, inOrder ? child.getPercent('offset', 0) : 1 - child.getPercent('offset', 0));
2935
+ if (i === 0 && stopColor[0].length === 4) {
2936
+ grad._colorSpace = 'DeviceCMYK';
2937
+ } // Fix until PR #763 is merged into PDFKit
2938
+ if (i === 0 && offset > 0) {
2939
+ grad.stop((n + 0) / nTotal, stopColor[0], stopColor[1]);
2940
+ }
2941
+ grad.stop((n + offset) / (nAfter + nBefore + 1), stopColor[0], stopColor[1]);
2942
+ if (i === children.length - 1 && offset < 1) {
2943
+ grad.stop((n + 1) / nTotal, stopColor[0], stopColor[1]);
2944
+ }
2945
+ }
2946
+ }
2947
+ grad.setTransform.apply(grad, matrix);
2948
+ return [grad, 1];
2949
+ } else {
2950
+ return fallback ? [fallback[0], fallback[1] * gOpacity] : undefined;
2951
+ }
2952
+ };
2953
+ };
2954
+ var SvgElemBasicShape = function (obj, inherits) {
2955
+ SvgElemStylable.call(this, obj, inherits);
2956
+ this.dashScale = 1;
2957
+ this.getBoundingShape = function () {
2958
+ return this.shape;
2959
+ };
2960
+ this.getTransformation = function () {
2961
+ return this.get('transform');
2962
+ };
2963
+ this.drawInDocument = function (isClip, isMask) {
2964
+ if (this.get('visibility') === 'hidden' || !this.shape) {
2965
+ return;
2966
+ }
2967
+ doc.save();
2968
+ if (this.get('vector-effect') === 'non-scaling-stroke') {
2969
+ this.shape.transform(this.getTransformation());
2970
+ } else {
2971
+ this.transform();
2972
+ }
2973
+ this.clip();
2974
+ if (!isClip) {
2975
+ let masked = this.mask(),
2976
+ group;
2977
+ if (masked) {
2978
+ group = docBeginGroup(getPageBBox());
2979
+ }
2980
+ let subPaths = this.shape.getSubPaths(),
2981
+ fill = this.getFill(isClip, isMask),
2982
+ stroke = this.getStroke(isClip, isMask),
2983
+ lineWidth = this.get('stroke-width'),
2984
+ lineCap = this.get('stroke-linecap');
2985
+ if (this.get('vector-effect') === 'non-scaling-stroke') {
2986
+ lineWidth = lineWidth / getPageScale();
2987
+ }
2988
+ if (fill || stroke) {
2989
+ if (fill) {
2990
+ docFillColor(fill);
2991
+ }
2992
+ if (stroke) {
2993
+ for (let j = 0; j < subPaths.length; j++) {
2994
+ if (isEqual(subPaths[j].totalLength, 0)) {
2995
+ if ((lineCap === 'square' || lineCap === 'round') && lineWidth > 0) {
2996
+ if (subPaths[j].startPoint && subPaths[j].startPoint.length > 1) {
2997
+ let x = subPaths[j].startPoint[0],
2998
+ y = subPaths[j].startPoint[1];
2999
+ docFillColor(stroke);
3000
+ if (lineCap === 'square') {
3001
+ doc.rect(x - 0.5 * lineWidth, y - 0.5 * lineWidth, lineWidth, lineWidth);
3002
+ } else if (lineCap === 'round') {
3003
+ doc.circle(x, y, 0.5 * lineWidth);
3004
+ }
3005
+ doc.fill();
3006
+ }
3007
+ }
3008
+ }
3009
+ }
3010
+ let dashArray = this.get('stroke-dasharray'),
3011
+ dashOffset = this.get('stroke-dashoffset');
3012
+ if (isNotEqual(this.dashScale, 1)) {
3013
+ for (let j = 0; j < dashArray.length; j++) {
3014
+ dashArray[j] *= this.dashScale;
3015
+ }
3016
+ dashOffset *= this.dashScale;
3017
+ }
3018
+ docStrokeColor(stroke);
3019
+ doc.lineWidth(lineWidth).miterLimit(this.get('stroke-miterlimit')).lineJoin(this.get('stroke-linejoin')).lineCap(lineCap);
3020
+ docApplyDash(dashArray, dashOffset);
3021
+ }
3022
+ for (let j = 0; j < subPaths.length; j++) {
3023
+ if (subPaths[j].totalLength > 0) {
3024
+ subPaths[j].insertInDocument();
3025
+ }
3026
+ }
3027
+ if (fill && stroke) {
3028
+ doc.fillAndStroke(this.get('fill-rule'));
3029
+ } else if (fill) {
3030
+ doc.fill(this.get('fill-rule'));
3031
+ } else if (stroke) {
3032
+ doc.stroke();
3033
+ }
3034
+ }
3035
+ let markerStart = this.get('marker-start'),
3036
+ markerMid = this.get('marker-mid'),
3037
+ markerEnd = this.get('marker-end');
3038
+ if (markerStart !== 'none' || markerMid !== 'none' || markerEnd !== 'none') {
3039
+ let markersPos = this.shape.getMarkers();
3040
+ if (markerStart !== 'none' && markersPos.length > 0) {
3041
+ let marker = new SvgElemMarker(markerStart, null);
3042
+ marker.drawMarker(false, isMask, markersPos[0], lineWidth);
3043
+ }
3044
+ if (markerMid !== 'none') {
3045
+ for (let i = 1; i < markersPos.length - 1; i++) {
3046
+ let marker = new SvgElemMarker(markerMid, null);
3047
+ marker.drawMarker(false, isMask, markersPos[i], lineWidth);
3048
+ }
3049
+ }
3050
+ if (markerEnd !== 'none' && markersPos.length > 0) {
3051
+ let marker = new SvgElemMarker(markerEnd, null);
3052
+ marker.drawMarker(false, isMask, markersPos[markersPos.length - 1], lineWidth);
3053
+ }
3054
+ }
3055
+ if (group) {
3056
+ docEndGroup(group);
3057
+ docInsertGroup(group);
3058
+ }
3059
+ } else {
3060
+ this.shape.insertInDocument();
3061
+ docFillColor(DefaultColors.white);
3062
+ doc.fill(this.get('clip-rule'));
3063
+ }
3064
+ doc.restore();
3065
+ };
3066
+ };
3067
+ var SvgElemRect = function (obj, inherits) {
3068
+ SvgElemBasicShape.call(this, obj, inherits);
3069
+ let x = this.getLength('x', this.getVWidth(), 0),
3070
+ y = this.getLength('y', this.getVHeight(), 0),
3071
+ w = this.getLength('width', this.getVWidth(), 0),
3072
+ h = this.getLength('height', this.getVHeight(), 0),
3073
+ rx = this.getLength('rx', this.getVWidth()),
3074
+ ry = this.getLength('ry', this.getVHeight());
3075
+ if (rx === undefined && ry === undefined) {
3076
+ rx = ry = 0;
3077
+ } else if (rx === undefined && ry !== undefined) {
3078
+ rx = ry;
3079
+ } else if (rx !== undefined && ry === undefined) {
3080
+ ry = rx;
3081
+ }
3082
+ if (w > 0 && h > 0) {
3083
+ if (rx && ry) {
3084
+ rx = Math.min(rx, 0.5 * w);
3085
+ ry = Math.min(ry, 0.5 * h);
3086
+ this.shape = new SvgShape().M(x + rx, y).L(x + w - rx, y).A(rx, ry, 0, 0, 1, x + w, y + ry).L(x + w, y + h - ry).A(rx, ry, 0, 0, 1, x + w - rx, y + h).L(x + rx, y + h).A(rx, ry, 0, 0, 1, x, y + h - ry).L(x, y + ry).A(rx, ry, 0, 0, 1, x + rx, y).Z();
3087
+ } else {
3088
+ this.shape = new SvgShape().M(x, y).L(x + w, y).L(x + w, y + h).L(x, y + h).Z();
3089
+ }
3090
+ } else {
3091
+ this.shape = new SvgShape();
3092
+ }
3093
+ };
3094
+ var SvgElemCircle = function (obj, inherits) {
3095
+ SvgElemBasicShape.call(this, obj, inherits);
3096
+ let cx = this.getLength('cx', this.getVWidth(), 0),
3097
+ cy = this.getLength('cy', this.getVHeight(), 0),
3098
+ r = this.getLength('r', this.getViewport(), 0);
3099
+ if (r > 0) {
3100
+ this.shape = new SvgShape().M(cx + r, cy).A(r, r, 0, 0, 1, cx - r, cy).A(r, r, 0, 0, 1, cx + r, cy).Z();
3101
+ } else {
3102
+ this.shape = new SvgShape();
3103
+ }
3104
+ };
3105
+ var SvgElemEllipse = function (obj, inherits) {
3106
+ SvgElemBasicShape.call(this, obj, inherits);
3107
+ let cx = this.getLength('cx', this.getVWidth(), 0),
3108
+ cy = this.getLength('cy', this.getVHeight(), 0),
3109
+ rx = this.getLength('rx', this.getVWidth(), 0),
3110
+ ry = this.getLength('ry', this.getVHeight(), 0);
3111
+ if (rx > 0 && ry > 0) {
3112
+ this.shape = new SvgShape().M(cx + rx, cy).A(rx, ry, 0, 0, 1, cx - rx, cy).A(rx, ry, 0, 0, 1, cx + rx, cy).Z();
3113
+ } else {
3114
+ this.shape = new SvgShape();
3115
+ }
3116
+ };
3117
+ var SvgElemLine = function (obj, inherits) {
3118
+ SvgElemBasicShape.call(this, obj, inherits);
3119
+ let x1 = this.getLength('x1', this.getVWidth(), 0),
3120
+ y1 = this.getLength('y1', this.getVHeight(), 0),
3121
+ x2 = this.getLength('x2', this.getVWidth(), 0),
3122
+ y2 = this.getLength('y2', this.getVHeight(), 0);
3123
+ this.shape = new SvgShape().M(x1, y1).L(x2, y2);
3124
+ };
3125
+ var SvgElemPolyline = function (obj, inherits) {
3126
+ SvgElemBasicShape.call(this, obj, inherits);
3127
+ let points = this.getNumberList('points');
3128
+ this.shape = new SvgShape();
3129
+ for (let i = 0; i < points.length - 1; i += 2) {
3130
+ if (i === 0) {
3131
+ this.shape.M(points[i], points[i + 1]);
3132
+ } else {
3133
+ this.shape.L(points[i], points[i + 1]);
3134
+ }
3135
+ }
3136
+ if (points.error) {
3137
+ warningCallback('SvgElemPolygon: unexpected string ' + points.error);
3138
+ }
3139
+ if (points.length % 2 === 1) {
3140
+ warningCallback('SvgElemPolyline: uneven number of coordinates');
3141
+ }
3142
+ };
3143
+ var SvgElemPolygon = function (obj, inherits) {
3144
+ SvgElemBasicShape.call(this, obj, inherits);
3145
+ let points = this.getNumberList('points');
3146
+ this.shape = new SvgShape();
3147
+ for (let i = 0; i < points.length - 1; i += 2) {
3148
+ if (i === 0) {
3149
+ this.shape.M(points[i], points[i + 1]);
3150
+ } else {
3151
+ this.shape.L(points[i], points[i + 1]);
3152
+ }
3153
+ }
3154
+ this.shape.Z();
3155
+ if (points.error) {
3156
+ warningCallback('SvgElemPolygon: unexpected string ' + points.error);
3157
+ }
3158
+ if (points.length % 2 === 1) {
3159
+ warningCallback('SvgElemPolygon: uneven number of coordinates');
3160
+ }
3161
+ };
3162
+ var SvgElemPath = function (obj, inherits) {
3163
+ SvgElemBasicShape.call(this, obj, inherits);
3164
+ this.shape = new SvgShape().path(this.attr('d'));
3165
+ let pathLength = this.getLength('pathLength', this.getViewport());
3166
+ this.pathLength = pathLength > 0 ? pathLength : undefined;
3167
+ this.dashScale = this.pathLength !== undefined ? this.shape.totalLength / this.pathLength : 1;
3168
+ };
3169
+ var SvgElemMarker = function (obj, inherits) {
3170
+ SvgElemHasChildren.call(this, obj, inherits);
3171
+ let width = this.getLength('markerWidth', this.getParentVWidth(), 3),
3172
+ height = this.getLength('markerHeight', this.getParentVHeight(), 3),
3173
+ viewBox = this.getViewbox('viewBox', [0, 0, width, height]);
3174
+ this.getVWidth = function () {
3175
+ return viewBox[2];
3176
+ };
3177
+ this.getVHeight = function () {
3178
+ return viewBox[3];
3179
+ };
3180
+ this.drawMarker = function (isClip, isMask, posArray, strokeWidth) {
3181
+ doc.save();
3182
+ let orient = this.attr('orient'),
3183
+ units = this.attr('markerUnits'),
3184
+ rotate = orient === 'auto' ? posArray[2] : (parseFloat(orient) || 0) * Math.PI / 180,
3185
+ scale = units === 'userSpaceOnUse' ? 1 : strokeWidth;
3186
+ doc.transform(Math.cos(rotate) * scale, Math.sin(rotate) * scale, -Math.sin(rotate) * scale, Math.cos(rotate) * scale, posArray[0], posArray[1]);
3187
+ let refX = this.getLength('refX', this.getVWidth(), 0),
3188
+ refY = this.getLength('refY', this.getVHeight(), 0),
3189
+ aspectRatioMatrix = parseAspectRatio(this.attr('preserveAspectRatio'), width, height, viewBox[2], viewBox[3], 0.5);
3190
+ if (this.get('overflow') === 'hidden') {
3191
+ doc.rect(aspectRatioMatrix[0] * (viewBox[0] + viewBox[2] / 2 - refX) - width / 2, aspectRatioMatrix[3] * (viewBox[1] + viewBox[3] / 2 - refY) - height / 2, width, height).clip();
3192
+ }
3193
+ doc.transform.apply(doc, aspectRatioMatrix);
3194
+ doc.translate(-refX, -refY);
3195
+ let group;
3196
+ if (this.get('opacity') < 1 && !isClip) {
3197
+ group = docBeginGroup(getPageBBox());
3198
+ }
3199
+ this.drawChildren(isClip, isMask);
3200
+ if (group) {
3201
+ docEndGroup(group);
3202
+ doc.fillOpacity(this.get('opacity'));
3203
+ docInsertGroup(group);
3204
+ }
3205
+ doc.restore();
3206
+ };
3207
+ };
3208
+ var SvgElemClipPath = function (obj, inherits) {
3209
+ SvgElemHasChildren.call(this, obj, inherits);
3210
+ this.useMask = function (bBox) {
3211
+ let group = docBeginGroup(getPageBBox());
3212
+ doc.save();
3213
+ doc.transform.apply(doc, this.get('transform'));
3214
+ if (this.attr('clipPathUnits') === 'objectBoundingBox') {
3215
+ doc.transform(bBox[2] - bBox[0], 0, 0, bBox[3] - bBox[1], bBox[0], bBox[1]);
3216
+ }
3217
+ this.clip();
3218
+ this.drawChildren(true, false);
3219
+ doc.restore();
3220
+ docEndGroup(group);
3221
+ docApplyMask(group, true);
3222
+ };
3223
+ };
3224
+ var SvgElemMask = function (obj, inherits) {
3225
+ SvgElemHasChildren.call(this, obj, inherits);
3226
+ this.useMask = function (bBox) {
3227
+ let group = docBeginGroup(getPageBBox());
3228
+ doc.save();
3229
+ let x, y, w, h;
3230
+ if (this.attr('maskUnits') === 'userSpaceOnUse') {
3231
+ x = this.getLength('x', this.getVWidth(), -0.1 * (bBox[2] - bBox[0]) + bBox[0]);
3232
+ y = this.getLength('y', this.getVHeight(), -0.1 * (bBox[3] - bBox[1]) + bBox[1]);
3233
+ w = this.getLength('width', this.getVWidth(), 1.2 * (bBox[2] - bBox[0]));
3234
+ h = this.getLength('height', this.getVHeight(), 1.2 * (bBox[3] - bBox[1]));
3235
+ } else {
3236
+ x = this.getLength('x', this.getVWidth(), -0.1) * (bBox[2] - bBox[0]) + bBox[0];
3237
+ y = this.getLength('y', this.getVHeight(), -0.1) * (bBox[3] - bBox[1]) + bBox[1];
3238
+ w = this.getLength('width', this.getVWidth(), 1.2) * (bBox[2] - bBox[0]);
3239
+ h = this.getLength('height', this.getVHeight(), 1.2) * (bBox[3] - bBox[1]);
3240
+ }
3241
+ if (this.attr('maskContentUnits') === 'objectBoundingBox') {
3242
+ doc.transform(bBox[2] - bBox[0], 0, 0, bBox[3] - bBox[1], bBox[0], bBox[1]);
3243
+ }
3244
+ this.clip();
3245
+ this.drawChildren(false, true);
3246
+ doc.restore();
3247
+ docEndGroup(group);
3248
+ docApplyMask(group, true);
3249
+ };
3250
+ };
3251
+ var SvgElemTextContainer = function (obj, inherits) {
3252
+ SvgElemStylable.call(this, obj, inherits);
3253
+ this.allowedChildren = ['tspan', '#text', '#cdata-section', 'a'];
3254
+ this.isText = true;
3255
+ this.getBoundingShape = function () {
3256
+ let shape = new SvgShape();
3257
+ for (let i = 0; i < this._pos.length; i++) {
3258
+ let pos = this._pos[i];
3259
+ if (!pos.hidden) {
3260
+ let dx0 = pos.ascent * Math.sin(pos.rotate),
3261
+ dy0 = -pos.ascent * Math.cos(pos.rotate),
3262
+ dx1 = pos.descent * Math.sin(pos.rotate),
3263
+ dy1 = -pos.descent * Math.cos(pos.rotate),
3264
+ dx2 = pos.width * Math.cos(pos.rotate),
3265
+ dy2 = pos.width * Math.sin(pos.rotate);
3266
+ shape.M(pos.x + dx0, pos.y + dy0).L(pos.x + dx0 + dx2, pos.y + dy0 + dy2).M(pos.x + dx1 + dx2, pos.y + dy1 + dy2).L(pos.x + dx1, pos.y + dy1);
3267
+ }
3268
+ }
3269
+ return shape;
3270
+ };
3271
+ this.drawTextInDocument = function (isClip, isMask) {
3272
+ if (this.link && !isClip && !isMask) {
3273
+ this.addLink();
3274
+ }
3275
+ if (this.get('text-decoration') === 'underline') {
3276
+ this.decorate(0.05 * this._font.size, -0.075 * this._font.size, isClip, isMask);
3277
+ }
3278
+ if (this.get('text-decoration') === 'overline') {
3279
+ this.decorate(0.05 * this._font.size, getAscent(this._font.font, this._font.size) + 0.075 * this._font.size, isClip, isMask);
3280
+ }
3281
+ let fill = this.getFill(isClip, isMask),
3282
+ stroke = this.getStroke(isClip, isMask),
3283
+ strokeWidth = this.get('stroke-width');
3284
+ if (this._font.fauxBold) {
3285
+ if (!stroke) {
3286
+ stroke = fill;
3287
+ strokeWidth = this._font.size * 0.03;
3288
+ } else {
3289
+ strokeWidth += this._font.size * 0.03;
3290
+ }
3291
+ }
3292
+ let children = this.getChildren();
3293
+ for (let i = 0; i < children.length; i++) {
3294
+ let childElem = children[i];
3295
+ switch (childElem.name) {
3296
+ case 'tspan':
3297
+ case 'textPath':
3298
+ case 'a':
3299
+ if (childElem.get('display') !== 'none') {
3300
+ childElem.drawTextInDocument(isClip, isMask);
3301
+ }
3302
+ break;
3303
+ case '#text':
3304
+ case '#cdata-section':
3305
+ if (this.get('visibility') === 'hidden') {
3306
+ continue;
3307
+ }
3308
+ if (fill || stroke || isClip) {
3309
+ if (fill) {
3310
+ docFillColor(fill);
3311
+ }
3312
+ if (stroke && strokeWidth) {
3313
+ docStrokeColor(stroke);
3314
+ doc.lineWidth(strokeWidth).miterLimit(this.get('stroke-miterlimit')).lineJoin(this.get('stroke-linejoin')).lineCap(this.get('stroke-linecap'));
3315
+ docApplyDash(this.get('stroke-dasharray'), this.get('stroke-dashoffset'));
3316
+ }
3317
+ docBeginText(this._font.font, this._font.size);
3318
+ docSetTextMode(!!fill, !!stroke);
3319
+ docWriteGlyphs(childElem._pos, this._font);
3320
+ docEndText();
3321
+ }
3322
+ break;
3323
+ }
3324
+ }
3325
+ if (this.get('text-decoration') === 'line-through') {
3326
+ this.decorate(0.05 * this._font.size, 0.5 * (getAscent(this._font.font, this._font.size) + getDescent(this._font.font, this._font.size)), isClip, isMask);
3327
+ }
3328
+ };
3329
+ this.decorate = function (lineWidth, linePosition, isClip, isMask) {
3330
+ let fill = this.getFill(isClip, isMask),
3331
+ stroke = this.getStroke(isClip, isMask);
3332
+ if (fill) {
3333
+ docFillColor(fill);
3334
+ }
3335
+ if (stroke) {
3336
+ docStrokeColor(stroke);
3337
+ doc.lineWidth(this.get('stroke-width')).miterLimit(this.get('stroke-miterlimit')).lineJoin(this.get('stroke-linejoin')).lineCap(this.get('stroke-linecap'));
3338
+ docApplyDash(this.get('stroke-dasharray'), this.get('stroke-dashoffset'));
3339
+ }
3340
+ for (let j = 0, pos = this._pos; j < pos.length; j++) {
3341
+ if (!pos[j].hidden && isNotEqual(pos[j].width, 0)) {
3342
+ let dx0 = (linePosition + lineWidth / 2) * Math.sin(pos[j].rotate),
3343
+ dy0 = -(linePosition + lineWidth / 2) * Math.cos(pos[j].rotate),
3344
+ dx1 = (linePosition - lineWidth / 2) * Math.sin(pos[j].rotate),
3345
+ dy1 = -(linePosition - lineWidth / 2) * Math.cos(pos[j].rotate),
3346
+ dx2 = pos[j].width * Math.cos(pos[j].rotate),
3347
+ dy2 = pos[j].width * Math.sin(pos[j].rotate);
3348
+ new SvgShape().M(pos[j].x + dx0, pos[j].y + dy0).L(pos[j].x + dx0 + dx2, pos[j].y + dy0 + dy2).L(pos[j].x + dx1 + dx2, pos[j].y + dy1 + dy2).L(pos[j].x + dx1, pos[j].y + dy1).Z().insertInDocument();
3349
+ if (fill && stroke) {
3350
+ doc.fillAndStroke();
3351
+ } else if (fill) {
3352
+ doc.fill();
3353
+ } else if (stroke) {
3354
+ doc.stroke();
3355
+ }
3356
+ }
3357
+ }
3358
+ };
3359
+ };
3360
+ var SvgElemTextNode = function (obj, inherits) {
3361
+ this.name = obj.nodeName;
3362
+ this.textContent = obj.nodeValue;
3363
+ };
3364
+ var SvgElemTspan = function (obj, inherits) {
3365
+ SvgElemTextContainer.call(this, obj, inherits);
3366
+ };
3367
+ var SvgElemTextPath = function (obj, inherits) {
3368
+ SvgElemTextContainer.call(this, obj, inherits);
3369
+ let pathObject, pathLength, temp;
3370
+ if ((temp = this.attr('path')) && temp.trim() !== '') {
3371
+ let pathLength = this.getLength('pathLength', this.getViewport());
3372
+ this.pathObject = new SvgShape().path(temp);
3373
+ this.pathLength = pathLength > 0 ? pathLength : this.pathObject.totalLength;
3374
+ this.pathScale = this.pathObject.totalLength / this.pathLength;
3375
+ } else if ((temp = this.getUrl('href') || this.getUrl('xlink:href')) && temp.nodeName === 'path') {
3376
+ let pathElem = new SvgElemPath(temp, this);
3377
+ this.pathObject = pathElem.shape.clone().transform(pathElem.get('transform'));
3378
+ this.pathLength = this.chooseValue(pathElem.pathLength, this.pathObject.totalLength);
3379
+ this.pathScale = this.pathObject.totalLength / this.pathLength;
3380
+ }
3381
+ };
3382
+ var SvgElemText = function (obj, inherits) {
3383
+ SvgElemTextContainer.call(this, obj, inherits);
3384
+ this.allowedChildren = ['textPath', 'tspan', '#text', '#cdata-section', 'a'];
3385
+ (function (textParentElem) {
3386
+ let processedText = '',
3387
+ remainingText = obj.textContent,
3388
+ textPaths = [],
3389
+ currentChunk = [],
3390
+ currentAnchor,
3391
+ currentDirection,
3392
+ currentX = 0,
3393
+ currentY = 0;
3394
+ function doAnchoring() {
3395
+ if (currentChunk.length) {
3396
+ let last = currentChunk[currentChunk.length - 1];
3397
+ let first = currentChunk[0];
3398
+ let width = last.x + last.width - first.x;
3399
+ let anchordx = {
3400
+ 'startltr': 0,
3401
+ 'middleltr': 0.5,
3402
+ 'endltr': 1,
3403
+ 'startrtl': 1,
3404
+ 'middlertl': 0.5,
3405
+ 'endrtl': 0
3406
+ }[currentAnchor + currentDirection] * width || 0;
3407
+ for (let i = 0; i < currentChunk.length; i++) {
3408
+ currentChunk[i].x -= anchordx;
3409
+ }
3410
+ }
3411
+ currentChunk = [];
3412
+ }
3413
+ function adjustLength(pos, length, spacingAndGlyphs) {
3414
+ let firstChar = pos[0],
3415
+ lastChar = pos[pos.length - 1],
3416
+ startX = firstChar.x,
3417
+ endX = lastChar.x + lastChar.width;
3418
+ if (spacingAndGlyphs) {
3419
+ let textScale = length / (endX - startX);
3420
+ if (textScale > 0 && textScale < Infinity) {
3421
+ for (let j = 0; j < pos.length; j++) {
3422
+ pos[j].continuous = false;
3423
+ pos[j].x = startX + textScale * (pos[j].x - startX);
3424
+ pos[j].scale *= textScale;
3425
+ pos[j].width *= textScale;
3426
+ }
3427
+ }
3428
+ } else {
3429
+ if (pos.length >= 2) {
3430
+ let spaceDiff = (length - (endX - startX)) / (pos.length - 1);
3431
+ for (let j = 0; j < pos.length; j++) {
3432
+ pos[j].continuous = false;
3433
+ pos[j].x += j * spaceDiff;
3434
+ }
3435
+ }
3436
+ }
3437
+ currentX += length - (endX - startX);
3438
+ }
3439
+ function recursive(currentElem, parentElem) {
3440
+ currentElem._x = combineArrays(currentElem.getLengthList('x', currentElem.getVWidth()), parentElem ? parentElem._x.slice(parentElem._pos.length) : []);
3441
+ currentElem._y = combineArrays(currentElem.getLengthList('y', currentElem.getVHeight()), parentElem ? parentElem._y.slice(parentElem._pos.length) : []);
3442
+ currentElem._dx = combineArrays(currentElem.getLengthList('dx', currentElem.getVWidth()), parentElem ? parentElem._dx.slice(parentElem._pos.length) : []);
3443
+ currentElem._dy = combineArrays(currentElem.getLengthList('dy', currentElem.getVHeight()), parentElem ? parentElem._dy.slice(parentElem._pos.length) : []);
3444
+ currentElem._rot = combineArrays(currentElem.getNumberList('rotate'), parentElem ? parentElem._rot.slice(parentElem._pos.length) : []);
3445
+ currentElem._defRot = currentElem.chooseValue(currentElem._rot[currentElem._rot.length - 1], parentElem && parentElem._defRot, 0);
3446
+ if (currentElem.name === 'textPath') {
3447
+ currentElem._y = [];
3448
+ }
3449
+ let fontOptions = {
3450
+ fauxItalic: false,
3451
+ fauxBold: false
3452
+ },
3453
+ fontNameorLink = fontCallback(currentElem.get('font-family'), currentElem.get('font-weight') === 'bold', currentElem.get('font-style') === 'italic', fontOptions);
3454
+ try {
3455
+ doc.font(fontNameorLink);
3456
+ } catch (e) {
3457
+ warningCallback('SVGElemText: failed to open font "' + fontNameorLink + '" in PDFKit: ' + e.message);
3458
+ }
3459
+ currentElem._pos = [];
3460
+ currentElem._index = 0;
3461
+ currentElem._font = {
3462
+ font: doc._font,
3463
+ size: currentElem.get('font-size'),
3464
+ fauxItalic: fontOptions.fauxItalic,
3465
+ fauxBold: fontOptions.fauxBold
3466
+ };
3467
+ let textLength = currentElem.getLength('textLength', currentElem.getVWidth(), undefined),
3468
+ spacingAndGlyphs = currentElem.attr('lengthAdjust') === 'spacingAndGlyphs',
3469
+ wordSpacing = currentElem.get('word-spacing'),
3470
+ letterSpacing = currentElem.get('letter-spacing'),
3471
+ textAnchor = currentElem.get('text-anchor'),
3472
+ textDirection = currentElem.get('direction'),
3473
+ // `alignment-baseline` and `baseline-shift` have no effect on
3474
+ // `<text>` elements according to the SVG spec. So, detect when
3475
+ // we're styling a `<text>` element and ignore
3476
+ // `alignment-baseline` (only factoring in `dominant-baseline`)
3477
+ // and `baseline-shift` (which can only have the default value of
3478
+ // `baseline`).
3479
+ //
3480
+ // Note that Chrome (as of v99) incorrectly factors in
3481
+ // `alignment-baseline` on `<text>` elements, while Firefox
3482
+ // correctly follows the spec and ignores it. This means that our
3483
+ // output will differ from Chrome's in these cases, but conform to
3484
+ // SVG specification.
3485
+ isTextElem = currentElem.name === 'text',
3486
+ baselineAttr = isTextElem ? currentElem.get('dominant-baseline') : currentElem.get('alignment-baseline') || currentElem.get('dominant-baseline'),
3487
+ baselineShiftAttr = isTextElem ? 'baseline' : currentElem.get('baseline-shift'),
3488
+ baseline = getBaseline(currentElem._font.font, currentElem._font.size, baselineAttr, baselineShiftAttr);
3489
+ if (currentElem.name === 'textPath') {
3490
+ doAnchoring();
3491
+ currentX = currentY = 0;
3492
+ }
3493
+ let children = currentElem.getChildren();
3494
+ for (let i = 0; i < children.length; i++) {
3495
+ let childElem = children[i];
3496
+ switch (childElem.name) {
3497
+ case 'tspan':
3498
+ case 'textPath':
3499
+ case 'a':
3500
+ recursive(childElem, currentElem);
3501
+ break;
3502
+ case '#text':
3503
+ case '#cdata-section':
3504
+ let rawText = childElem.textContent,
3505
+ renderedText = rawText,
3506
+ words;
3507
+ childElem._font = currentElem._font;
3508
+ childElem._pos = [];
3509
+ remainingText = remainingText.substring(rawText.length);
3510
+ if (currentElem.get('xml:space') === 'preserve') {
3511
+ renderedText = renderedText.replace(/[\s]/g, ' ');
3512
+ } else {
3513
+ renderedText = renderedText.replace(/[\s]+/g, ' ');
3514
+ if (processedText.match(/[\s]$|^$/)) {
3515
+ renderedText = renderedText.replace(/^[\s]/, '');
3516
+ }
3517
+ if (remainingText.match(/^[\s]*$/)) {
3518
+ renderedText = renderedText.replace(/[\s]$/, '');
3519
+ }
3520
+ }
3521
+ processedText += rawText;
3522
+ if (wordSpacing === 0) {
3523
+ words = [renderedText];
3524
+ } else {
3525
+ words = renderedText.split(/(\s)/);
3526
+ }
3527
+ for (let w = 0; w < words.length; w++) {
3528
+ let pos = getTextPos(currentElem._font.font, currentElem._font.size, words[w]);
3529
+ for (let j = 0; j < pos.length; j++) {
3530
+ let index = currentElem._index,
3531
+ xAttr = currentElem._x[index],
3532
+ yAttr = currentElem._y[index],
3533
+ dxAttr = currentElem._dx[index],
3534
+ dyAttr = currentElem._dy[index],
3535
+ rotAttr = currentElem._rot[index],
3536
+ continuous = !(w === 0 && j === 0);
3537
+ if (letterSpacing !== 0) {
3538
+ continuous = false;
3539
+ }
3540
+ if (wordSpacing !== 0) {
3541
+ continuous = false;
3542
+ }
3543
+ if (xAttr !== undefined) {
3544
+ continuous = false;
3545
+ doAnchoring();
3546
+ currentX = xAttr;
3547
+ }
3548
+ if (yAttr !== undefined) {
3549
+ continuous = false;
3550
+ doAnchoring();
3551
+ currentY = yAttr;
3552
+ }
3553
+ if (dxAttr !== undefined) {
3554
+ continuous = false;
3555
+ currentX += dxAttr;
3556
+ }
3557
+ if (dyAttr !== undefined) {
3558
+ continuous = false;
3559
+ currentY += dyAttr;
3560
+ }
3561
+ if (rotAttr !== undefined || currentElem._defRot !== 0) {
3562
+ continuous = false;
3563
+ }
3564
+ let position = {
3565
+ glyph: pos[j].glyph,
3566
+ rotate: Math.PI / 180 * currentElem.chooseValue(rotAttr, currentElem._defRot),
3567
+ x: currentX + pos[j].xOffset,
3568
+ kern: pos[j].kern,
3569
+ y: currentY + baseline + pos[j].yOffset,
3570
+ width: pos[j].width,
3571
+ ascent: getAscent(currentElem._font.font, currentElem._font.size),
3572
+ descent: getDescent(currentElem._font.font, currentElem._font.size),
3573
+ scale: 1,
3574
+ hidden: false,
3575
+ continuous: continuous
3576
+ };
3577
+ currentChunk.push(position);
3578
+ childElem._pos.push(position);
3579
+ currentElem._pos.push(position);
3580
+ currentElem._index += pos[j].unicode.length;
3581
+ if (currentChunk.length === 1) {
3582
+ currentAnchor = textAnchor;
3583
+ currentDirection = textDirection;
3584
+ }
3585
+ currentX += pos[j].xAdvance + letterSpacing;
3586
+ currentY += pos[j].yAdvance;
3587
+ }
3588
+ if (words[w] === ' ') {
3589
+ currentX += wordSpacing;
3590
+ }
3591
+ }
3592
+ break;
3593
+ default:
3594
+ remainingText = remainingText.substring(childElem.textContent.length);
3595
+ }
3596
+ }
3597
+ if (textLength && currentElem._pos.length) {
3598
+ adjustLength(currentElem._pos, textLength, spacingAndGlyphs);
3599
+ }
3600
+ if (currentElem.name === 'textPath' || currentElem.name === 'text') {
3601
+ doAnchoring();
3602
+ }
3603
+ if (currentElem.name === 'textPath') {
3604
+ textPaths.push(currentElem);
3605
+ let pathObject = currentElem.pathObject;
3606
+ if (pathObject) {
3607
+ currentX = pathObject.endPoint[0];
3608
+ currentY = pathObject.endPoint[1];
3609
+ }
3610
+ }
3611
+ if (parentElem) {
3612
+ parentElem._pos = parentElem._pos.concat(currentElem._pos);
3613
+ parentElem._index += currentElem._index;
3614
+ }
3615
+ }
3616
+ function textOnPath(currentElem) {
3617
+ let pathObject = currentElem.pathObject,
3618
+ pathLength = currentElem.pathLength,
3619
+ pathScale = currentElem.pathScale;
3620
+ if (pathObject) {
3621
+ let textOffset = currentElem.getLength('startOffset', pathLength, 0);
3622
+ for (let j = 0; j < currentElem._pos.length; j++) {
3623
+ let charMidX = textOffset + currentElem._pos[j].x + 0.5 * currentElem._pos[j].width;
3624
+ if (charMidX > pathLength || charMidX < 0) {
3625
+ currentElem._pos[j].hidden = true;
3626
+ } else {
3627
+ let pointOnPath = pathObject.getPointAtLength(charMidX * pathScale);
3628
+ if (isNotEqual(pathScale, 1)) {
3629
+ currentElem._pos[j].scale *= pathScale;
3630
+ currentElem._pos[j].width *= pathScale;
3631
+ }
3632
+ currentElem._pos[j].x = pointOnPath[0] - 0.5 * currentElem._pos[j].width * Math.cos(pointOnPath[2]) - currentElem._pos[j].y * Math.sin(pointOnPath[2]);
3633
+ currentElem._pos[j].y = pointOnPath[1] - 0.5 * currentElem._pos[j].width * Math.sin(pointOnPath[2]) + currentElem._pos[j].y * Math.cos(pointOnPath[2]);
3634
+ currentElem._pos[j].rotate = pointOnPath[2] + currentElem._pos[j].rotate;
3635
+ currentElem._pos[j].continuous = false;
3636
+ }
3637
+ }
3638
+ } else {
3639
+ for (let j = 0; j < currentElem._pos.length; j++) {
3640
+ currentElem._pos[j].hidden = true;
3641
+ }
3642
+ }
3643
+ }
3644
+ recursive(textParentElem, null);
3645
+ for (let i = 0; i < textPaths.length; i++) {
3646
+ textOnPath(textPaths[i]);
3647
+ }
3648
+ })(this);
3649
+ this.getTransformation = function () {
3650
+ return this.get('transform');
3651
+ };
3652
+ this.drawInDocument = function (isClip, isMask) {
3653
+ doc.save();
3654
+ this.transform();
3655
+ this.clip();
3656
+ let masked = this.mask(),
3657
+ group;
3658
+ if (masked) {
3659
+ group = docBeginGroup(getPageBBox());
3660
+ }
3661
+ this.drawTextInDocument(isClip, isMask);
3662
+ if (group) {
3663
+ docEndGroup(group);
3664
+ docInsertGroup(group);
3665
+ }
3666
+ doc.restore();
3667
+ };
3668
+ };
3669
+ options = options || {};
3670
+ var pxToPt = options.assumePt ? 1 : 72 / 96,
3671
+ // 1px = 72/96pt, but only if assumePt is false
3672
+ viewportWidth = (options.width || doc.page.width) / pxToPt,
3673
+ viewportHeight = (options.height || doc.page.height) / pxToPt,
3674
+ preserveAspectRatio = options.preserveAspectRatio || null,
3675
+ // default to null so that the attr can override if not passed
3676
+ useCSS = options.useCSS && typeof SVGElement !== 'undefined' && svg instanceof SVGElement && typeof getComputedStyle === 'function',
3677
+ warningCallback = options.warningCallback,
3678
+ fontCallback = options.fontCallback,
3679
+ imageCallback = options.imageCallback,
3680
+ colorCallback = options.colorCallback,
3681
+ documentCallback = options.documentCallback,
3682
+ precision = Math.ceil(Math.max(1, options.precision)) || 3,
3683
+ groupStack = [],
3684
+ documentCache = {},
3685
+ links = [],
3686
+ styleRules = [];
3687
+ if (typeof warningCallback !== 'function') {
3688
+ warningCallback = function (str) {
3689
+ if (typeof console !== undefined && typeof console.warn === 'function') {
3690
+ console.warn(str);
3691
+ }
3692
+ };
3693
+ }
3694
+ if (typeof fontCallback !== 'function') {
3695
+ fontCallback = function (family, bold, italic, fontOptions) {
3696
+ // Check if the font is already registered in the document
3697
+ if (bold && italic) {
3698
+ if (doc._registeredFonts.hasOwnProperty(family + '-BoldItalic')) {
3699
+ return family + '-BoldItalic';
3700
+ } else if (doc._registeredFonts.hasOwnProperty(family + '-Italic')) {
3701
+ fontOptions.fauxBold = true;
3702
+ return family + '-Italic';
3703
+ } else if (doc._registeredFonts.hasOwnProperty(family + '-Bold')) {
3704
+ fontOptions.fauxItalic = true;
3705
+ return family + '-Bold';
3706
+ } else if (doc._registeredFonts.hasOwnProperty(family)) {
3707
+ fontOptions.fauxBold = true;
3708
+ fontOptions.fauxItalic = true;
3709
+ return family;
3710
+ }
3711
+ }
3712
+ if (bold && !italic) {
3713
+ if (doc._registeredFonts.hasOwnProperty(family + '-Bold')) {
3714
+ return family + '-Bold';
3715
+ } else if (doc._registeredFonts.hasOwnProperty(family)) {
3716
+ fontOptions.fauxBold = true;
3717
+ return family;
3718
+ }
3719
+ }
3720
+ if (!bold && italic) {
3721
+ if (doc._registeredFonts.hasOwnProperty(family + '-Italic')) {
3722
+ return family + '-Italic';
3723
+ } else if (doc._registeredFonts.hasOwnProperty(family)) {
3724
+ fontOptions.fauxItalic = true;
3725
+ return family;
3726
+ }
3727
+ }
3728
+ if (!bold && !italic) {
3729
+ if (doc._registeredFonts.hasOwnProperty(family)) {
3730
+ return family;
3731
+ }
3732
+ }
3733
+ // Use standard fonts as fallback
3734
+ if (family.match(/(?:^|,)\s*serif\s*$/)) {
3735
+ if (bold && italic) {
3736
+ return 'Times-BoldItalic';
3737
+ }
3738
+ if (bold && !italic) {
3739
+ return 'Times-Bold';
3740
+ }
3741
+ if (!bold && italic) {
3742
+ return 'Times-Italic';
3743
+ }
3744
+ if (!bold && !italic) {
3745
+ return 'Times-Roman';
3746
+ }
3747
+ } else if (family.match(/(?:^|,)\s*monospace\s*$/)) {
3748
+ if (bold && italic) {
3749
+ return 'Courier-BoldOblique';
3750
+ }
3751
+ if (bold && !italic) {
3752
+ return 'Courier-Bold';
3753
+ }
3754
+ if (!bold && italic) {
3755
+ return 'Courier-Oblique';
3756
+ }
3757
+ if (!bold && !italic) {
3758
+ return 'Courier';
3759
+ }
3760
+ } else if (family.match(/(?:^|,)\s*sans-serif\s*$/) || true) {
3761
+ if (bold && italic) {
3762
+ return 'Helvetica-BoldOblique';
3763
+ }
3764
+ if (bold && !italic) {
3765
+ return 'Helvetica-Bold';
3766
+ }
3767
+ if (!bold && italic) {
3768
+ return 'Helvetica-Oblique';
3769
+ }
3770
+ if (!bold && !italic) {
3771
+ return 'Helvetica';
3772
+ }
3773
+ }
3774
+ };
3775
+ }
3776
+ if (typeof imageCallback !== 'function') {
3777
+ imageCallback = function (link) {
3778
+ return link.replace(/\s+/g, '');
3779
+ };
3780
+ }
3781
+ if (typeof colorCallback !== 'function') {
3782
+ colorCallback = null;
3783
+ } else {
3784
+ for (let color in DefaultColors) {
3785
+ let newColor = colorCallback(DefaultColors[color]);
3786
+ DefaultColors[color][0] = newColor[0];
3787
+ DefaultColors[color][1] = newColor[1];
3788
+ }
3789
+ }
3790
+ if (typeof documentCallback !== 'function') {
3791
+ documentCallback = null;
3792
+ }
3793
+ if (typeof svg === 'string') {
3794
+ svg = parseXml(svg);
3795
+ }
3796
+ if (svg) {
3797
+ let styles = svg.getElementsByTagName('style');
3798
+ for (let i = 0; i < styles.length; i++) {
3799
+ styleRules = styleRules.concat(parseStyleSheet(styles[i].textContent));
3800
+ }
3801
+ let elem = createSVGElement(svg, null);
3802
+ if (typeof elem.drawInDocument === 'function') {
3803
+ if (options.useCSS && !useCSS) {
3804
+ warningCallback('SVGtoPDF: useCSS option can only be used for SVG *elements* in compatible browsers');
3805
+ }
3806
+ let savedFillColor = doc._fillColor;
3807
+ doc.save().translate(x || 0, y || 0).scale(pxToPt);
3808
+ elem.drawInDocument();
3809
+ for (let i = 0; i < links.length; i++) {
3810
+ doc.page.annotations.push(links[i]);
3811
+ }
3812
+ doc.restore();
3813
+ doc._fillColor = savedFillColor;
3814
+ } else {
3815
+ warningCallback('SVGtoPDF: this element can\'t be rendered directly: ' + svg.nodeName);
3816
+ }
3817
+ } else {
3818
+ warningCallback('SVGtoPDF: the input does not look like a valid SVG');
3819
+ }
3820
+ };
3821
+ if (typeof module !== 'undefined' && module && typeof module.exports !== 'undefined') {
3822
+ module.exports = SVGtoPDF;
3823
+ }