@digicole/pdfmake-rtl 1.2.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/tasks.json +17 -0
- package/CHANGELOG.md +83 -128
- package/LICENSE +22 -22
- package/README.md +188 -681
- package/build/fonts/Cairo/Cairo-Black.ttf +0 -0
- package/build/fonts/Cairo/Cairo-Bold.ttf +0 -0
- package/build/fonts/Cairo/Cairo-ExtraLight.ttf +0 -0
- package/build/fonts/Cairo/Cairo-Light.ttf +0 -0
- package/build/fonts/Cairo/Cairo-Regular.ttf +0 -0
- package/build/fonts/Cairo/Cairo-SemiBold.ttf +0 -0
- package/build/fonts/Cairo.js +27 -0
- package/build/fonts/Roboto/Roboto-Italic.ttf +0 -0
- package/build/fonts/Roboto/Roboto-Medium.ttf +0 -0
- package/build/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
- package/build/fonts/Roboto/Roboto-Regular.ttf +0 -0
- package/build/fonts/Roboto.js +27 -0
- package/build/pdfmake.js +63736 -71285
- package/build/pdfmake.js.map +1 -1
- package/build/pdfmake.min.js +2 -2
- package/build/pdfmake.min.js.map +1 -1
- package/build/standard-fonts/Courier.js +27 -0
- package/build/standard-fonts/Helvetica.js +27 -0
- package/build/standard-fonts/Symbol.js +21 -0
- package/build/standard-fonts/Times.js +27 -0
- package/build/standard-fonts/ZapfDingbats.js +21 -0
- package/build/vfs_fonts.js +11 -7
- package/build-vfs.js +44 -44
- package/fonts/Cairo/Cairo-Black.ttf +0 -0
- package/fonts/Cairo/Cairo-Bold.ttf +0 -0
- package/fonts/Cairo/Cairo-ExtraLight.ttf +0 -0
- package/fonts/Cairo/Cairo-Light.ttf +0 -0
- package/fonts/Cairo/Cairo-Regular.ttf +0 -0
- package/fonts/Cairo/Cairo-SemiBold.ttf +0 -0
- package/fonts/Cairo.js +8 -0
- package/fonts/Roboto/Roboto-Italic.ttf +0 -0
- package/fonts/Roboto/Roboto-Medium.ttf +0 -0
- package/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
- package/fonts/Roboto/Roboto-Regular.ttf +0 -0
- package/fonts/Roboto.js +8 -0
- package/index.js +26 -26
- package/package.json +42 -39
- package/src/3rd-party/svg-to-pdfkit/LICENSE +9 -9
- package/src/3rd-party/svg-to-pdfkit/source.js +229 -36
- package/src/3rd-party/svg-to-pdfkit.js +3 -3
- package/src/OutputDocument.js +64 -0
- package/src/OutputDocumentServer.js +32 -0
- package/src/PDFDocument.js +174 -0
- package/src/PageSize.js +53 -0
- package/src/Renderer.js +445 -0
- package/src/TextBreaker.js +168 -0
- package/src/TextInlines.js +263 -0
- package/src/URLResolver.js +43 -0
- package/src/base.js +70 -0
- package/src/browser-extensions/OutputDocumentBrowser.js +80 -0
- package/src/browser-extensions/fonts/Cairo.js +27 -0
- package/src/browser-extensions/fonts/Roboto.js +27 -0
- package/src/browser-extensions/index.js +61 -0
- package/src/browser-extensions/pdfMake.js +1 -355
- package/src/browser-extensions/standard-fonts/Courier.js +27 -0
- package/src/browser-extensions/standard-fonts/Helvetica.js +27 -0
- package/src/browser-extensions/standard-fonts/Symbol.js +21 -0
- package/src/browser-extensions/standard-fonts/Times.js +27 -0
- package/src/browser-extensions/standard-fonts/ZapfDingbats.js +21 -0
- package/src/browser-extensions/virtual-fs-cjs.js +1 -0
- package/src/columnCalculator.js +154 -157
- package/src/docMeasure.js +802 -810
- package/src/docPreprocessor.js +306 -273
- package/src/documentContext.js +345 -340
- package/src/elementWriter.js +736 -411
- package/src/helpers/node.js +136 -0
- package/src/helpers/tools.js +44 -0
- package/src/helpers/variableType.js +50 -0
- package/src/index.js +16 -0
- package/src/layoutBuilder.js +1393 -1197
- package/src/line.js +122 -104
- package/src/pageElementWriter.js +187 -174
- package/src/printer.js +370 -727
- package/src/qrEnc.js +796 -791
- package/src/rtlUtils.js +500 -485
- package/src/standardPageSizes.js +52 -54
- package/src/styleContextStack.js +208 -138
- package/src/svgMeasure.js +109 -70
- package/src/tableLayouts.js +100 -0
- package/src/tableProcessor.js +620 -606
- package/src/textDecorator.js +175 -157
- package/src/virtual-fs.js +66 -0
- package/standard-fonts/Courier.js +8 -0
- package/standard-fonts/Helvetica.js +8 -0
- package/standard-fonts/Symbol.js +5 -0
- package/standard-fonts/Times.js +8 -0
- package/standard-fonts/ZapfDingbats.js +5 -0
- package/index.html +0 -396
- package/src/browser-extensions/URLBrowserResolver.js +0 -96
- package/src/browser-extensions/virtual-fs.js +0 -55
- package/src/fontProvider.js +0 -68
- package/src/helpers.js +0 -138
- package/src/imageMeasure.js +0 -62
- package/src/pdfKitEngine.js +0 -21
- package/src/textTools.js +0 -391
- package/src/traversalTracker.js +0 -47
|
@@ -60,7 +60,8 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
60
60
|
'display': {inherit: false, initial: 'inline', values: {'none':'none', 'inline':'inline', 'block':'inline'}},
|
|
61
61
|
'clip-path': {inherit: false, initial: 'none'},
|
|
62
62
|
'mask': {inherit: false, initial: 'none'},
|
|
63
|
-
'overflow': {inherit: false, initial: 'hidden', values: {'hidden':'hidden', 'scroll':'hidden', 'visible':'visible'}}
|
|
63
|
+
'overflow': {inherit: false, initial: 'hidden', values: {'hidden':'hidden', 'scroll':'hidden', 'visible':'visible'}},
|
|
64
|
+
'vector-effect': {inherit: true, initial: 'none', values: {'none':'none', 'non-scaling-stroke':'non-scaling-stroke'}}
|
|
64
65
|
};
|
|
65
66
|
|
|
66
67
|
function docBeginGroup(bbox) {
|
|
@@ -113,11 +114,13 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
113
114
|
doc.addContent('/' + name + ' gs');
|
|
114
115
|
}
|
|
115
116
|
function docCreatePattern(group, dx, dy, matrix) {
|
|
116
|
-
let pattern =
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
let pattern = {
|
|
118
|
+
type: 'PDFPattern',
|
|
119
|
+
group: group,
|
|
120
|
+
dx: dx,
|
|
121
|
+
dy: dy,
|
|
122
|
+
matrix: matrix || [1, 0, 0, 1, 0, 0],
|
|
123
|
+
}
|
|
121
124
|
return pattern;
|
|
122
125
|
}
|
|
123
126
|
function docUsePattern(pattern, stroke) {
|
|
@@ -153,14 +156,62 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
153
156
|
let mode = fill && stroke ? 2 : stroke ? 1 : fill ? 0 : 3;
|
|
154
157
|
doc.addContent(mode + ' Tr');
|
|
155
158
|
}
|
|
156
|
-
function
|
|
157
|
-
|
|
159
|
+
function docWriteGlyphs(positions, font) {
|
|
160
|
+
let commands = [];
|
|
161
|
+
let commandStr = '';
|
|
162
|
+
const skew = font.fauxItalic ? -0.25 : 0;
|
|
163
|
+
|
|
164
|
+
// Add the given character to the 'TJ' command string.
|
|
165
|
+
function addChar(char) {
|
|
166
|
+
commandStr += char.glyph;
|
|
167
|
+
if (char.kern === 0) return;
|
|
168
|
+
commands.push(`<${commandStr}> ${validateNumber(char.kern)}`);
|
|
169
|
+
commandStr = '';
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// Flush the current TJ command string to the output stream.
|
|
173
|
+
function flush() {
|
|
174
|
+
if (commandStr.length) {
|
|
175
|
+
commands.push(`<${commandStr}> 0`);
|
|
176
|
+
commandStr = '';
|
|
177
|
+
}
|
|
178
|
+
if (commands.length) {
|
|
179
|
+
doc.addContent(`[${commands.join(' ')}] TJ`);
|
|
180
|
+
commands = [];
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
for (let i = 0; i < positions.length; i++) {
|
|
185
|
+
const pos = positions[i];
|
|
186
|
+
|
|
187
|
+
if (pos.hidden || isEqual(pos.width, 0)) {
|
|
188
|
+
flush();
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (pos.continuous) {
|
|
193
|
+
addChar(pos);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// If this character is non-continuous, flush the command buffer.
|
|
198
|
+
flush();
|
|
199
|
+
|
|
200
|
+
// Start a new TJ command after writing a Text Matrix (Tm)
|
|
201
|
+
const cos = Math.cos(pos.rotate);
|
|
202
|
+
const sin = Math.sin(pos.rotate);
|
|
203
|
+
docSetTextMatrix(cos * pos.scale, sin * pos.scale, cos * skew - sin, sin * skew + cos, pos.x, pos.y);
|
|
204
|
+
addChar(pos);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// Flush any remaining characters in the buffer.
|
|
208
|
+
flush();
|
|
158
209
|
}
|
|
159
210
|
function docEndText() {
|
|
160
211
|
doc.addContent('ET');
|
|
161
212
|
}
|
|
162
213
|
function docFillColor(color) {
|
|
163
|
-
if (color[0].
|
|
214
|
+
if (color[0].type === 'PDFPattern') {
|
|
164
215
|
doc.fillOpacity(color[1]);
|
|
165
216
|
docUsePattern(color[0], false);
|
|
166
217
|
} else {
|
|
@@ -168,13 +219,127 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
168
219
|
}
|
|
169
220
|
}
|
|
170
221
|
function docStrokeColor(color) {
|
|
171
|
-
if (color[0].
|
|
222
|
+
if (color[0].type === 'PDFPattern') {
|
|
172
223
|
doc.strokeOpacity(color[1]);
|
|
173
224
|
docUsePattern(color[0], true);
|
|
174
225
|
} else {
|
|
175
226
|
doc.strokeColor(color[0], color[1]);
|
|
176
227
|
}
|
|
177
228
|
}
|
|
229
|
+
// PDFKit doesn't accept any 0s in the dash array, but that's perfectly
|
|
230
|
+
// valid in SVG. So this function applys a dash array and offset, detecting
|
|
231
|
+
// any 0s in the dash array and updating it and the dash offset as needed to
|
|
232
|
+
// remove the zeros, but preserve the end result.
|
|
233
|
+
//
|
|
234
|
+
// `dashArray` must have an even number of elements
|
|
235
|
+
function docApplyDash(dashArray, dashOffset) {
|
|
236
|
+
let index;
|
|
237
|
+
// Anytime there's a 0 that isn't the first or last element of the array,
|
|
238
|
+
// we can remove it by combining the previous or next value. If it's a
|
|
239
|
+
// dash, then it's a zero-length dash between two spaces, so the dash can
|
|
240
|
+
// be eliminated and spaces combined by summing them, replacing all three
|
|
241
|
+
// values with the sum of the two spaces. If the 0 value is a space, then
|
|
242
|
+
// it's a zero-length space between two dashes, and the dashes can be
|
|
243
|
+
// similarly combined. So first we run that logic iteratively to remove
|
|
244
|
+
// all the 0s from the dash array that aren't the first or last element.
|
|
245
|
+
// Note that because we replace 3 values with one value, this doesn't
|
|
246
|
+
// change the even-ness of the length of dashArray.
|
|
247
|
+
while ((index = dashArray.slice(1, -1).indexOf(0)) !== -1) {
|
|
248
|
+
let actualIndex = index + 1;
|
|
249
|
+
let replacementValue = dashArray[actualIndex - 1] + dashArray[actualIndex + 1];
|
|
250
|
+
dashArray = dashArray
|
|
251
|
+
.slice(0, actualIndex - 1)
|
|
252
|
+
.concat([replacementValue])
|
|
253
|
+
.concat(dashArray.slice(actualIndex + 2));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// The stroke array only having two elements (a dash value and space
|
|
257
|
+
// value) is a special case.
|
|
258
|
+
if (dashArray.length === 2) {
|
|
259
|
+
if (dashArray[0] === 0) {
|
|
260
|
+
// Regardless of the space value, the dash length is zero, so we're
|
|
261
|
+
// not actually drawing a stroke. We can't describe that in a
|
|
262
|
+
// doc.dash() call in a way that PDFKit will accept, so we set the
|
|
263
|
+
// stroke opacity to zero as our best approximation.
|
|
264
|
+
doc.strokeOpacity(0);
|
|
265
|
+
return;
|
|
266
|
+
} else if (dashArray[1] === 0) {
|
|
267
|
+
// Regardless of the dash value, the space value is zero, meaning
|
|
268
|
+
// we're actually drawing a solid stroke, not a dashed one. We can
|
|
269
|
+
// make this happen by just emptying out the dash array.
|
|
270
|
+
dashArray = [];
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
if (dashArray[0] === 0) {
|
|
274
|
+
// The first dash is zero-length. We fix this by combining the first
|
|
275
|
+
// space (just after the first dash) with the last space and updating
|
|
276
|
+
// the dash offset accordingly. For example, if we had
|
|
277
|
+
//
|
|
278
|
+
// [ 0 4 3 2 5 1 ] (dash offset 0)
|
|
279
|
+
//
|
|
280
|
+
// ␣␣␣␣---␣␣-----␣
|
|
281
|
+
// ⎸
|
|
282
|
+
//
|
|
283
|
+
// we'd end up with
|
|
284
|
+
//
|
|
285
|
+
// [ 3 2 5 5 ] (dash offset -4)
|
|
286
|
+
//
|
|
287
|
+
// ---␣␣-----␣␣␣␣␣
|
|
288
|
+
// ⎸
|
|
289
|
+
//
|
|
290
|
+
// Another example where the dash array also ends with a 0:
|
|
291
|
+
//
|
|
292
|
+
// [ 0 4 3 2 5 0 ] (dash offset 0)
|
|
293
|
+
//
|
|
294
|
+
// ␣␣␣␣---␣␣-----
|
|
295
|
+
// ⎸
|
|
296
|
+
//
|
|
297
|
+
// we'd end up with
|
|
298
|
+
//
|
|
299
|
+
// [ 3 2 5 4 ] (dash offset -4)
|
|
300
|
+
//
|
|
301
|
+
// ---␣␣-----␣␣␣␣
|
|
302
|
+
// ⎸
|
|
303
|
+
dashOffset -= dashArray[1];
|
|
304
|
+
dashArray[dashArray.length - 1] += dashArray[1];
|
|
305
|
+
dashArray = dashArray.slice(2);
|
|
306
|
+
}
|
|
307
|
+
if (dashArray[dashArray.length - 1] === 0) {
|
|
308
|
+
// The last space is zero-length. We fix this by combining the last dash
|
|
309
|
+
// (just before the last space) with the first dash and updating the
|
|
310
|
+
// dash offset accordingly. For example, if we had
|
|
311
|
+
//
|
|
312
|
+
// [ 1 4 3 2 5 0 ] (dash offset 0)
|
|
313
|
+
//
|
|
314
|
+
// -␣␣␣␣---␣␣-----
|
|
315
|
+
// ⎸
|
|
316
|
+
//
|
|
317
|
+
// we'd end up with
|
|
318
|
+
//
|
|
319
|
+
// [ 6 4 3 2 ] (dash offset 5)
|
|
320
|
+
//
|
|
321
|
+
// ------␣␣␣␣---␣␣
|
|
322
|
+
// ⎸
|
|
323
|
+
//
|
|
324
|
+
dashOffset += dashArray[dashArray.length - 2];
|
|
325
|
+
dashArray[0] += dashArray[dashArray.length - 2];
|
|
326
|
+
dashArray = dashArray.slice(0, -2);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Ensure the dash offset is non-negative (because of crbug.com/660850).
|
|
331
|
+
// First compute the total length of the dash array so we can add it to
|
|
332
|
+
// dash offset until dash offset is non-negative.
|
|
333
|
+
let length = 0;
|
|
334
|
+
for (let i = 0; i < dashArray.length; i++) {length += dashArray[i];}
|
|
335
|
+
if (length > 0) {
|
|
336
|
+
while (dashOffset < 0) {
|
|
337
|
+
dashOffset += length;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
doc.dash(dashArray, {phase: dashOffset});
|
|
342
|
+
}
|
|
178
343
|
function docInsertLink(x, y, w, h, url) {
|
|
179
344
|
let ref = doc.ref({
|
|
180
345
|
Type: 'Annot',
|
|
@@ -308,6 +473,11 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
308
473
|
raw = (raw || '').trim();
|
|
309
474
|
if (temp = NamedColors[raw]) {
|
|
310
475
|
result = [temp.slice(), 1];
|
|
476
|
+
} else if (temp = raw.match(/^cmyk\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9.]+)\s*\)$/i)) {
|
|
477
|
+
temp[1] = parseInt(temp[1]); temp[2] = parseInt(temp[2]); temp[3] = parseInt(temp[3]); temp[4] = parseFloat(temp[4]);
|
|
478
|
+
if (temp[1] <= 100 && temp[2] <= 100 && temp[3] <= 100 && temp[4] <= 100) {
|
|
479
|
+
result = [temp.slice(1, 5), 1];
|
|
480
|
+
}
|
|
311
481
|
} else if (temp = raw.match(/^rgba\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9.]+)\s*\)$/i)) {
|
|
312
482
|
temp[1] = parseInt(temp[1]); temp[2] = parseInt(temp[2]); temp[3] = parseInt(temp[3]); temp[4] = parseFloat(temp[4]);
|
|
313
483
|
if (temp[1] < 256 && temp[2] < 256 && temp[3] < 256 && temp[4] <= 1) {
|
|
@@ -367,6 +537,11 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
367
537
|
return new SvgShape().M(0, 0).L(doc.page.width, 0).L(doc.page.width, doc.page.height).L(0, doc.page.height)
|
|
368
538
|
.transform(inverseMatrix(getGlobalMatrix())).getBoundingBox();
|
|
369
539
|
}
|
|
540
|
+
function getPageScale() {
|
|
541
|
+
const bbox = getPageBBox();
|
|
542
|
+
const width = doc.page.width;
|
|
543
|
+
return width / bbox[2];
|
|
544
|
+
}
|
|
370
545
|
function inverseMatrix(m) {
|
|
371
546
|
let dt = m[0] * m[3] - m[1] * m[2];
|
|
372
547
|
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];
|
|
@@ -615,6 +790,7 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
615
790
|
data.push({
|
|
616
791
|
glyph: hex[i],
|
|
617
792
|
unicode: unicode,
|
|
793
|
+
kern: pos[i].advanceWidth - pos[i].xAdvance,
|
|
618
794
|
width: pos[i].advanceWidth * size / 1000,
|
|
619
795
|
xOffset: pos[i].xOffset * size / 1000,
|
|
620
796
|
yOffset: pos[i].yOffset * size / 1000,
|
|
@@ -1266,12 +1442,6 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
1266
1442
|
break;
|
|
1267
1443
|
case 'stroke-dashoffset':
|
|
1268
1444
|
result = this.computeLength(value, this.getViewport());
|
|
1269
|
-
if (result != null) {
|
|
1270
|
-
if (result < 0) { // fix for crbug.com/660850
|
|
1271
|
-
let dasharray = this.get('stroke-dasharray');
|
|
1272
|
-
for (let j = 0; j < dasharray.length; j++) {result += dasharray[j];}
|
|
1273
|
-
}
|
|
1274
|
-
}
|
|
1275
1445
|
break;
|
|
1276
1446
|
}
|
|
1277
1447
|
if (result != null) {return styleCache[key] = result;}
|
|
@@ -1322,7 +1492,7 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
1322
1492
|
this.clip = function() {
|
|
1323
1493
|
if (this.get('clip-path') !== 'none') {
|
|
1324
1494
|
let clipPath = new SvgElemClipPath(this.get('clip-path'), null);
|
|
1325
|
-
clipPath.useMask(this.getBoundingBox());
|
|
1495
|
+
clipPath.useMask((clipPath.attr('clipPathUnits') === 'objectBoundingBox') ? this.getBoundingBox() : null);
|
|
1326
1496
|
return true;
|
|
1327
1497
|
}
|
|
1328
1498
|
};
|
|
@@ -1788,7 +1958,11 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
1788
1958
|
this.drawInDocument = function(isClip, isMask) {
|
|
1789
1959
|
if (this.get('visibility') === 'hidden' || !this.shape) {return;}
|
|
1790
1960
|
doc.save();
|
|
1791
|
-
this.
|
|
1961
|
+
if (this.get('vector-effect') === 'non-scaling-stroke') {
|
|
1962
|
+
this.shape.transform(this.getTransformation());
|
|
1963
|
+
} else {
|
|
1964
|
+
this.transform();
|
|
1965
|
+
}
|
|
1792
1966
|
this.clip();
|
|
1793
1967
|
if (!isClip) {
|
|
1794
1968
|
let masked = this.mask(),
|
|
@@ -1801,6 +1975,11 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
1801
1975
|
stroke = this.getStroke(isClip, isMask),
|
|
1802
1976
|
lineWidth = this.get('stroke-width'),
|
|
1803
1977
|
lineCap = this.get('stroke-linecap');
|
|
1978
|
+
|
|
1979
|
+
if (this.get('vector-effect') === 'non-scaling-stroke') {
|
|
1980
|
+
lineWidth = lineWidth / getPageScale();
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1804
1983
|
if (fill || stroke) {
|
|
1805
1984
|
if (fill) {
|
|
1806
1985
|
docFillColor(fill);
|
|
@@ -1835,8 +2014,8 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
1835
2014
|
doc.lineWidth(lineWidth)
|
|
1836
2015
|
.miterLimit(this.get('stroke-miterlimit'))
|
|
1837
2016
|
.lineJoin(this.get('stroke-linejoin'))
|
|
1838
|
-
.lineCap(lineCap)
|
|
1839
|
-
|
|
2017
|
+
.lineCap(lineCap);
|
|
2018
|
+
docApplyDash(dashArray, dashOffset);
|
|
1840
2019
|
}
|
|
1841
2020
|
for (let j = 0; j < subPaths.length; j++) {
|
|
1842
2021
|
if (subPaths[j].totalLength > 0) {
|
|
@@ -1856,7 +2035,7 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
1856
2035
|
markerEnd = this.get('marker-end');
|
|
1857
2036
|
if (markerStart !== 'none' || markerMid !== 'none' || markerEnd !== 'none') {
|
|
1858
2037
|
let markersPos = this.shape.getMarkers();
|
|
1859
|
-
if (markerStart !== 'none') {
|
|
2038
|
+
if (markerStart !== 'none' && markersPos.length > 0) {
|
|
1860
2039
|
let marker = new SvgElemMarker(markerStart, null);
|
|
1861
2040
|
marker.drawMarker(false, isMask, markersPos[0], lineWidth);
|
|
1862
2041
|
}
|
|
@@ -1866,7 +2045,7 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
1866
2045
|
marker.drawMarker(false, isMask, markersPos[i], lineWidth);
|
|
1867
2046
|
}
|
|
1868
2047
|
}
|
|
1869
|
-
if (markerEnd !== 'none') {
|
|
2048
|
+
if (markerEnd !== 'none' && markersPos.length > 0) {
|
|
1870
2049
|
let marker = new SvgElemMarker(markerEnd, null);
|
|
1871
2050
|
marker.drawMarker(false, isMask, markersPos[markersPos.length - 1], lineWidth);
|
|
1872
2051
|
}
|
|
@@ -2028,6 +2207,7 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
2028
2207
|
this.useMask = function(bBox) {
|
|
2029
2208
|
let group = docBeginGroup(getPageBBox());
|
|
2030
2209
|
doc.save();
|
|
2210
|
+
doc.transform.apply(doc, this.get('transform'));
|
|
2031
2211
|
if (this.attr('clipPathUnits') === 'objectBoundingBox') {
|
|
2032
2212
|
doc.transform(bBox[2] - bBox[0], 0, 0, bBox[3] - bBox[1], bBox[0], bBox[1]);
|
|
2033
2213
|
}
|
|
@@ -2056,7 +2236,6 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
2056
2236
|
w = this.getLength('width', this.getVWidth(), 1.2) * (bBox[2] - bBox[0]);
|
|
2057
2237
|
h = this.getLength('height', this.getVHeight(), 1.2) * (bBox[3] - bBox[1]);
|
|
2058
2238
|
}
|
|
2059
|
-
doc.rect(x, y, w, h).clip();
|
|
2060
2239
|
if (this.attr('maskContentUnits') === 'objectBoundingBox') {
|
|
2061
2240
|
doc.transform(bBox[2] - bBox[0], 0, 0, bBox[3] - bBox[1], bBox[0], bBox[1]);
|
|
2062
2241
|
}
|
|
@@ -2125,18 +2304,12 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
2125
2304
|
doc.lineWidth(strokeWidth)
|
|
2126
2305
|
.miterLimit(this.get('stroke-miterlimit'))
|
|
2127
2306
|
.lineJoin(this.get('stroke-linejoin'))
|
|
2128
|
-
.lineCap(this.get('stroke-linecap'))
|
|
2129
|
-
|
|
2307
|
+
.lineCap(this.get('stroke-linecap'));
|
|
2308
|
+
docApplyDash(this.get('stroke-dasharray'), this.get('stroke-dashoffset'));
|
|
2130
2309
|
}
|
|
2131
2310
|
docBeginText(this._font.font, this._font.size);
|
|
2132
2311
|
docSetTextMode(!!fill, !!stroke);
|
|
2133
|
-
|
|
2134
|
-
if (!pos[j].hidden && isNotEqual(pos[j].width, 0)) {
|
|
2135
|
-
let cos = Math.cos(pos[j].rotate), sin = Math.sin(pos[j].rotate), skew = (this._font.fauxItalic ? -0.25 : 0);
|
|
2136
|
-
docSetTextMatrix(cos * pos[j].scale, sin * pos[j].scale, cos * skew - sin, sin * skew + cos, pos[j].x, pos[j].y);
|
|
2137
|
-
docWriteGlyph(pos[j].glyph);
|
|
2138
|
-
}
|
|
2139
|
-
}
|
|
2312
|
+
docWriteGlyphs(childElem._pos, this._font);
|
|
2140
2313
|
docEndText();
|
|
2141
2314
|
}
|
|
2142
2315
|
break;
|
|
@@ -2157,8 +2330,8 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
2157
2330
|
doc.lineWidth(this.get('stroke-width'))
|
|
2158
2331
|
.miterLimit(this.get('stroke-miterlimit'))
|
|
2159
2332
|
.lineJoin(this.get('stroke-linejoin'))
|
|
2160
|
-
.lineCap(this.get('stroke-linecap'))
|
|
2161
|
-
|
|
2333
|
+
.lineCap(this.get('stroke-linecap'));
|
|
2334
|
+
docApplyDash(this.get('stroke-dasharray'), this.get('stroke-dashoffset'));
|
|
2162
2335
|
}
|
|
2163
2336
|
for (let j = 0, pos = this._pos; j < pos.length; j++) {
|
|
2164
2337
|
if (!pos[j].hidden && isNotEqual(pos[j].width, 0)) {
|
|
@@ -2234,6 +2407,7 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
2234
2407
|
let textScale = length / (endX - startX);
|
|
2235
2408
|
if (textScale > 0 && textScale < Infinity) {
|
|
2236
2409
|
for (let j = 0; j < pos.length; j++) {
|
|
2410
|
+
pos[j].continuous = false;
|
|
2237
2411
|
pos[j].x = startX + textScale * (pos[j].x - startX);
|
|
2238
2412
|
pos[j].scale *= textScale;
|
|
2239
2413
|
pos[j].width *= textScale;
|
|
@@ -2243,6 +2417,7 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
2243
2417
|
if (pos.length >= 2) {
|
|
2244
2418
|
let spaceDiff = (length - (endX - startX)) / (pos.length - 1);
|
|
2245
2419
|
for (let j = 0; j < pos.length; j++) {
|
|
2420
|
+
pos[j].continuous = false;
|
|
2246
2421
|
pos[j].x += j * spaceDiff;
|
|
2247
2422
|
}
|
|
2248
2423
|
}
|
|
@@ -2262,7 +2437,7 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
2262
2437
|
try {
|
|
2263
2438
|
doc.font(fontNameorLink);
|
|
2264
2439
|
} catch(e) {
|
|
2265
|
-
warningCallback('SVGElemText: failed to open font "' + fontNameorLink + '" in PDFKit');
|
|
2440
|
+
warningCallback('SVGElemText: failed to open font "' + fontNameorLink + '" in PDFKit: ' + e.message);
|
|
2266
2441
|
}
|
|
2267
2442
|
currentElem._pos = [];
|
|
2268
2443
|
currentElem._index = 0;
|
|
@@ -2273,7 +2448,22 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
2273
2448
|
letterSpacing = currentElem.get('letter-spacing'),
|
|
2274
2449
|
textAnchor = currentElem.get('text-anchor'),
|
|
2275
2450
|
textDirection = currentElem.get('direction'),
|
|
2276
|
-
|
|
2451
|
+
// `alignment-baseline` and `baseline-shift` have no effect on
|
|
2452
|
+
// `<text>` elements according to the SVG spec. So, detect when
|
|
2453
|
+
// we're styling a `<text>` element and ignore
|
|
2454
|
+
// `alignment-baseline` (only factoring in `dominant-baseline`)
|
|
2455
|
+
// and `baseline-shift` (which can only have the default value of
|
|
2456
|
+
// `baseline`).
|
|
2457
|
+
//
|
|
2458
|
+
// Note that Chrome (as of v99) incorrectly factors in
|
|
2459
|
+
// `alignment-baseline` on `<text>` elements, while Firefox
|
|
2460
|
+
// correctly follows the spec and ignores it. This means that our
|
|
2461
|
+
// output will differ from Chrome's in these cases, but conform to
|
|
2462
|
+
// SVG specification.
|
|
2463
|
+
isTextElem = currentElem.name === 'text',
|
|
2464
|
+
baselineAttr = isTextElem ? currentElem.get('dominant-baseline') : (currentElem.get('alignment-baseline') || currentElem.get('dominant-baseline')),
|
|
2465
|
+
baselineShiftAttr = isTextElem ? 'baseline' : currentElem.get('baseline-shift'),
|
|
2466
|
+
baseline = getBaseline(currentElem._font.font, currentElem._font.size, baselineAttr, baselineShiftAttr);
|
|
2277
2467
|
if (currentElem.name === 'textPath') {
|
|
2278
2468
|
doAnchoring();
|
|
2279
2469
|
currentX = currentY = 0;
|
|
@@ -2313,6 +2503,8 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
2313
2503
|
dyAttr = currentElem._dy[index],
|
|
2314
2504
|
rotAttr = currentElem._rot[index],
|
|
2315
2505
|
continuous = !(w === 0 && j === 0);
|
|
2506
|
+
if (letterSpacing !== 0) {continuous = false}
|
|
2507
|
+
if (wordSpacing !== 0) {continuous = false}
|
|
2316
2508
|
if (xAttr !== undefined) {continuous = false; doAnchoring(); currentX = xAttr;}
|
|
2317
2509
|
if (yAttr !== undefined) {continuous = false; doAnchoring(); currentY = yAttr;}
|
|
2318
2510
|
if (dxAttr !== undefined) {continuous = false; currentX += dxAttr;}
|
|
@@ -2322,6 +2514,7 @@ var SVGtoPDF = function(doc, svg, x, y, options) {
|
|
|
2322
2514
|
glyph: pos[j].glyph,
|
|
2323
2515
|
rotate: (Math.PI / 180) * currentElem.chooseValue(rotAttr, currentElem._defRot),
|
|
2324
2516
|
x: currentX + pos[j].xOffset,
|
|
2517
|
+
kern: pos[j].kern,
|
|
2325
2518
|
y: currentY + baseline + pos[j].yOffset,
|
|
2326
2519
|
width: pos[j].width,
|
|
2327
2520
|
ascent: getAscent(currentElem._font.font, currentElem._font.size),
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import SVGtoPDF from './svg-to-pdfkit/source.js';
|
|
2
|
+
|
|
3
|
+
export default SVGtoPDF;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
class OutputDocument {
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {Promise<object>} pdfDocumentPromise
|
|
5
|
+
*/
|
|
6
|
+
constructor(pdfDocumentPromise) {
|
|
7
|
+
this.bufferSize = 1073741824;
|
|
8
|
+
this.pdfDocumentPromise = pdfDocumentPromise;
|
|
9
|
+
this.bufferPromise = null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @returns {Promise<object>}
|
|
14
|
+
*/
|
|
15
|
+
getStream() {
|
|
16
|
+
return this.pdfDocumentPromise;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @returns {Promise<Buffer>}
|
|
21
|
+
*/
|
|
22
|
+
getBuffer() {
|
|
23
|
+
const getBufferInternal = (async () => {
|
|
24
|
+
const stream = await this.getStream();
|
|
25
|
+
return new Promise((resolve) => {
|
|
26
|
+
let chunks = [];
|
|
27
|
+
stream.on('readable', () => {
|
|
28
|
+
let chunk;
|
|
29
|
+
while ((chunk = stream.read(this.bufferSize)) !== null) {
|
|
30
|
+
chunks.push(chunk);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
stream.on('end', () => {
|
|
34
|
+
resolve(Buffer.concat(chunks));
|
|
35
|
+
});
|
|
36
|
+
stream.end();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (this.bufferPromise === null) {
|
|
41
|
+
this.bufferPromise = getBufferInternal();
|
|
42
|
+
}
|
|
43
|
+
return this.bufferPromise;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @returns {Promise<string>}
|
|
48
|
+
*/
|
|
49
|
+
async getBase64() {
|
|
50
|
+
const buffer = await this.getBuffer();
|
|
51
|
+
return buffer.toString('base64');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @returns {Promise<string>}
|
|
56
|
+
*/
|
|
57
|
+
async getDataUrl() {
|
|
58
|
+
const data = await this.getBase64();
|
|
59
|
+
return 'data:application/pdf;base64,' + data;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default OutputDocument;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import OutputDocument from './OutputDocument';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
|
|
4
|
+
class OutputDocumentServer extends OutputDocument {
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {string} filename
|
|
8
|
+
* @returns {Promise}
|
|
9
|
+
*/
|
|
10
|
+
async write(filename) {
|
|
11
|
+
const stream = await this.getStream();
|
|
12
|
+
const writeStream = fs.createWriteStream(filename);
|
|
13
|
+
|
|
14
|
+
const streamEnded = new Promise((resolve, reject) => {
|
|
15
|
+
stream.on('end', resolve);
|
|
16
|
+
stream.on('error', reject);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const writeClosed = new Promise((resolve, reject) => {
|
|
20
|
+
writeStream.on('close', resolve);
|
|
21
|
+
writeStream.on('error', reject);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
stream.pipe(writeStream);
|
|
25
|
+
stream.end();
|
|
26
|
+
|
|
27
|
+
await Promise.all([streamEnded, writeClosed]);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default OutputDocumentServer;
|