pdfkit 0.14.0 → 0.15.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/js/pdfkit.es5.js CHANGED
@@ -5,6 +5,7 @@ import CryptoJS from 'crypto-js';
5
5
  import fontkit from 'fontkit';
6
6
  import { EventEmitter } from 'events';
7
7
  import LineBreaker from 'linebreak';
8
+ import exif from 'jpeg-exif';
8
9
  import PNG from 'png-js';
9
10
 
10
11
  function _classCallCheck(instance, Constructor) {
@@ -3138,6 +3139,11 @@ var VectorMixin = {
3138
3139
  },
3139
3140
  transform: function transform(m11, m12, m21, m22, dx, dy) {
3140
3141
  // keep track of the current transformation matrix
3142
+ if (m11 === 1 && m12 === 0 && m21 === 0 && m22 === 1 && dx === 0 && dy === 0) {
3143
+ // Ignore identity transforms
3144
+ return this;
3145
+ }
3146
+
3141
3147
  var m = this._ctm;
3142
3148
 
3143
3149
  var _m = _slicedToArray(m, 6),
@@ -3876,7 +3882,17 @@ var EmbeddedFont = /*#__PURE__*/function (_PDFFont) {
3876
3882
  _iterator.f();
3877
3883
  }
3878
3884
 
3879
- cmap.end("/CIDInit /ProcSet findresource begin\n12 dict begin\nbegincmap\n/CIDSystemInfo <<\n /Registry (Adobe)\n /Ordering (UCS)\n /Supplement 0\n>> def\n/CMapName /Adobe-Identity-UCS def\n/CMapType 2 def\n1 begincodespacerange\n<0000><ffff>\nendcodespacerange\n1 beginbfrange\n<0000> <".concat(toHex(entries.length - 1), "> [").concat(entries.join(' '), "]\nendbfrange\nendcmap\nCMapName currentdict /CMap defineresource pop\nend\nend"));
3885
+ var chunkSize = 256;
3886
+ var chunks = Math.ceil(entries.length / chunkSize);
3887
+ var ranges = [];
3888
+
3889
+ for (var i = 0; i < chunks; i++) {
3890
+ var start = i * chunkSize;
3891
+ var end = Math.min((i + 1) * chunkSize, entries.length);
3892
+ ranges.push("<".concat(toHex(start), "> <").concat(toHex(end - 1), "> [").concat(entries.slice(start, end).join(' '), "]"));
3893
+ }
3894
+
3895
+ cmap.end("/CIDInit /ProcSet findresource begin\n12 dict begin\nbegincmap\n/CIDSystemInfo <<\n /Registry (Adobe)\n /Ordering (UCS)\n /Supplement 0\n>> def\n/CMapName /Adobe-Identity-UCS def\n/CMapType 2 def\n1 begincodespacerange\n<0000><ffff>\nendcodespacerange\n1 beginbfrange\n".concat(ranges.join('\n'), "\nendbfrange\nendcmap\nCMapName currentdict /CMap defineresource pop\nend\nend"));
3880
3896
  return cmap;
3881
3897
  }
3882
3898
  }]);
@@ -4009,6 +4025,9 @@ var FontsMixin = {
4009
4025
  }
4010
4026
  };
4011
4027
 
4028
+ var SOFT_HYPHEN = "\xAD";
4029
+ var HYPHEN = '-';
4030
+
4012
4031
  var LineWrapper = /*#__PURE__*/function (_EventEmitter) {
4013
4032
  _inherits(LineWrapper, _EventEmitter);
4014
4033
 
@@ -4089,6 +4108,15 @@ var LineWrapper = /*#__PURE__*/function (_EventEmitter) {
4089
4108
  value: function wordWidth(word) {
4090
4109
  return this.document.widthOfString(word, this) + this.characterSpacing + this.wordSpacing;
4091
4110
  }
4111
+ }, {
4112
+ key: "canFit",
4113
+ value: function canFit(word, w) {
4114
+ if (word[word.length - 1] != SOFT_HYPHEN) {
4115
+ return w <= this.spaceLeft;
4116
+ }
4117
+
4118
+ return w + this.wordWidth(HYPHEN) <= this.spaceLeft;
4119
+ }
4092
4120
  }, {
4093
4121
  key: "eachWord",
4094
4122
  value: function eachWord(text, fn) {
@@ -4223,13 +4251,13 @@ var LineWrapper = /*#__PURE__*/function (_EventEmitter) {
4223
4251
  _this2.spaceLeft = _this2.lineWidth;
4224
4252
  }
4225
4253
 
4226
- if (w <= _this2.spaceLeft) {
4254
+ if (_this2.canFit(word, w)) {
4227
4255
  buffer += word;
4228
4256
  textWidth += w;
4229
4257
  wc++;
4230
4258
  }
4231
4259
 
4232
- if (bk.required || w > _this2.spaceLeft) {
4260
+ if (bk.required || !_this2.canFit(word, w)) {
4233
4261
  // if the user specified a max height and an ellipsis, and is about to pass the
4234
4262
  // max height and max columns after the next line, append the ellipsis
4235
4263
  var lh = _this2.document.currentLineHeight(true);
@@ -4266,6 +4294,12 @@ var LineWrapper = /*#__PURE__*/function (_EventEmitter) {
4266
4294
  }
4267
4295
 
4268
4296
  _this2.emit('lastLine', options, _this2);
4297
+ } // Previous entry is a soft hyphen - add visible hyphen.
4298
+
4299
+
4300
+ if (buffer[buffer.length - 1] == SOFT_HYPHEN) {
4301
+ buffer = buffer.slice(0, -1) + HYPHEN;
4302
+ _this2.spaceLeft -= _this2.wordWidth(HYPHEN);
4269
4303
  }
4270
4304
 
4271
4305
  emitLine(); // if we've reached the edge of the page,
@@ -4464,8 +4498,6 @@ var TextMixin = {
4464
4498
  return height;
4465
4499
  },
4466
4500
  list: function list(_list, x, y, options, wrapper) {
4467
- var _this3 = this;
4468
-
4469
4501
  options = this._initOptions(x, y, options);
4470
4502
  var listType = options.listType || 'bullet';
4471
4503
  var unit = Math.round(this._font.ascender / 1000 * this._fontSize);
@@ -4481,8 +4513,8 @@ var TextMixin = {
4481
4513
  var flatten = function flatten(list) {
4482
4514
  var n = 1;
4483
4515
 
4484
- for (var _i = 0; _i < list.length; _i++) {
4485
- var item = list[_i];
4516
+ for (var i = 0; i < list.length; i++) {
4517
+ var item = list[i];
4486
4518
 
4487
4519
  if (Array.isArray(item)) {
4488
4520
  level++;
@@ -4514,83 +4546,92 @@ var TextMixin = {
4514
4546
  }
4515
4547
  };
4516
4548
 
4517
- wrapper = new LineWrapper(this, options);
4518
- wrapper.on('line', this._line);
4519
- level = 1;
4520
- var i = 0;
4521
- wrapper.on('firstLine', function () {
4522
- var item, itemType, labelType, bodyType;
4549
+ var drawListItem = function drawListItem(listItem) {
4550
+ var _this3 = this;
4523
4551
 
4524
- if (options.structParent) {
4525
- if (options.structTypes) {
4526
- var _options$structTypes = _slicedToArray(options.structTypes, 3);
4552
+ wrapper = new LineWrapper(this, options);
4553
+ wrapper.on('line', this._line);
4554
+ level = 1;
4555
+ var i = 0;
4556
+ wrapper.once('firstLine', function () {
4557
+ var item, itemType, labelType, bodyType;
4527
4558
 
4528
- itemType = _options$structTypes[0];
4529
- labelType = _options$structTypes[1];
4530
- bodyType = _options$structTypes[2];
4531
- } else {
4532
- itemType = 'LI';
4533
- labelType = 'Lbl';
4534
- bodyType = 'LBody';
4559
+ if (options.structParent) {
4560
+ if (options.structTypes) {
4561
+ var _options$structTypes = _slicedToArray(options.structTypes, 3);
4562
+
4563
+ itemType = _options$structTypes[0];
4564
+ labelType = _options$structTypes[1];
4565
+ bodyType = _options$structTypes[2];
4566
+ } else {
4567
+ itemType = 'LI';
4568
+ labelType = 'Lbl';
4569
+ bodyType = 'LBody';
4570
+ }
4535
4571
  }
4536
- }
4537
4572
 
4538
- if (itemType) {
4539
- item = _this3.struct(itemType);
4540
- options.structParent.add(item);
4541
- } else if (options.structParent) {
4542
- item = options.structParent;
4543
- }
4573
+ if (itemType) {
4574
+ item = _this3.struct(itemType);
4575
+ options.structParent.add(item);
4576
+ } else if (options.structParent) {
4577
+ item = options.structParent;
4578
+ }
4544
4579
 
4545
- var l;
4580
+ var l;
4546
4581
 
4547
- if ((l = levels[i++]) !== level) {
4548
- var diff = itemIndent * (l - level);
4549
- _this3.x += diff;
4550
- wrapper.lineWidth -= diff;
4551
- level = l;
4552
- }
4582
+ if ((l = levels[i++]) !== level) {
4583
+ var diff = itemIndent * (l - level);
4584
+ _this3.x += diff;
4585
+ wrapper.lineWidth -= diff;
4586
+ level = l;
4587
+ }
4553
4588
 
4554
- if (item && (labelType || bodyType)) {
4555
- item.add(_this3.struct(labelType || bodyType, [_this3.markStructureContent(labelType || bodyType)]));
4556
- }
4589
+ if (item && (labelType || bodyType)) {
4590
+ item.add(_this3.struct(labelType || bodyType, [_this3.markStructureContent(labelType || bodyType)]));
4591
+ }
4557
4592
 
4558
- switch (listType) {
4559
- case 'bullet':
4560
- _this3.circle(_this3.x - indent + r, _this3.y + midLine, r);
4593
+ switch (listType) {
4594
+ case 'bullet':
4595
+ _this3.circle(_this3.x - indent + r, _this3.y + midLine, r);
4561
4596
 
4562
- _this3.fill();
4597
+ _this3.fill();
4563
4598
 
4564
- break;
4599
+ break;
4565
4600
 
4566
- case 'numbered':
4567
- case 'lettered':
4568
- var text = label(numbers[i - 1]);
4601
+ case 'numbered':
4602
+ case 'lettered':
4603
+ var text = label(numbers[i - 1]);
4569
4604
 
4570
- _this3._fragment(text, _this3.x - indent, _this3.y, options);
4605
+ _this3._fragment(text, _this3.x - indent, _this3.y, options);
4571
4606
 
4572
- break;
4573
- }
4607
+ break;
4608
+ }
4574
4609
 
4575
- if (item && labelType && bodyType) {
4576
- item.add(_this3.struct(bodyType, [_this3.markStructureContent(bodyType)]));
4577
- }
4610
+ if (item && labelType && bodyType) {
4611
+ item.add(_this3.struct(bodyType, [_this3.markStructureContent(bodyType)]));
4612
+ }
4613
+
4614
+ if (item && item !== options.structParent) {
4615
+ item.end();
4616
+ }
4617
+ });
4618
+ wrapper.on('sectionStart', function () {
4619
+ var pos = indent + itemIndent * (level - 1);
4620
+ _this3.x += pos;
4621
+ return wrapper.lineWidth -= pos;
4622
+ });
4623
+ wrapper.on('sectionEnd', function () {
4624
+ var pos = indent + itemIndent * (level - 1);
4625
+ _this3.x -= pos;
4626
+ return wrapper.lineWidth += pos;
4627
+ });
4628
+ wrapper.wrap(listItem, options);
4629
+ };
4630
+
4631
+ for (var i = 0; i < items.length; i++) {
4632
+ drawListItem.call(this, items[i]);
4633
+ }
4578
4634
 
4579
- if (item && item !== options.structParent) {
4580
- item.end();
4581
- }
4582
- });
4583
- wrapper.on('sectionStart', function () {
4584
- var pos = indent + itemIndent * (level - 1);
4585
- _this3.x += pos;
4586
- return wrapper.lineWidth -= pos;
4587
- });
4588
- wrapper.on('sectionEnd', function () {
4589
- var pos = indent + itemIndent * (level - 1);
4590
- _this3.x -= pos;
4591
- return wrapper.lineWidth += pos;
4592
- });
4593
- wrapper.wrap(items.join('\n'), options);
4594
4635
  return this;
4595
4636
  },
4596
4637
  _initOptions: function _initOptions() {
@@ -4965,8 +5006,10 @@ var JPEG = /*#__PURE__*/function () {
4965
5006
 
4966
5007
  if (this.data.readUInt16BE(0) !== 0xffd8) {
4967
5008
  throw 'SOI not found in JPEG';
4968
- }
5009
+ } // Parse the EXIF orientation
5010
+
4969
5011
 
5012
+ this.orientation = exif.fromBuffer(this.data).Orientation || 1;
4970
5013
  var pos = 2;
4971
5014
 
4972
5015
  while (pos < this.data.length) {
@@ -5234,7 +5277,7 @@ var PDFImage = /*#__PURE__*/function () {
5234
5277
  } else {
5235
5278
  var match;
5236
5279
 
5237
- if (match = /^data:.+;base64,(.*)$/.exec(src)) {
5280
+ if (match = /^data:.+?;base64,(.*)$/.exec(src)) {
5238
5281
  data = Buffer.from(match[1], 'base64');
5239
5282
  } else {
5240
5283
  data = fs.readFileSync(src);
@@ -5265,13 +5308,15 @@ var ImagesMixin = {
5265
5308
  },
5266
5309
  image: function image(src, x, y) {
5267
5310
  var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
5268
- var bh, bp, bw, image, ip, left, left1;
5311
+ var bh, bp, bw, image, ip, left, left1, rotateAngle, originX, originY;
5269
5312
 
5270
5313
  if (typeof x === 'object') {
5271
5314
  options = x;
5272
5315
  x = null;
5273
- }
5316
+ } // Ignore orientation based on document options or image options
5317
+
5274
5318
 
5319
+ var ignoreOrientation = options.ignoreOrientation || options.ignoreOrientation !== false && this.options.ignoreOrientation;
5275
5320
  x = (left = x != null ? x : options.x) != null ? left : this.x;
5276
5321
  y = (left1 = y != null ? y : options.y) != null ? left1 : this.y;
5277
5322
 
@@ -5295,27 +5340,37 @@ var ImagesMixin = {
5295
5340
  this.page.xobjects[image.label] = image.obj;
5296
5341
  }
5297
5342
 
5298
- var w = options.width || image.width;
5299
- var h = options.height || image.height;
5343
+ var _image = image,
5344
+ width = _image.width,
5345
+ height = _image.height; // If EXIF orientation calls for it, swap width and height
5346
+
5347
+ if (!ignoreOrientation && image.orientation > 4) {
5348
+ var _ref = [height, width];
5349
+ width = _ref[0];
5350
+ height = _ref[1];
5351
+ }
5352
+
5353
+ var w = options.width || width;
5354
+ var h = options.height || height;
5300
5355
 
5301
5356
  if (options.width && !options.height) {
5302
- var wp = w / image.width;
5303
- w = image.width * wp;
5304
- h = image.height * wp;
5357
+ var wp = w / width;
5358
+ w = width * wp;
5359
+ h = height * wp;
5305
5360
  } else if (options.height && !options.width) {
5306
- var hp = h / image.height;
5307
- w = image.width * hp;
5308
- h = image.height * hp;
5361
+ var hp = h / height;
5362
+ w = width * hp;
5363
+ h = height * hp;
5309
5364
  } else if (options.scale) {
5310
- w = image.width * options.scale;
5311
- h = image.height * options.scale;
5365
+ w = width * options.scale;
5366
+ h = height * options.scale;
5312
5367
  } else if (options.fit) {
5313
5368
  var _options$fit = _slicedToArray(options.fit, 2);
5314
5369
 
5315
5370
  bw = _options$fit[0];
5316
5371
  bh = _options$fit[1];
5317
5372
  bp = bw / bh;
5318
- ip = image.width / image.height;
5373
+ ip = width / height;
5319
5374
 
5320
5375
  if (ip > bp) {
5321
5376
  w = bw;
@@ -5330,7 +5385,7 @@ var ImagesMixin = {
5330
5385
  bw = _options$cover[0];
5331
5386
  bh = _options$cover[1];
5332
5387
  bp = bw / bh;
5333
- ip = image.width / image.height;
5388
+ ip = width / height;
5334
5389
 
5335
5390
  if (ip > bp) {
5336
5391
  h = bh;
@@ -5353,6 +5408,93 @@ var ImagesMixin = {
5353
5408
  } else if (options.valign === 'bottom') {
5354
5409
  y = y + bh - h;
5355
5410
  }
5411
+ }
5412
+
5413
+ if (!ignoreOrientation) {
5414
+ switch (image.orientation) {
5415
+ // No orientation (need to flip image, though, because of the default transform matrix on the document)
5416
+ default:
5417
+ case 1:
5418
+ h = -h;
5419
+ y -= h;
5420
+ rotateAngle = 0;
5421
+ break;
5422
+ // Flip Horizontal
5423
+
5424
+ case 2:
5425
+ w = -w;
5426
+ h = -h;
5427
+ x -= w;
5428
+ y -= h;
5429
+ rotateAngle = 0;
5430
+ break;
5431
+ // Rotate 180 degrees
5432
+
5433
+ case 3:
5434
+ originX = x;
5435
+ originY = y;
5436
+ h = -h;
5437
+ x -= w;
5438
+ rotateAngle = 180;
5439
+ break;
5440
+ // Flip vertical
5441
+
5442
+ case 4:
5443
+ // Do nothing, image will be flipped
5444
+ break;
5445
+ // Flip horizontally and rotate 270 degrees CW
5446
+
5447
+ case 5:
5448
+ originX = x;
5449
+ originY = y;
5450
+ var _ref2 = [h, w];
5451
+ w = _ref2[0];
5452
+ h = _ref2[1];
5453
+ y -= h;
5454
+ rotateAngle = 90;
5455
+ break;
5456
+ // Rotate 90 degrees CW
5457
+
5458
+ case 6:
5459
+ originX = x;
5460
+ originY = y;
5461
+ var _ref3 = [h, w];
5462
+ w = _ref3[0];
5463
+ h = _ref3[1];
5464
+ h = -h;
5465
+ rotateAngle = 90;
5466
+ break;
5467
+ // Flip horizontally and rotate 90 degrees CW
5468
+
5469
+ case 7:
5470
+ originX = x;
5471
+ originY = y;
5472
+ var _ref4 = [h, w];
5473
+ w = _ref4[0];
5474
+ h = _ref4[1];
5475
+ h = -h;
5476
+ w = -w;
5477
+ x -= w;
5478
+ rotateAngle = 90;
5479
+ break;
5480
+ // Rotate 270 degrees CW
5481
+
5482
+ case 8:
5483
+ originX = x;
5484
+ originY = y;
5485
+ var _ref5 = [h, w];
5486
+ w = _ref5[0];
5487
+ h = _ref5[1];
5488
+ h = -h;
5489
+ x -= w;
5490
+ y -= h;
5491
+ rotateAngle = -90;
5492
+ break;
5493
+ }
5494
+ } else {
5495
+ h = -h;
5496
+ y -= h;
5497
+ rotateAngle = 0;
5356
5498
  } // create link annotations if the link option is given
5357
5499
 
5358
5500
 
@@ -5374,7 +5516,14 @@ var ImagesMixin = {
5374
5516
  }
5375
5517
 
5376
5518
  this.save();
5377
- this.transform(w, 0, 0, -h, x, y + h);
5519
+
5520
+ if (rotateAngle) {
5521
+ this.rotate(rotateAngle, {
5522
+ origin: [originX, originY]
5523
+ });
5524
+ }
5525
+
5526
+ this.transform(w, 0, 0, h, x, y);
5378
5527
  this.addContent("/".concat(image.label, " Do"));
5379
5528
  this.restore();
5380
5529
  return this;
@@ -6482,7 +6631,10 @@ var AcroFormMixin = {
6482
6631
  var result = 0;
6483
6632
  Object.keys(options).forEach(function (key) {
6484
6633
  if (FIELD_FLAGS[key]) {
6485
- result |= FIELD_FLAGS[key];
6634
+ if (options[key]) {
6635
+ result |= FIELD_FLAGS[key];
6636
+ }
6637
+
6486
6638
  delete options[key];
6487
6639
  }
6488
6640
  });
@@ -6615,7 +6767,7 @@ var AttachmentsMixin = {
6615
6767
  } else {
6616
6768
  var match;
6617
6769
 
6618
- if (match = /^data:(.*);base64,(.*)$/.exec(src)) {
6770
+ if (match = /^data:(.*?);base64,(.*)$/.exec(src)) {
6619
6771
  if (match[1]) {
6620
6772
  refBody.Subtype = match[1].replace('/', '#2F');
6621
6773
  }
@@ -6747,6 +6899,21 @@ var PDFA = {
6747
6899
  }
6748
6900
  };
6749
6901
 
6902
+ var PDFUA = {
6903
+ initPDFUA: function initPDFUA() {
6904
+ this.subset = 1;
6905
+ },
6906
+ endSubset: function endSubset() {
6907
+ this._addPdfuaMetadata();
6908
+ },
6909
+ _addPdfuaMetadata: function _addPdfuaMetadata() {
6910
+ this.appendXML(this._getPdfuaid());
6911
+ },
6912
+ _getPdfuaid: function _getPdfuaid() {
6913
+ return "\n <rdf:Description xmlns:pdfuaid=\"http://www.aiim.org/pdfua/ns/id/\" rdf:about=\"\">\n <pdfuaid:part>".concat(this.subset, "</pdfuaid:part>\n </rdf:Description>\n ");
6914
+ }
6915
+ };
6916
+
6750
6917
  var SubsetMixin = {
6751
6918
  _importSubset: function _importSubset(subset) {
6752
6919
  Object.assign(this, subset);
@@ -6766,6 +6933,12 @@ var SubsetMixin = {
6766
6933
 
6767
6934
  this.initPDFA(options.subset);
6768
6935
  break;
6936
+
6937
+ case 'PDF/UA':
6938
+ this._importSubset(PDFUA);
6939
+
6940
+ this.initPDFUA();
6941
+ break;
6769
6942
  }
6770
6943
  }
6771
6944
  };