pdfkit 0.15.1 → 0.16.0
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/CHANGELOG.md +21 -0
- package/README.md +2 -2
- package/js/pdfkit.es.js +148 -60
- package/js/pdfkit.es.js.map +1 -1
- package/js/pdfkit.js +146 -58
- package/js/pdfkit.js.map +1 -1
- package/js/pdfkit.standalone.js +35915 -39326
- package/package.json +29 -28
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
## pdfkit changelog
|
|
2
2
|
|
|
3
|
+
### [v0.16.0] - 2024-12-29
|
|
4
|
+
|
|
5
|
+
- Update fontkit to 2.0
|
|
6
|
+
- Update linebreak to 1.1
|
|
7
|
+
- Add support for spot colors
|
|
8
|
+
- Add support to scale text horizontally
|
|
9
|
+
- Add an option to keep the indentation after a new line starts and allow to indent a whole paragraph/text element
|
|
10
|
+
- Add `Name` property for set custom icon for `note()`
|
|
11
|
+
- Fix sets tab order to "Structure" when a document is tagged
|
|
12
|
+
- Fix font cache collision for fonts with missing postscript name or bad TTF metadata or identical metadata for different fonts
|
|
13
|
+
- Fix for embedding fonts into PDF (font name must not contain spaces)
|
|
14
|
+
- Fix measuring text when OpenType features are passed in to .text()
|
|
15
|
+
|
|
16
|
+
### [v0.15.2] - 2024-12-15
|
|
17
|
+
|
|
18
|
+
- Fix index not counting when rendering ordered lists (#1517)
|
|
19
|
+
- Fix PDF/A3 compliance of attachments
|
|
20
|
+
- Fix CIDSet generation only for PDF/A1 subset
|
|
21
|
+
- Fix missing acroform font dictionary
|
|
22
|
+
- Fix modify time comparison check equality embedded files
|
|
23
|
+
|
|
3
24
|
### [v0.15.1] - 2024-10-30
|
|
4
25
|
|
|
5
26
|
- Fix browserify transform sRGB_IEC61966_2_1.icc file
|
package/README.md
CHANGED
|
@@ -128,8 +128,8 @@ complex documents with a very small amount of code. For more, see the `demo` fol
|
|
|
128
128
|
|
|
129
129
|
There are three ways to use PDFKit in the browser:
|
|
130
130
|
|
|
131
|
-
- Use [Browserify](http://browserify.org/). See demo [source code](
|
|
132
|
-
- Use [webpack](https://webpack.js.org/). See [complete example](examples/webpack).
|
|
131
|
+
- Use [Browserify](http://browserify.org/). See demo [source code](https://github.com/foliojs/pdfkit/blob/master/examples/browserify/browser.js) and [build script](https://github.com/foliojs/pdfkit/blob/master/package.json#L62)
|
|
132
|
+
- Use [webpack](https://webpack.js.org/). See [complete example](https://github.com/foliojs/pdfkit/blob/master/examples/webpack).
|
|
133
133
|
- Use prebuilt version. Distributed as `pdfkit.standalone.js` file in the [releases](https://github.com/foliojs/pdfkit/releases) or in the package `js` folder.
|
|
134
134
|
|
|
135
135
|
In addition to PDFKit, you'll need somewhere to stream the output to. HTML5 has a
|
package/js/pdfkit.es.js
CHANGED
|
@@ -2,7 +2,7 @@ import stream from 'stream';
|
|
|
2
2
|
import zlib from 'zlib';
|
|
3
3
|
import CryptoJS from 'crypto-js';
|
|
4
4
|
import fs from 'fs';
|
|
5
|
-
import fontkit from 'fontkit';
|
|
5
|
+
import * as fontkit from 'fontkit';
|
|
6
6
|
import { EventEmitter } from 'events';
|
|
7
7
|
import LineBreaker from 'linebreak';
|
|
8
8
|
import exif from 'jpeg-exif';
|
|
@@ -51,19 +51,39 @@ class PDFTree {
|
|
|
51
51
|
out.push('>>');
|
|
52
52
|
return out.join('\n');
|
|
53
53
|
}
|
|
54
|
-
_compareKeys(
|
|
54
|
+
_compareKeys(/*a, b*/
|
|
55
55
|
) {
|
|
56
56
|
throw new Error('Must be implemented by subclasses');
|
|
57
57
|
}
|
|
58
58
|
_keysName() {
|
|
59
59
|
throw new Error('Must be implemented by subclasses');
|
|
60
60
|
}
|
|
61
|
-
_dataForKey(
|
|
61
|
+
_dataForKey(/*k*/
|
|
62
62
|
) {
|
|
63
63
|
throw new Error('Must be implemented by subclasses');
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
class SpotColor {
|
|
68
|
+
constructor(doc, name, C, M, Y, K) {
|
|
69
|
+
this.id = 'CS' + Object.keys(doc.spotColors).length;
|
|
70
|
+
this.name = name;
|
|
71
|
+
this.values = [C, M, Y, K];
|
|
72
|
+
this.ref = doc.ref(['Separation', this.name, 'DeviceCMYK', {
|
|
73
|
+
Range: [0, 1, 0, 1, 0, 1, 0, 1],
|
|
74
|
+
C0: [0, 0, 0, 0],
|
|
75
|
+
C1: this.values.map(value => value / 100),
|
|
76
|
+
FunctionType: 2,
|
|
77
|
+
Domain: [0, 1],
|
|
78
|
+
N: 1
|
|
79
|
+
}]);
|
|
80
|
+
this.ref.end();
|
|
81
|
+
}
|
|
82
|
+
toString() {
|
|
83
|
+
return `${this.ref.id} 0 R`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
67
87
|
/*
|
|
68
88
|
PDFObject - converts JavaScript types into their corresponding PDF types.
|
|
69
89
|
By Devon Govett
|
|
@@ -136,7 +156,7 @@ class PDFObject {
|
|
|
136
156
|
// Buffers are converted to PDF hex strings
|
|
137
157
|
} else if (Buffer.isBuffer(object)) {
|
|
138
158
|
return `<${object.toString('hex')}>`;
|
|
139
|
-
} else if (object instanceof PDFAbstractReference || object instanceof PDFTree) {
|
|
159
|
+
} else if (object instanceof PDFAbstractReference || object instanceof PDFTree || object instanceof SpotColor) {
|
|
140
160
|
return object.toString();
|
|
141
161
|
} else if (object instanceof Date) {
|
|
142
162
|
let string = `D:${pad(object.getUTCFullYear(), 4)}` + pad(object.getUTCMonth() + 1, 2) + pad(object.getUTCDate(), 2) + pad(object.getUTCHours(), 2) + pad(object.getUTCMinutes(), 2) + pad(object.getUTCSeconds(), 2) + 'Z';
|
|
@@ -191,7 +211,7 @@ class PDFReference extends PDFAbstractReference {
|
|
|
191
211
|
this.buffer = [];
|
|
192
212
|
}
|
|
193
213
|
write(chunk) {
|
|
194
|
-
if (!
|
|
214
|
+
if (!(chunk instanceof Uint8Array)) {
|
|
195
215
|
chunk = Buffer.from(chunk + '\n', 'binary');
|
|
196
216
|
}
|
|
197
217
|
this.uncompressedLength += chunk.length;
|
|
@@ -380,8 +400,20 @@ class PDFPage {
|
|
|
380
400
|
write(chunk) {
|
|
381
401
|
return this.content.write(chunk);
|
|
382
402
|
}
|
|
403
|
+
|
|
404
|
+
// Set tab order if document is tagged for accessibility.
|
|
405
|
+
_setTabOrder() {
|
|
406
|
+
if (!this.dictionary.Tabs && this.document.hasMarkInfoDictionary()) {
|
|
407
|
+
this.dictionary.data.Tabs = 'S';
|
|
408
|
+
}
|
|
409
|
+
}
|
|
383
410
|
end() {
|
|
411
|
+
this._setTabOrder();
|
|
384
412
|
this.dictionary.end();
|
|
413
|
+
this.resources.data.ColorSpace = this.resources.data.ColorSpace || {};
|
|
414
|
+
for (let color of Object.values(this.document.spotColors)) {
|
|
415
|
+
this.resources.data.ColorSpace[color.id] = color;
|
|
416
|
+
}
|
|
385
417
|
this.resources.end();
|
|
386
418
|
return this.content.end();
|
|
387
419
|
}
|
|
@@ -1002,9 +1034,9 @@ function wordArrayToBuffer(wordArray) {
|
|
|
1002
1034
|
const PASSWORD_PADDING = [0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a];
|
|
1003
1035
|
|
|
1004
1036
|
const {
|
|
1005
|
-
number
|
|
1037
|
+
number: number$2
|
|
1006
1038
|
} = PDFObject;
|
|
1007
|
-
class PDFGradient {
|
|
1039
|
+
class PDFGradient$1 {
|
|
1008
1040
|
constructor(doc) {
|
|
1009
1041
|
this.doc = doc;
|
|
1010
1042
|
this.stops = [];
|
|
@@ -1091,7 +1123,7 @@ class PDFGradient {
|
|
|
1091
1123
|
Type: 'Pattern',
|
|
1092
1124
|
PatternType: 2,
|
|
1093
1125
|
Shading: shader,
|
|
1094
|
-
Matrix: this.matrix.map(number)
|
|
1126
|
+
Matrix: this.matrix.map(number$2)
|
|
1095
1127
|
});
|
|
1096
1128
|
pattern.end();
|
|
1097
1129
|
if (this.stops.some(stop => stop[2] < 1)) {
|
|
@@ -1169,7 +1201,7 @@ class PDFGradient {
|
|
|
1169
1201
|
return this.doc.addContent(`/${this.id} ${op}`);
|
|
1170
1202
|
}
|
|
1171
1203
|
}
|
|
1172
|
-
class PDFLinearGradient extends PDFGradient {
|
|
1204
|
+
class PDFLinearGradient$1 extends PDFGradient$1 {
|
|
1173
1205
|
constructor(doc, x1, y1, x2, y2) {
|
|
1174
1206
|
super(doc);
|
|
1175
1207
|
this.x1 = x1;
|
|
@@ -1187,10 +1219,10 @@ class PDFLinearGradient extends PDFGradient {
|
|
|
1187
1219
|
});
|
|
1188
1220
|
}
|
|
1189
1221
|
opacityGradient() {
|
|
1190
|
-
return new PDFLinearGradient(this.doc, this.x1, this.y1, this.x2, this.y2);
|
|
1222
|
+
return new PDFLinearGradient$1(this.doc, this.x1, this.y1, this.x2, this.y2);
|
|
1191
1223
|
}
|
|
1192
1224
|
}
|
|
1193
|
-
class PDFRadialGradient extends PDFGradient {
|
|
1225
|
+
class PDFRadialGradient$1 extends PDFGradient$1 {
|
|
1194
1226
|
constructor(doc, x1, y1, r1, x2, y2, r2) {
|
|
1195
1227
|
super(doc);
|
|
1196
1228
|
this.doc = doc;
|
|
@@ -1211,13 +1243,13 @@ class PDFRadialGradient extends PDFGradient {
|
|
|
1211
1243
|
});
|
|
1212
1244
|
}
|
|
1213
1245
|
opacityGradient() {
|
|
1214
|
-
return new PDFRadialGradient(this.doc, this.x1, this.y1, this.r1, this.x2, this.y2, this.r2);
|
|
1246
|
+
return new PDFRadialGradient$1(this.doc, this.x1, this.y1, this.r1, this.x2, this.y2, this.r2);
|
|
1215
1247
|
}
|
|
1216
1248
|
}
|
|
1217
1249
|
var Gradient = {
|
|
1218
|
-
PDFGradient,
|
|
1219
|
-
PDFLinearGradient,
|
|
1220
|
-
PDFRadialGradient
|
|
1250
|
+
PDFGradient: PDFGradient$1,
|
|
1251
|
+
PDFLinearGradient: PDFLinearGradient$1,
|
|
1252
|
+
PDFRadialGradient: PDFRadialGradient$1
|
|
1221
1253
|
};
|
|
1222
1254
|
|
|
1223
1255
|
/*
|
|
@@ -1225,7 +1257,7 @@ PDF tiling pattern support. Uncolored only.
|
|
|
1225
1257
|
*/
|
|
1226
1258
|
|
|
1227
1259
|
const underlyingColorSpaces = ['DeviceCMYK', 'DeviceRGB'];
|
|
1228
|
-
class PDFTilingPattern {
|
|
1260
|
+
class PDFTilingPattern$1 {
|
|
1229
1261
|
constructor(doc, bBox, xStep, yStep, stream) {
|
|
1230
1262
|
this.doc = doc;
|
|
1231
1263
|
this.bBox = bBox;
|
|
@@ -1303,19 +1335,20 @@ class PDFTilingPattern {
|
|
|
1303
1335
|
}
|
|
1304
1336
|
}
|
|
1305
1337
|
var pattern = {
|
|
1306
|
-
PDFTilingPattern
|
|
1338
|
+
PDFTilingPattern: PDFTilingPattern$1
|
|
1307
1339
|
};
|
|
1308
1340
|
|
|
1309
1341
|
const {
|
|
1310
|
-
PDFGradient
|
|
1311
|
-
PDFLinearGradient
|
|
1312
|
-
PDFRadialGradient
|
|
1342
|
+
PDFGradient,
|
|
1343
|
+
PDFLinearGradient,
|
|
1344
|
+
PDFRadialGradient
|
|
1313
1345
|
} = Gradient;
|
|
1314
1346
|
const {
|
|
1315
|
-
PDFTilingPattern
|
|
1347
|
+
PDFTilingPattern
|
|
1316
1348
|
} = pattern;
|
|
1317
1349
|
var ColorMixin = {
|
|
1318
1350
|
initColor() {
|
|
1351
|
+
this.spotColors = {};
|
|
1319
1352
|
// The opacity dictionaries
|
|
1320
1353
|
this._opacityRegistry = {};
|
|
1321
1354
|
this._opacityCount = 0;
|
|
@@ -1332,6 +1365,8 @@ var ColorMixin = {
|
|
|
1332
1365
|
color = [hex >> 16, hex >> 8 & 0xff, hex & 0xff];
|
|
1333
1366
|
} else if (namedColors[color]) {
|
|
1334
1367
|
color = namedColors[color];
|
|
1368
|
+
} else if (this.spotColors[color]) {
|
|
1369
|
+
return this.spotColors[color];
|
|
1335
1370
|
}
|
|
1336
1371
|
}
|
|
1337
1372
|
if (Array.isArray(color)) {
|
|
@@ -1347,11 +1382,11 @@ var ColorMixin = {
|
|
|
1347
1382
|
return null;
|
|
1348
1383
|
},
|
|
1349
1384
|
_setColor(color, stroke) {
|
|
1350
|
-
if (color instanceof PDFGradient
|
|
1385
|
+
if (color instanceof PDFGradient) {
|
|
1351
1386
|
color.apply(stroke);
|
|
1352
1387
|
return true;
|
|
1353
1388
|
// see if tiling pattern, decode & apply it it
|
|
1354
|
-
} else if (Array.isArray(color) && color[0] instanceof PDFTilingPattern
|
|
1389
|
+
} else if (Array.isArray(color) && color[0] instanceof PDFTilingPattern) {
|
|
1355
1390
|
color[0].apply(stroke, color[1]);
|
|
1356
1391
|
return true;
|
|
1357
1392
|
}
|
|
@@ -1366,8 +1401,12 @@ var ColorMixin = {
|
|
|
1366
1401
|
const op = stroke ? 'SCN' : 'scn';
|
|
1367
1402
|
const space = this._getColorSpace(color);
|
|
1368
1403
|
this._setColorSpace(space, stroke);
|
|
1369
|
-
color
|
|
1370
|
-
|
|
1404
|
+
if (color instanceof SpotColor) {
|
|
1405
|
+
this.page.colorSpaces[color.id] = color.ref;
|
|
1406
|
+
this.addContent(`1 ${op}`);
|
|
1407
|
+
} else {
|
|
1408
|
+
this.addContent(`${color.join(' ')} ${op}`);
|
|
1409
|
+
}
|
|
1371
1410
|
return true;
|
|
1372
1411
|
},
|
|
1373
1412
|
_setColorSpace(space, stroke) {
|
|
@@ -1375,6 +1414,9 @@ var ColorMixin = {
|
|
|
1375
1414
|
return this.addContent(`/${space} ${op}`);
|
|
1376
1415
|
},
|
|
1377
1416
|
_getColorSpace(color) {
|
|
1417
|
+
if (color instanceof SpotColor) {
|
|
1418
|
+
return color.id;
|
|
1419
|
+
}
|
|
1378
1420
|
return color.length === 4 ? 'DeviceCMYK' : 'DeviceRGB';
|
|
1379
1421
|
},
|
|
1380
1422
|
fillColor(color, opacity) {
|
|
@@ -1441,13 +1483,18 @@ var ColorMixin = {
|
|
|
1441
1483
|
return this.addContent(`/${name} gs`);
|
|
1442
1484
|
},
|
|
1443
1485
|
linearGradient(x1, y1, x2, y2) {
|
|
1444
|
-
return new PDFLinearGradient
|
|
1486
|
+
return new PDFLinearGradient(this, x1, y1, x2, y2);
|
|
1445
1487
|
},
|
|
1446
1488
|
radialGradient(x1, y1, r1, x2, y2, r2) {
|
|
1447
|
-
return new PDFRadialGradient
|
|
1489
|
+
return new PDFRadialGradient(this, x1, y1, r1, x2, y2, r2);
|
|
1448
1490
|
},
|
|
1449
1491
|
pattern(bbox, xStep, yStep, stream) {
|
|
1450
|
-
return new PDFTilingPattern
|
|
1492
|
+
return new PDFTilingPattern(this, bbox, xStep, yStep, stream);
|
|
1493
|
+
},
|
|
1494
|
+
addSpotColor(name, C, M, Y, K) {
|
|
1495
|
+
const color = new SpotColor(this, name, C, M, Y, K);
|
|
1496
|
+
this.spotColors[name] = color;
|
|
1497
|
+
return this;
|
|
1451
1498
|
}
|
|
1452
1499
|
};
|
|
1453
1500
|
var namedColors = {
|
|
@@ -2693,7 +2740,7 @@ class EmbeddedFont extends PDFFont {
|
|
|
2693
2740
|
if (isCFF) {
|
|
2694
2741
|
fontFile.data.Subtype = 'CIDFontType0C';
|
|
2695
2742
|
}
|
|
2696
|
-
|
|
2743
|
+
fontFile.end(this.subset.encode());
|
|
2697
2744
|
const familyClass = ((this.font['OS/2'] != null ? this.font['OS/2'].sFamilyClass : undefined) || 0) >> 8;
|
|
2698
2745
|
let flags = 0;
|
|
2699
2746
|
if (this.font.post.isFixedPitch) {
|
|
@@ -2712,7 +2759,7 @@ class EmbeddedFont extends PDFFont {
|
|
|
2712
2759
|
|
|
2713
2760
|
// generate a tag (6 uppercase letters. 17 is the char code offset from '0' to 'A'. 73 will map to 'Z')
|
|
2714
2761
|
const tag = [1, 2, 3, 4, 5, 6].map(i => String.fromCharCode((this.id.charCodeAt(i) || 73) + 17)).join('');
|
|
2715
|
-
const name = tag + '+' + this.font.postscriptName;
|
|
2762
|
+
const name = tag + '+' + this.font.postscriptName.replaceAll(' ', '_');
|
|
2716
2763
|
const {
|
|
2717
2764
|
bbox
|
|
2718
2765
|
} = this.font;
|
|
@@ -2734,7 +2781,7 @@ class EmbeddedFont extends PDFFont {
|
|
|
2734
2781
|
} else {
|
|
2735
2782
|
descriptor.data.FontFile2 = fontFile;
|
|
2736
2783
|
}
|
|
2737
|
-
if (this.document.subset) {
|
|
2784
|
+
if (this.document.subset && this.document.subset === 1) {
|
|
2738
2785
|
const CIDSet = Buffer.from('FFFFFFFFC0', 'hex');
|
|
2739
2786
|
const CIDSetRef = this.document.ref();
|
|
2740
2787
|
CIDSetRef.write(CIDSet);
|
|
@@ -2834,12 +2881,10 @@ class PDFFontFactory {
|
|
|
2834
2881
|
}
|
|
2835
2882
|
src = fs.readFileSync(src);
|
|
2836
2883
|
}
|
|
2837
|
-
if (
|
|
2884
|
+
if (src instanceof Uint8Array) {
|
|
2838
2885
|
font = fontkit.create(src, family);
|
|
2839
|
-
} else if (src instanceof Uint8Array) {
|
|
2840
|
-
font = fontkit.create(Buffer.from(src), family);
|
|
2841
2886
|
} else if (src instanceof ArrayBuffer) {
|
|
2842
|
-
font = fontkit.create(
|
|
2887
|
+
font = fontkit.create(new Uint8Array(src), family);
|
|
2843
2888
|
}
|
|
2844
2889
|
if (font == null) {
|
|
2845
2890
|
throw new Error('Not a supported font format or standard PDF font.');
|
|
@@ -2848,6 +2893,18 @@ class PDFFontFactory {
|
|
|
2848
2893
|
}
|
|
2849
2894
|
}
|
|
2850
2895
|
|
|
2896
|
+
const isEqualFont = (font1, font2) => {
|
|
2897
|
+
// compare font checksum
|
|
2898
|
+
if (font1.font._tables?.head?.checkSumAdjustment !== font2.font._tables?.head?.checkSumAdjustment) {
|
|
2899
|
+
return false;
|
|
2900
|
+
}
|
|
2901
|
+
|
|
2902
|
+
// compare font name table
|
|
2903
|
+
if (JSON.stringify(font1.font._tables?.name?.records) !== JSON.stringify(font2.font._tables?.name?.records)) {
|
|
2904
|
+
return false;
|
|
2905
|
+
}
|
|
2906
|
+
return true;
|
|
2907
|
+
};
|
|
2851
2908
|
var FontsMixin = {
|
|
2852
2909
|
initFonts() {
|
|
2853
2910
|
let defaultFont = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Helvetica';
|
|
@@ -2901,7 +2958,7 @@ var FontsMixin = {
|
|
|
2901
2958
|
|
|
2902
2959
|
// check for existing font familes with the same name already in the PDF
|
|
2903
2960
|
// useful if the font was passed as a buffer
|
|
2904
|
-
if (font = this._fontFamilies[this._font.name]) {
|
|
2961
|
+
if ((font = this._fontFamilies[this._font.name]) && isEqualFont(this._font, font)) {
|
|
2905
2962
|
this._font = font;
|
|
2906
2963
|
return this;
|
|
2907
2964
|
}
|
|
@@ -2940,12 +2997,13 @@ class LineWrapper extends EventEmitter {
|
|
|
2940
2997
|
constructor(document, options) {
|
|
2941
2998
|
super();
|
|
2942
2999
|
this.document = document;
|
|
2943
|
-
this.
|
|
2944
|
-
this.
|
|
2945
|
-
this.
|
|
3000
|
+
this.horizontalScaling = options.horizontalScaling || 100;
|
|
3001
|
+
this.indent = (options.indent || 0) * this.horizontalScaling / 100;
|
|
3002
|
+
this.characterSpacing = (options.characterSpacing || 0) * this.horizontalScaling / 100;
|
|
3003
|
+
this.wordSpacing = (options.wordSpacing === 0) * this.horizontalScaling / 100;
|
|
2946
3004
|
this.columns = options.columns || 1;
|
|
2947
|
-
this.columnGap = options.columnGap != null ? options.columnGap : 18; // 1/4 inch
|
|
2948
|
-
this.lineWidth = (options.width - this.columnGap * (this.columns - 1)) / this.columns;
|
|
3005
|
+
this.columnGap = (options.columnGap != null ? options.columnGap : 18) * this.horizontalScaling / 100; // 1/4 inch
|
|
3006
|
+
this.lineWidth = (options.width * this.horizontalScaling / 100 - this.columnGap * (this.columns - 1)) / this.columns;
|
|
2949
3007
|
this.spaceLeft = this.lineWidth;
|
|
2950
3008
|
this.startX = this.document.x;
|
|
2951
3009
|
this.startY = this.document.y;
|
|
@@ -2970,6 +3028,14 @@ class LineWrapper extends EventEmitter {
|
|
|
2970
3028
|
const indent = this.continuedX || this.indent;
|
|
2971
3029
|
this.document.x += indent;
|
|
2972
3030
|
this.lineWidth -= indent;
|
|
3031
|
+
|
|
3032
|
+
// if indentAllLines is set to true
|
|
3033
|
+
// we're not resetting the indentation for this paragraph after the first line
|
|
3034
|
+
if (options.indentAllLines) {
|
|
3035
|
+
return;
|
|
3036
|
+
}
|
|
3037
|
+
|
|
3038
|
+
// otherwise we start the next line without indent
|
|
2973
3039
|
return this.once('line', () => {
|
|
2974
3040
|
this.document.x -= indent;
|
|
2975
3041
|
this.lineWidth += indent;
|
|
@@ -3080,14 +3146,15 @@ class LineWrapper extends EventEmitter {
|
|
|
3080
3146
|
}
|
|
3081
3147
|
wrap(text, options) {
|
|
3082
3148
|
// override options from previous continued fragments
|
|
3149
|
+
this.horizontalScaling = options.horizontalScaling || 100;
|
|
3083
3150
|
if (options.indent != null) {
|
|
3084
|
-
this.indent = options.indent;
|
|
3151
|
+
this.indent = options.indent * this.horizontalScaling / 100;
|
|
3085
3152
|
}
|
|
3086
3153
|
if (options.characterSpacing != null) {
|
|
3087
|
-
this.characterSpacing = options.characterSpacing;
|
|
3154
|
+
this.characterSpacing = options.characterSpacing * this.horizontalScaling / 100;
|
|
3088
3155
|
}
|
|
3089
3156
|
if (options.wordSpacing != null) {
|
|
3090
|
-
this.wordSpacing = options.wordSpacing;
|
|
3157
|
+
this.wordSpacing = options.wordSpacing * this.horizontalScaling / 100;
|
|
3091
3158
|
}
|
|
3092
3159
|
if (options.ellipsis != null) {
|
|
3093
3160
|
this.ellipsis = options.ellipsis;
|
|
@@ -3245,7 +3312,7 @@ class LineWrapper extends EventEmitter {
|
|
|
3245
3312
|
}
|
|
3246
3313
|
|
|
3247
3314
|
const {
|
|
3248
|
-
number
|
|
3315
|
+
number
|
|
3249
3316
|
} = PDFObject;
|
|
3250
3317
|
var TextMixin = {
|
|
3251
3318
|
initText() {
|
|
@@ -3315,7 +3382,8 @@ var TextMixin = {
|
|
|
3315
3382
|
},
|
|
3316
3383
|
widthOfString(string) {
|
|
3317
3384
|
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
3318
|
-
|
|
3385
|
+
const horizontalScaling = options.horizontalScaling || 100;
|
|
3386
|
+
return (this._font.widthOfString(string, this._fontSize, options.features) + (options.characterSpacing || 0) * (string.length - 1)) * horizontalScaling / 100;
|
|
3319
3387
|
},
|
|
3320
3388
|
heightOfString(text, options) {
|
|
3321
3389
|
const {
|
|
@@ -3375,11 +3443,10 @@ var TextMixin = {
|
|
|
3375
3443
|
return `${text}.`;
|
|
3376
3444
|
}
|
|
3377
3445
|
};
|
|
3378
|
-
const drawListItem = function (listItem) {
|
|
3446
|
+
const drawListItem = function (listItem, i) {
|
|
3379
3447
|
wrapper = new LineWrapper(this, options);
|
|
3380
3448
|
wrapper.on('line', this._line);
|
|
3381
3449
|
level = 1;
|
|
3382
|
-
let i = 0;
|
|
3383
3450
|
wrapper.once('firstLine', () => {
|
|
3384
3451
|
let item, itemType, labelType, bodyType;
|
|
3385
3452
|
if (options.structParent) {
|
|
@@ -3436,7 +3503,7 @@ var TextMixin = {
|
|
|
3436
3503
|
wrapper.wrap(listItem, options);
|
|
3437
3504
|
};
|
|
3438
3505
|
for (let i = 0; i < items.length; i++) {
|
|
3439
|
-
drawListItem.call(this, items[i]);
|
|
3506
|
+
drawListItem.call(this, items[i], i);
|
|
3440
3507
|
}
|
|
3441
3508
|
return this;
|
|
3442
3509
|
},
|
|
@@ -3494,7 +3561,7 @@ var TextMixin = {
|
|
|
3494
3561
|
this._fragment(text, this.x, this.y, options);
|
|
3495
3562
|
const lineGap = options.lineGap || this._lineGap || 0;
|
|
3496
3563
|
if (!wrapper) {
|
|
3497
|
-
return this.x += this.widthOfString(text);
|
|
3564
|
+
return this.x += this.widthOfString(text, options);
|
|
3498
3565
|
} else {
|
|
3499
3566
|
return this.y += this.currentLineHeight(true) + lineGap;
|
|
3500
3567
|
}
|
|
@@ -3510,6 +3577,7 @@ var TextMixin = {
|
|
|
3510
3577
|
const align = options.align || 'left';
|
|
3511
3578
|
let wordSpacing = options.wordSpacing || 0;
|
|
3512
3579
|
const characterSpacing = options.characterSpacing || 0;
|
|
3580
|
+
const horizontalScaling = options.horizontalScaling || 100;
|
|
3513
3581
|
|
|
3514
3582
|
// text alignments
|
|
3515
3583
|
if (options.width) {
|
|
@@ -3636,10 +3704,10 @@ var TextMixin = {
|
|
|
3636
3704
|
this.addContent('BT');
|
|
3637
3705
|
|
|
3638
3706
|
// text position
|
|
3639
|
-
this.addContent(`1 0 0 1 ${number
|
|
3707
|
+
this.addContent(`1 0 0 1 ${number(x)} ${number(y)} Tm`);
|
|
3640
3708
|
|
|
3641
3709
|
// font and font size
|
|
3642
|
-
this.addContent(`/${this._font.id} ${number
|
|
3710
|
+
this.addContent(`/${this._font.id} ${number(this._fontSize)} Tf`);
|
|
3643
3711
|
|
|
3644
3712
|
// rendering mode
|
|
3645
3713
|
const mode = options.fill && options.stroke ? 2 : options.stroke ? 1 : 0;
|
|
@@ -3649,7 +3717,12 @@ var TextMixin = {
|
|
|
3649
3717
|
|
|
3650
3718
|
// Character spacing
|
|
3651
3719
|
if (characterSpacing) {
|
|
3652
|
-
this.addContent(`${number
|
|
3720
|
+
this.addContent(`${number(characterSpacing)} Tc`);
|
|
3721
|
+
}
|
|
3722
|
+
|
|
3723
|
+
// Horizontal scaling
|
|
3724
|
+
if (horizontalScaling !== 100) {
|
|
3725
|
+
this.addContent(`${horizontalScaling} Tz`);
|
|
3653
3726
|
}
|
|
3654
3727
|
|
|
3655
3728
|
// Add the actual text
|
|
@@ -3691,7 +3764,7 @@ var TextMixin = {
|
|
|
3691
3764
|
if (last < cur) {
|
|
3692
3765
|
const hex = encoded.slice(last, cur).join('');
|
|
3693
3766
|
const advance = positions[cur - 1].xAdvance - positions[cur - 1].advanceWidth;
|
|
3694
|
-
commands.push(`<${hex}> ${number
|
|
3767
|
+
commands.push(`<${hex}> ${number(-advance)}`);
|
|
3695
3768
|
}
|
|
3696
3769
|
return last = cur;
|
|
3697
3770
|
};
|
|
@@ -3713,13 +3786,13 @@ var TextMixin = {
|
|
|
3713
3786
|
flush(i);
|
|
3714
3787
|
|
|
3715
3788
|
// Move the text position and flush just the current character
|
|
3716
|
-
this.addContent(`1 0 0 1 ${number
|
|
3789
|
+
this.addContent(`1 0 0 1 ${number(x + pos.xOffset * scale)} ${number(y + pos.yOffset * scale)} Tm`);
|
|
3717
3790
|
flush(i + 1);
|
|
3718
3791
|
hadOffset = true;
|
|
3719
3792
|
} else {
|
|
3720
3793
|
// If the last character had an offset, reset the text position
|
|
3721
3794
|
if (hadOffset) {
|
|
3722
|
-
this.addContent(`1 0 0 1 ${number
|
|
3795
|
+
this.addContent(`1 0 0 1 ${number(x)} ${number(y)} Tm`);
|
|
3723
3796
|
hadOffset = false;
|
|
3724
3797
|
}
|
|
3725
3798
|
|
|
@@ -4224,7 +4297,9 @@ var AnnotationsMixin = {
|
|
|
4224
4297
|
let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
4225
4298
|
options.Subtype = 'Text';
|
|
4226
4299
|
options.Contents = new String(contents);
|
|
4227
|
-
options.Name
|
|
4300
|
+
if (options.Name == null) {
|
|
4301
|
+
options.Name = 'Comment';
|
|
4302
|
+
}
|
|
4228
4303
|
if (options.color == null) {
|
|
4229
4304
|
options.color = [243, 223, 92];
|
|
4230
4305
|
}
|
|
@@ -4749,6 +4824,9 @@ var MarkingsMixin = {
|
|
|
4749
4824
|
}
|
|
4750
4825
|
return this._root.data.MarkInfo;
|
|
4751
4826
|
},
|
|
4827
|
+
hasMarkInfoDictionary() {
|
|
4828
|
+
return !!this._root.data.MarkInfo;
|
|
4829
|
+
},
|
|
4752
4830
|
getStructTreeRoot() {
|
|
4753
4831
|
if (!this._root.data.StructTreeRoot) {
|
|
4754
4832
|
this._root.data.StructTreeRoot = this.ref({
|
|
@@ -5088,7 +5166,7 @@ var AcroFormMixin = {
|
|
|
5088
5166
|
},
|
|
5089
5167
|
_resolveFont(options) {
|
|
5090
5168
|
// add current font to document-level AcroForm dict if necessary
|
|
5091
|
-
if (this._acroform.fonts[this._font.id]
|
|
5169
|
+
if (this._acroform.fonts[this._font.id] == null) {
|
|
5092
5170
|
this._acroform.fonts[this._font.id] = this._font.ref();
|
|
5093
5171
|
}
|
|
5094
5172
|
|
|
@@ -5160,11 +5238,13 @@ var AttachmentsMixin = {
|
|
|
5160
5238
|
* * options.hidden: if true, do not add attachment to EmbeddedFiles dictionary. Useful for file attachment annotations
|
|
5161
5239
|
* * options.creationDate: override creation date
|
|
5162
5240
|
* * options.modifiedDate: override modified date
|
|
5241
|
+
* * options.relationship: Relationship between the PDF document and its attached file. Can be 'Alternative', 'Data', 'Source', 'Supplement' or 'Unspecified'.
|
|
5163
5242
|
* @returns filespec reference
|
|
5164
5243
|
*/
|
|
5165
5244
|
file(src) {
|
|
5166
5245
|
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
5167
5246
|
options.name = options.name || src;
|
|
5247
|
+
options.relationship = options.relationship || 'Unspecified';
|
|
5168
5248
|
const refBody = {
|
|
5169
5249
|
Type: 'EmbeddedFile',
|
|
5170
5250
|
Params: {}
|
|
@@ -5235,6 +5315,7 @@ var AttachmentsMixin = {
|
|
|
5235
5315
|
// add filespec for embedded file
|
|
5236
5316
|
const fileSpecBody = {
|
|
5237
5317
|
Type: 'Filespec',
|
|
5318
|
+
AFRelationship: options.relationship,
|
|
5238
5319
|
F: new String(options.name),
|
|
5239
5320
|
EF: {
|
|
5240
5321
|
F: ref
|
|
@@ -5249,13 +5330,20 @@ var AttachmentsMixin = {
|
|
|
5249
5330
|
if (!options.hidden) {
|
|
5250
5331
|
this.addNamedEmbeddedFile(options.name, filespec);
|
|
5251
5332
|
}
|
|
5333
|
+
|
|
5334
|
+
// Add file to the catalogue to be PDF/A3 compliant
|
|
5335
|
+
if (this._root.data.AF) {
|
|
5336
|
+
this._root.data.AF.push(filespec);
|
|
5337
|
+
} else {
|
|
5338
|
+
this._root.data.AF = [filespec];
|
|
5339
|
+
}
|
|
5252
5340
|
return filespec;
|
|
5253
5341
|
}
|
|
5254
5342
|
};
|
|
5255
5343
|
|
|
5256
5344
|
/** check two embedded file metadata objects for equality */
|
|
5257
5345
|
function isEqual(a, b) {
|
|
5258
|
-
return a.Subtype === b.Subtype && a.Params.CheckSum.toString() === b.Params.CheckSum.toString() && a.Params.Size === b.Params.Size && a.Params.CreationDate.getTime() === b.Params.CreationDate.getTime() && a.Params.ModDate.getTime() === b.Params.ModDate.getTime();
|
|
5346
|
+
return a.Subtype === b.Subtype && a.Params.CheckSum.toString() === b.Params.CheckSum.toString() && a.Params.Size === b.Params.Size && a.Params.CreationDate.getTime() === b.Params.CreationDate.getTime() && (a.Params.ModDate === undefined && b.Params.ModDate === undefined || a.Params.ModDate.getTime() === b.Params.ModDate.getTime());
|
|
5259
5347
|
}
|
|
5260
5348
|
|
|
5261
5349
|
var PDFA = {
|
|
@@ -5784,5 +5872,5 @@ mixin(AttachmentsMixin);
|
|
|
5784
5872
|
mixin(SubsetMixin);
|
|
5785
5873
|
PDFDocument.LineWrapper = LineWrapper;
|
|
5786
5874
|
|
|
5787
|
-
export default
|
|
5875
|
+
export { PDFDocument as default };
|
|
5788
5876
|
//# sourceMappingURL=pdfkit.es.js.map
|