pdfkit 0.12.3 → 0.14.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.
@@ -405,6 +405,11 @@ class PDFPage {
405
405
  return data.Pattern != null ? data.Pattern : data.Pattern = {};
406
406
  }
407
407
 
408
+ get colorSpaces() {
409
+ var data = this.resources.data;
410
+ return data.ColorSpace || (data.ColorSpace = {});
411
+ }
412
+
408
413
  get annotations() {
409
414
  var data = this.dictionary.data;
410
415
  return data.Annots != null ? data.Annots : data.Annots = [];
@@ -1478,7 +1483,7 @@ class PDFGradient {
1478
1483
  return pattern;
1479
1484
  }
1480
1485
 
1481
- apply(op) {
1486
+ apply(stroke) {
1482
1487
  // apply gradient transform to existing document ctm
1483
1488
  var [m0, m1, m2, m3, m4, m5] = this.doc._ctm;
1484
1489
  var [m11, m12, m21, m22, dx, dy] = this.transform;
@@ -1488,6 +1493,9 @@ class PDFGradient {
1488
1493
  this.embed(m);
1489
1494
  }
1490
1495
 
1496
+ this.doc._setColorSpace('Pattern', stroke);
1497
+
1498
+ var op = stroke ? 'SCN' : 'scn';
1491
1499
  return this.doc.addContent("/".concat(this.id, " ").concat(op));
1492
1500
  }
1493
1501
 
@@ -1552,24 +1560,119 @@ var Gradient = {
1552
1560
  PDFRadialGradient
1553
1561
  };
1554
1562
 
1563
+ /*
1564
+ PDF tiling pattern support. Uncolored only.
1565
+ */
1566
+ var underlyingColorSpaces = ['DeviceCMYK', 'DeviceRGB'];
1567
+
1568
+ class PDFTilingPattern {
1569
+ constructor(doc, bBox, xStep, yStep, stream) {
1570
+ this.doc = doc;
1571
+ this.bBox = bBox;
1572
+ this.xStep = xStep;
1573
+ this.yStep = yStep;
1574
+ this.stream = stream;
1575
+ }
1576
+
1577
+ createPattern() {
1578
+ // no resources needed for our current usage
1579
+ // required entry
1580
+ var resources = this.doc.ref();
1581
+ resources.end(); // apply default transform matrix (flipped in the default doc._ctm)
1582
+ // see document.js & gradient.js
1583
+
1584
+ var [m0, m1, m2, m3, m4, m5] = this.doc._ctm;
1585
+ var [m11, m12, m21, m22, dx, dy] = [1, 0, 0, 1, 0, 0];
1586
+ var m = [m0 * m11 + m2 * m12, m1 * m11 + m3 * m12, m0 * m21 + m2 * m22, m1 * m21 + m3 * m22, m0 * dx + m2 * dy + m4, m1 * dx + m3 * dy + m5];
1587
+ var pattern = this.doc.ref({
1588
+ Type: 'Pattern',
1589
+ PatternType: 1,
1590
+ // tiling
1591
+ PaintType: 2,
1592
+ // 1-colored, 2-uncolored
1593
+ TilingType: 2,
1594
+ // 2-no distortion
1595
+ BBox: this.bBox,
1596
+ XStep: this.xStep,
1597
+ YStep: this.yStep,
1598
+ Matrix: m.map(v => +v.toFixed(5)),
1599
+ Resources: resources
1600
+ });
1601
+ pattern.end(this.stream);
1602
+ return pattern;
1603
+ }
1604
+
1605
+ embedPatternColorSpaces() {
1606
+ // map each pattern to an underlying color space
1607
+ // and embed on each page
1608
+ underlyingColorSpaces.forEach(csName => {
1609
+ var csId = this.getPatternColorSpaceId(csName);
1610
+ if (this.doc.page.colorSpaces[csId]) return;
1611
+ var cs = this.doc.ref(['Pattern', csName]);
1612
+ cs.end();
1613
+ this.doc.page.colorSpaces[csId] = cs;
1614
+ });
1615
+ }
1616
+
1617
+ getPatternColorSpaceId(underlyingColorspace) {
1618
+ return "CsP".concat(underlyingColorspace);
1619
+ }
1620
+
1621
+ embed() {
1622
+ if (!this.id) {
1623
+ this.doc._patternCount = this.doc._patternCount + 1;
1624
+ this.id = 'P' + this.doc._patternCount;
1625
+ this.pattern = this.createPattern();
1626
+ } // patterns are embedded in each page
1627
+
1628
+
1629
+ if (!this.doc.page.patterns[this.id]) {
1630
+ this.doc.page.patterns[this.id] = this.pattern;
1631
+ }
1632
+ }
1633
+
1634
+ apply(stroke, patternColor) {
1635
+ // do any embedding/creating that might be needed
1636
+ this.embedPatternColorSpaces();
1637
+ this.embed();
1638
+
1639
+ var normalizedColor = this.doc._normalizeColor(patternColor);
1640
+
1641
+ if (!normalizedColor) throw Error("invalid pattern color. (value: ".concat(patternColor, ")")); // select one of the pattern color spaces
1642
+
1643
+ var csId = this.getPatternColorSpaceId(this.doc._getColorSpace(normalizedColor));
1644
+
1645
+ this.doc._setColorSpace(csId, stroke); // stroke/fill using the pattern and color (in the above underlying color space)
1646
+
1647
+
1648
+ var op = stroke ? 'SCN' : 'scn';
1649
+ return this.doc.addContent("".concat(normalizedColor.join(' '), " /").concat(this.id, " ").concat(op));
1650
+ }
1651
+
1652
+ }
1653
+
1654
+ var pattern = {
1655
+ PDFTilingPattern
1656
+ };
1657
+
1555
1658
  var {
1556
1659
  PDFGradient: PDFGradient$1,
1557
1660
  PDFLinearGradient: PDFLinearGradient$1,
1558
1661
  PDFRadialGradient: PDFRadialGradient$1
1559
1662
  } = Gradient;
1663
+ var {
1664
+ PDFTilingPattern: PDFTilingPattern$1
1665
+ } = pattern;
1560
1666
  var ColorMixin = {
1561
1667
  initColor() {
1562
1668
  // The opacity dictionaries
1563
1669
  this._opacityRegistry = {};
1564
1670
  this._opacityCount = 0;
1671
+ this._patternCount = 0;
1565
1672
  return this._gradCount = 0;
1566
1673
  },
1567
1674
 
1568
1675
  _normalizeColor(color) {
1569
- if (color instanceof PDFGradient$1) {
1570
- return color;
1571
- }
1572
-
1573
1676
  if (typeof color === 'string') {
1574
1677
  if (color.charAt(0) === '#') {
1575
1678
  if (color.length === 4) {
@@ -1598,6 +1701,19 @@ var ColorMixin = {
1598
1701
  },
1599
1702
 
1600
1703
  _setColor(color, stroke) {
1704
+ if (color instanceof PDFGradient$1) {
1705
+ color.apply(stroke);
1706
+ return true; // see if tiling pattern, decode & apply it it
1707
+ } else if (Array.isArray(color) && color[0] instanceof PDFTilingPattern$1) {
1708
+ color[0].apply(stroke, color[1]);
1709
+ return true;
1710
+ } // any other case should be a normal color and not a pattern
1711
+
1712
+
1713
+ return this._setColorCore(color, stroke);
1714
+ },
1715
+
1716
+ _setColorCore(color, stroke) {
1601
1717
  color = this._normalizeColor(color);
1602
1718
 
1603
1719
  if (!color) {
@@ -1606,19 +1722,12 @@ var ColorMixin = {
1606
1722
 
1607
1723
  var op = stroke ? 'SCN' : 'scn';
1608
1724
 
1609
- if (color instanceof PDFGradient$1) {
1610
- this._setColorSpace('Pattern', stroke);
1725
+ var space = this._getColorSpace(color);
1611
1726
 
1612
- color.apply(op);
1613
- } else {
1614
- var space = color.length === 4 ? 'DeviceCMYK' : 'DeviceRGB';
1615
-
1616
- this._setColorSpace(space, stroke);
1617
-
1618
- color = color.join(' ');
1619
- this.addContent("".concat(color, " ").concat(op));
1620
- }
1727
+ this._setColorSpace(space, stroke);
1621
1728
 
1729
+ color = color.join(' ');
1730
+ this.addContent("".concat(color, " ").concat(op));
1622
1731
  return true;
1623
1732
  },
1624
1733
 
@@ -1627,6 +1736,10 @@ var ColorMixin = {
1627
1736
  return this.addContent("/".concat(space, " ").concat(op));
1628
1737
  },
1629
1738
 
1739
+ _getColorSpace(color) {
1740
+ return color.length === 4 ? 'DeviceCMYK' : 'DeviceRGB';
1741
+ },
1742
+
1630
1743
  fillColor(color, opacity) {
1631
1744
  var set = this._setColor(color, false);
1632
1745
 
@@ -1717,6 +1830,10 @@ var ColorMixin = {
1717
1830
 
1718
1831
  radialGradient(x1, y1, r1, x2, y2, r2) {
1719
1832
  return new PDFRadialGradient$1(this, x1, y1, r1, x2, y2, r2);
1833
+ },
1834
+
1835
+ pattern(bbox, xStep, yStep, stream) {
1836
+ return new PDFTilingPattern$1(this, bbox, xStep, yStep, stream);
1720
1837
  }
1721
1838
 
1722
1839
  };
@@ -3124,6 +3241,14 @@ class EmbeddedFont extends PDFFont {
3124
3241
  descriptor.data.FontFile2 = fontFile;
3125
3242
  }
3126
3243
 
3244
+ if (this.document.subset) {
3245
+ var CIDSet = Buffer.from('FFFFFFFFC0', 'hex');
3246
+ var CIDSetRef = this.document.ref();
3247
+ CIDSetRef.write(CIDSet);
3248
+ CIDSetRef.end();
3249
+ descriptor.data.CIDSet = CIDSetRef;
3250
+ }
3251
+
3127
3252
  descriptor.end();
3128
3253
  var descendantFontData = {
3129
3254
  Type: 'Font',
@@ -5927,6 +6052,176 @@ function isEqual(a, b) {
5927
6052
  return a.Subtype === b.Subtype && a.Params.CheckSum.toString() === b.Params.CheckSum.toString() && a.Params.Size === b.Params.Size && a.Params.CreationDate === b.Params.CreationDate && a.Params.ModDate === b.Params.ModDate;
5928
6053
  }
5929
6054
 
6055
+ var PDFA = {
6056
+ initPDFA(pSubset) {
6057
+ if (pSubset.charAt(pSubset.length - 3) === '-') {
6058
+ this.subset_conformance = pSubset.charAt(pSubset.length - 1).toUpperCase();
6059
+ this.subset = parseInt(pSubset.charAt(pSubset.length - 2));
6060
+ } else {
6061
+ // Default to Basic conformance when user doesn't specify
6062
+ this.subset_conformance = 'B';
6063
+ this.subset = parseInt(pSubset.charAt(pSubset.length - 1));
6064
+ }
6065
+ },
6066
+
6067
+ endSubset() {
6068
+ this._addPdfaMetadata();
6069
+
6070
+ var jsPath = "".concat(__dirname, "/data/sRGB_IEC61966_2_1.icc");
6071
+ var jestPath = "".concat(__dirname, "/../color_profiles/sRGB_IEC61966_2_1.icc");
6072
+
6073
+ this._addColorOutputIntent(fs.existsSync(jsPath) ? jsPath : jestPath);
6074
+ },
6075
+
6076
+ _addColorOutputIntent(pICCPath) {
6077
+ var iccProfile = fs.readFileSync(pICCPath);
6078
+ var colorProfileRef = this.ref({
6079
+ Length: iccProfile.length,
6080
+ N: 3
6081
+ });
6082
+ colorProfileRef.write(iccProfile);
6083
+ colorProfileRef.end();
6084
+ var intentRef = this.ref({
6085
+ Type: 'OutputIntent',
6086
+ S: 'GTS_PDFA1',
6087
+ Info: new String('sRGB IEC61966-2.1'),
6088
+ OutputConditionIdentifier: new String('sRGB IEC61966-2.1'),
6089
+ DestOutputProfile: colorProfileRef
6090
+ });
6091
+ intentRef.end();
6092
+ this._root.data.OutputIntents = [intentRef];
6093
+ },
6094
+
6095
+ _getPdfaid() {
6096
+ return "\n <rdf:Description xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\" rdf:about=\"\">\n <pdfaid:part>".concat(this.subset, "</pdfaid:part>\n <pdfaid:conformance>").concat(this.subset_conformance, "</pdfaid:conformance>\n </rdf:Description>\n ");
6097
+ },
6098
+
6099
+ _addPdfaMetadata() {
6100
+ this.appendXML(this._getPdfaid());
6101
+ }
6102
+
6103
+ };
6104
+
6105
+ var SubsetMixin = {
6106
+ _importSubset(subset) {
6107
+ Object.assign(this, subset);
6108
+ },
6109
+
6110
+ initSubset(options) {
6111
+ switch (options.subset) {
6112
+ case 'PDF/A-1':
6113
+ case 'PDF/A-1a':
6114
+ case 'PDF/A-1b':
6115
+ case 'PDF/A-2':
6116
+ case 'PDF/A-2a':
6117
+ case 'PDF/A-2b':
6118
+ case 'PDF/A-3':
6119
+ case 'PDF/A-3a':
6120
+ case 'PDF/A-3b':
6121
+ this._importSubset(PDFA);
6122
+
6123
+ this.initPDFA(options.subset);
6124
+ break;
6125
+ }
6126
+ }
6127
+
6128
+ };
6129
+
6130
+ class PDFMetadata {
6131
+ constructor() {
6132
+ this._metadata = "\n <?xpacket begin=\"\uFEFF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n <x:xmpmeta xmlns:x=\"adobe:ns:meta/\">\n <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n ";
6133
+ }
6134
+
6135
+ _closeTags() {
6136
+ this._metadata = this._metadata.concat("\n </rdf:RDF>\n </x:xmpmeta>\n <?xpacket end=\"w\"?>\n ");
6137
+ }
6138
+
6139
+ append(xml) {
6140
+ var newline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
6141
+ this._metadata = this._metadata.concat(xml);
6142
+ if (newline) this._metadata = this._metadata.concat('\n');
6143
+ }
6144
+
6145
+ getXML() {
6146
+ return this._metadata;
6147
+ }
6148
+
6149
+ getLength() {
6150
+ return this._metadata.length;
6151
+ }
6152
+
6153
+ end() {
6154
+ this._closeTags();
6155
+
6156
+ this._metadata = this._metadata.trim();
6157
+ }
6158
+
6159
+ }
6160
+
6161
+ var MetadataMixin = {
6162
+ initMetadata() {
6163
+ this.metadata = new PDFMetadata();
6164
+ },
6165
+
6166
+ appendXML(xml) {
6167
+ var newline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
6168
+ this.metadata.append(xml, newline);
6169
+ },
6170
+
6171
+ _addInfo() {
6172
+ this.appendXML("\n <rdf:Description rdf:about=\"\" xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\">\n <xmp:CreateDate>".concat(this.info.CreationDate.toISOString().split('.')[0] + "Z", "</xmp:CreateDate>\n <xmp:CreatorTool>").concat(this.info.Creator, "</xmp:CreatorTool>\n </rdf:Description>\n "));
6173
+
6174
+ if (this.info.Title || this.info.Author || this.info.Subject) {
6175
+ this.appendXML("\n <rdf:Description rdf:about=\"\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n ");
6176
+
6177
+ if (this.info.Title) {
6178
+ this.appendXML("\n <dc:title>\n <rdf:Alt>\n <rdf:li xml:lang=\"x-default\">".concat(this.info.Title, "</rdf:li>\n </rdf:Alt>\n </dc:title>\n "));
6179
+ }
6180
+
6181
+ if (this.info.Author) {
6182
+ this.appendXML("\n <dc:creator>\n <rdf:Seq>\n <rdf:li>".concat(this.info.Author, "</rdf:li>\n </rdf:Seq>\n </dc:creator>\n "));
6183
+ }
6184
+
6185
+ if (this.info.Subject) {
6186
+ this.appendXML("\n <dc:description>\n <rdf:Alt>\n <rdf:li xml:lang=\"x-default\">".concat(this.info.Subject, "</rdf:li>\n </rdf:Alt>\n </dc:description>\n "));
6187
+ }
6188
+
6189
+ this.appendXML("\n </rdf:Description>\n ");
6190
+ }
6191
+
6192
+ this.appendXML("\n <rdf:Description rdf:about=\"\" xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n <pdf:Producer>".concat(this.info.Creator, "</pdf:Producer>"), false);
6193
+
6194
+ if (this.info.Keywords) {
6195
+ this.appendXML("\n <pdf:Keywords>".concat(this.info.Keywords, "</pdf:Keywords>"), false);
6196
+ }
6197
+
6198
+ this.appendXML("\n </rdf:Description>\n ");
6199
+ },
6200
+
6201
+ endMetadata() {
6202
+ this._addInfo();
6203
+
6204
+ this.metadata.end();
6205
+ /*
6206
+ Metadata was introduced in PDF 1.4, so adding it to 1.3
6207
+ will likely only take up more space.
6208
+ */
6209
+
6210
+ if (this.version != 1.3) {
6211
+ this.metadataRef = this.ref({
6212
+ length: this.metadata.getLength(),
6213
+ Type: 'Metadata',
6214
+ Subtype: 'XML'
6215
+ });
6216
+ this.metadataRef.compress = false;
6217
+ this.metadataRef.write(Buffer.from(this.metadata.getXML(), 'utf-8'));
6218
+ this.metadataRef.end();
6219
+ this._root.data.Metadata = this.metadataRef;
6220
+ }
6221
+ }
6222
+
6223
+ };
6224
+
5930
6225
  /*
5931
6226
  PDFDocument - represents an entire PDF document
5932
6227
  By Devon Govett
@@ -5991,13 +6286,15 @@ class PDFDocument extends stream.Readable {
5991
6286
 
5992
6287
  this.page = null; // Initialize mixins
5993
6288
 
6289
+ this.initMetadata();
5994
6290
  this.initColor();
5995
6291
  this.initVector();
5996
6292
  this.initFonts(options.font);
5997
6293
  this.initText();
5998
6294
  this.initImages();
5999
6295
  this.initOutline();
6000
- this.initMarkings(options); // Initialize the metadata
6296
+ this.initMarkings(options);
6297
+ this.initSubset(options); // Initialize the metadata
6001
6298
 
6002
6299
  this.info = {
6003
6300
  Producer: 'PDFKit',
@@ -6219,6 +6516,12 @@ class PDFDocument extends stream.Readable {
6219
6516
  this.endOutline();
6220
6517
  this.endMarkings();
6221
6518
 
6519
+ if (this.subset) {
6520
+ this.endSubset();
6521
+ }
6522
+
6523
+ this.endMetadata();
6524
+
6222
6525
  this._root.end();
6223
6526
 
6224
6527
  this._root.data.Pages.end();
@@ -6294,6 +6597,7 @@ var mixin = methods => {
6294
6597
  Object.assign(PDFDocument.prototype, methods);
6295
6598
  };
6296
6599
 
6600
+ mixin(MetadataMixin);
6297
6601
  mixin(ColorMixin);
6298
6602
  mixin(VectorMixin);
6299
6603
  mixin(FontsMixin);
@@ -6304,6 +6608,7 @@ mixin(OutlineMixin);
6304
6608
  mixin(MarkingsMixin);
6305
6609
  mixin(AcroFormMixin);
6306
6610
  mixin(AttachmentsMixin);
6611
+ mixin(SubsetMixin);
6307
6612
  PDFDocument.LineWrapper = LineWrapper;
6308
6613
 
6309
6614
  export default PDFDocument;