@kittl/pdfkit 0.17.4 → 0.17.5

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.js CHANGED
@@ -941,14 +941,18 @@ class PDFGradient$1 {
941
941
  }
942
942
  color = this.doc._normalizeColor(color);
943
943
  if (this.stops.length === 0) {
944
- if (color.length === 3) {
945
- this._colorSpace = 'DeviceRGB';
946
- } else if (color.length === 4) {
947
- this._colorSpace = 'DeviceCMYK';
948
- } else if (color.length === 1) {
949
- this._colorSpace = 'DeviceGray';
944
+ if (this._activeColorProfile) {
945
+ this._colorSpace = this._activeColorProfile.ref;
950
946
  } else {
951
- throw new Error('Unknown color space');
947
+ if (color.length === 3) {
948
+ this._colorSpace = 'DeviceRGB';
949
+ } else if (color.length === 4) {
950
+ this._colorSpace = 'DeviceCMYK';
951
+ } else if (color.length === 1) {
952
+ this._colorSpace = 'DeviceGray';
953
+ } else {
954
+ throw new Error('Unknown color space');
955
+ }
952
956
  }
953
957
  } else if (this._colorSpace === 'DeviceRGB' && color.length !== 3 || this._colorSpace === 'DeviceCMYK' && color.length !== 4 || this._colorSpace === 'DeviceGray' && color.length !== 1) {
954
958
  throw new Error('All gradient stops must use the same color space');
@@ -1239,7 +1243,7 @@ var ColorMixin = {
1239
1243
  if (color.length === 3) {
1240
1244
  color = color.map(part => part / 255);
1241
1245
  } else if (color.length === 4) {
1242
- color = color.map(part => part / 255);
1246
+ color = color.map(part => part / 100);
1243
1247
  }
1244
1248
  return color;
1245
1249
  }
@@ -1315,7 +1319,7 @@ var ColorMixin = {
1315
1319
  this._doOpacity(null, opacity);
1316
1320
  return this;
1317
1321
  },
1318
- beingColorProfile(label) {
1322
+ beginColorSpace(label) {
1319
1323
  const profile = this._colorProfiles[label];
1320
1324
  if (!profile) {
1321
1325
  throw Error('Invalid color space label, the profile should be set first');
@@ -1323,7 +1327,7 @@ var ColorMixin = {
1323
1327
  this._activeColorProfile = profile;
1324
1328
  return this;
1325
1329
  },
1326
- endColorProfile() {
1330
+ endColorSpace() {
1327
1331
  this._activeColorProfile = null;
1328
1332
  return this;
1329
1333
  },
@@ -3947,10 +3951,102 @@ class PNGImage {
3947
3951
  }
3948
3952
  }
3949
3953
 
3954
+ class BitmapImage {
3955
+ constructor(data, label, properties) {
3956
+ this.label = label;
3957
+ this.data = data;
3958
+ this.width = properties.width;
3959
+ this.height = properties.height;
3960
+ this.channels = properties.channels;
3961
+ this.colorSpace = properties.colorSpace;
3962
+ this.hasAlphaChannel = properties.hasAlphaChannel;
3963
+ this.obj = null;
3964
+ }
3965
+ embed(document) {
3966
+ if (this.obj) {
3967
+ return;
3968
+ }
3969
+ this.document = document;
3970
+ if (!(this.data instanceof Uint8Array && this.data.length === this.channels * this.width * this.height)) {
3971
+ throw Error("Invalid bitmap, data doesn't match the given properties.");
3972
+ }
3973
+ if (this.colorSpace) {
3974
+ const profile = this.document._colorProfiles[this.colorSpace];
3975
+ if (!profile) {
3976
+ throw Error("PDFDocument doesn't support bitmap color space.");
3977
+ }
3978
+ const channels = this.hasAlphaChannel ? this.channels - 1 : this.channels;
3979
+ if (profile.channels !== channels) {
3980
+ throw Error("Color profile doesn't support image channels");
3981
+ }
3982
+ this.colorSpace = profile.ref;
3983
+ } else {
3984
+ if (!this.hasAlphaChannel) {
3985
+ this.colorSpace = this.channels === 4 ? 'DeviceCMYK' : 'DeviceRGB';
3986
+ } else {
3987
+ this.colorSpace = this.channels === 5 ? 'DeviceCMYK' : 'DeviceRGB';
3988
+ }
3989
+ }
3990
+ let pixelData = this.data;
3991
+ let alphaData = undefined;
3992
+ if (this.hasAlphaChannel) {
3993
+ const pixelChannels = this.channels - 1;
3994
+ pixelData = new Uint8Array(pixelChannels * this.width * this.height);
3995
+ alphaData = new Uint8Array(this.width * this.height);
3996
+ if (this.channels === 4) {
3997
+ for (let src = 0, dst = 0, a = 0; a < this.data.length; src += 4, dst += 3, a++) {
3998
+ pixelData[dst] = this.data[src];
3999
+ pixelData[dst + 1] = this.data[src + 1];
4000
+ pixelData[dst + 2] = this.data[src + 2];
4001
+ alphaData[a] = this.data[src + 3];
4002
+ }
4003
+ } else if (this.channels === 5) {
4004
+ for (let src = 0, dst = 0, a = 0; a < this.data.length; src += 5, dst += 4, a++) {
4005
+ pixelData[dst] = this.data[src];
4006
+ pixelData[dst + 1] = this.data[src + 1];
4007
+ pixelData[dst + 2] = this.data[src + 2];
4008
+ pixelData[dst + 3] = this.data[src + 3];
4009
+ alphaData[a] = this.data[src + 4];
4010
+ }
4011
+ } else {
4012
+ for (let src = 0, dst = 0, a = 0; a < this.data.length; src += this.channels, dst += pixelChannels, a++) {
4013
+ for (let j = 0; j < pixelChannels; j++) {
4014
+ pixelData[dst + j] = this.data[src + j];
4015
+ }
4016
+ alphaData[a] = this.data[src + pixelChannels];
4017
+ }
4018
+ }
4019
+ }
4020
+ this.obj = this.document.ref({
4021
+ Type: 'XObject',
4022
+ Subtype: 'Image',
4023
+ BitsPerComponent: 8,
4024
+ Width: this.width,
4025
+ Height: this.height,
4026
+ ColorSpace: this.colorSpace
4027
+ });
4028
+ if (alphaData) {
4029
+ const sMask = this.document.ref({
4030
+ Type: 'XObject',
4031
+ Subtype: 'Image',
4032
+ Height: this.height,
4033
+ Width: this.width,
4034
+ BitsPerComponent: 8,
4035
+ ColorSpace: 'DeviceGray',
4036
+ Decode: [0, 1]
4037
+ });
4038
+ sMask.end(alphaData);
4039
+ this.obj.data['SMask'] = sMask;
4040
+ }
4041
+ this.obj.end(pixelData);
4042
+ this.data = null;
4043
+ }
4044
+ }
4045
+
3950
4046
  class PDFImage {
3951
- static open(src, label) {
4047
+ static open(src, label, properties) {
3952
4048
  let data;
3953
- if (Buffer.isBuffer(src)) {
4049
+ if (src instanceof Uint8Array || Buffer.isBuffer(src)) {
3954
4050
  data = src;
3955
4051
  } else if (src instanceof ArrayBuffer) {
3956
4052
  data = Buffer.from(new Uint8Array(src));
@@ -3968,6 +4064,9 @@ class PDFImage {
3968
4064
  }
3969
4065
  }
3970
4066
  }
4067
+ if (properties?.isBitmap) {
4068
+ return new BitmapImage(data, label, properties);
4069
+ }
3971
4070
  if (data[0] === 0xff && data[1] === 0xd8) {
3972
4071
  return new JPEG(data, label);
3973
4072
  } else if (data[0] === 0x89 && data.toString('ascii', 1, 4) === 'PNG') {
@@ -4151,13 +4250,13 @@ var ImagesMixin = {
4151
4250
  this.restore();
4152
4251
  return this;
4153
4252
  },
4154
- openImage(src) {
4253
+ openImage(src, properties) {
4155
4254
  let image;
4156
4255
  if (typeof src === 'string') {
4157
4256
  image = this._imageRegistry[src];
4158
4257
  }
4159
4258
  if (!image) {
4160
- image = PDFImage.open(src, `I${++this._imageCount}`);
4259
+ image = PDFImage.open(src, `I${++this._imageCount}`, properties);
4161
4260
  if (typeof src === 'string') {
4162
4261
  this._imageRegistry[src] = image;
4163
4262
  }
@@ -6032,8 +6131,7 @@ class ICCProfile {
6032
6131
  N: this.channels,
6033
6132
  Length: this.data.length
6034
6133
  });
6035
- this.streamRef.write(this.data);
6036
- this.streamRef.end();
6134
+ this.streamRef.end(this.data);
6037
6135
  this.ref = this.document.ref([`ICCBased ${this.streamRef}`]);
6038
6136
  this.ref.end();
6039
6137
  this.data = null;