@libpdf/core 0.1.1 → 0.2.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/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ import { createCMSECDSASignature } from "pkijs";
9
9
  import { base64 } from "@scure/base";
10
10
 
11
11
  //#region package.json
12
- var version = "0.1.1";
12
+ var version = "0.2.1";
13
13
 
14
14
  //#endregion
15
15
  //#region src/objects/pdf-array.ts
@@ -44,9 +44,12 @@ var PdfArray = class PdfArray {
44
44
  }
45
45
  /**
46
46
  * Get item at index. Returns undefined if out of bounds.
47
+ * If resolver is provided, resolves indirect references.
47
48
  */
48
- at(index) {
49
- return this.items.at(index);
49
+ at(index, resolver) {
50
+ const value = this.items.at(index);
51
+ if (resolver && value?.type === "ref") return resolver(value) ?? void 0;
52
+ return value;
50
53
  }
51
54
  /**
52
55
  * Set item at index. Extends array if needed.
@@ -3484,14 +3487,14 @@ var PDFAnnotation = class {
3484
3487
  * Annotation subtype (e.g., "Text", "Highlight", "Link").
3485
3488
  */
3486
3489
  get type() {
3487
- const subtype = this.dict.getName("Subtype")?.value;
3490
+ const subtype = this.dict.getName("Subtype", this.registry.resolve.bind(this.registry))?.value;
3488
3491
  return isAnnotationSubtype(subtype) ? subtype : "Text";
3489
3492
  }
3490
3493
  /**
3491
3494
  * Annotation rectangle in page coordinates.
3492
3495
  */
3493
3496
  get rect() {
3494
- const arr = this.dict.getArray("Rect");
3497
+ const arr = this.dict.getArray("Rect", this.registry.resolve.bind(this.registry));
3495
3498
  if (!arr || arr.length < 4) return {
3496
3499
  x: 0,
3497
3500
  y: 0,
@@ -3510,7 +3513,7 @@ var PDFAnnotation = class {
3510
3513
  * Set the annotation rectangle.
3511
3514
  */
3512
3515
  setRect(rect) {
3513
- const arr = this.dict.getArray("Rect");
3516
+ const arr = this.dict.getArray("Rect", this.registry.resolve.bind(this.registry));
3514
3517
  if (arr && arr.length >= 4) {
3515
3518
  arr.set(0, PdfNumber.of(rect.x));
3516
3519
  arr.set(1, PdfNumber.of(rect.y));
@@ -3528,7 +3531,7 @@ var PDFAnnotation = class {
3528
3531
  * Text content or description of the annotation.
3529
3532
  */
3530
3533
  get contents() {
3531
- return this.dict.getString("Contents")?.asString() ?? null;
3534
+ return this.dict.getString("Contents", this.registry.resolve.bind(this.registry))?.asString() ?? null;
3532
3535
  }
3533
3536
  /**
3534
3537
  * Set the annotation contents.
@@ -3541,7 +3544,7 @@ var PDFAnnotation = class {
3541
3544
  * Annotation name (unique identifier within page).
3542
3545
  */
3543
3546
  get name() {
3544
- return this.dict.getString("NM")?.asString() ?? null;
3547
+ return this.dict.getString("NM", this.registry.resolve.bind(this.registry))?.asString() ?? null;
3545
3548
  }
3546
3549
  /**
3547
3550
  * Set the annotation name.
@@ -3554,7 +3557,7 @@ var PDFAnnotation = class {
3554
3557
  * Modification date.
3555
3558
  */
3556
3559
  get modificationDate() {
3557
- return this.dict.getString("M")?.asString() ?? null;
3560
+ return this.dict.getString("M", this.registry.resolve.bind(this.registry))?.asString() ?? null;
3558
3561
  }
3559
3562
  /**
3560
3563
  * Set the modification date (PDF date format).
@@ -3567,7 +3570,7 @@ var PDFAnnotation = class {
3567
3570
  * Annotation flags.
3568
3571
  */
3569
3572
  get flags() {
3570
- return this.dict.getNumber("F")?.value ?? 0;
3573
+ return this.dict.getNumber("F", this.registry.resolve.bind(this.registry))?.value ?? 0;
3571
3574
  }
3572
3575
  /**
3573
3576
  * Check if the annotation has a specific flag set.
@@ -3613,7 +3616,7 @@ var PDFAnnotation = class {
3613
3616
  * Annotation color.
3614
3617
  */
3615
3618
  get color() {
3616
- return parseColorArray(this.dict.getArray("C"));
3619
+ return parseColorArray(this.dict.getArray("C", this.registry.resolve.bind(this.registry)));
3617
3620
  }
3618
3621
  /**
3619
3622
  * Set the annotation color.
@@ -3627,13 +3630,13 @@ var PDFAnnotation = class {
3627
3630
  * Get the border style.
3628
3631
  */
3629
3632
  getBorderStyle() {
3630
- const bs = this.dict.getDict("BS");
3633
+ const bs = this.dict.getDict("BS", this.registry.resolve.bind(this.registry));
3631
3634
  if (!bs) return null;
3632
3635
  const result = {
3633
- width: bs.getNumber("W")?.value ?? 1,
3634
- style: BORDER_STYLE_MAP[bs.getName("S")?.value ?? "S"] ?? "solid"
3636
+ width: bs.getNumber("W", this.registry.resolve.bind(this.registry))?.value ?? 1,
3637
+ style: BORDER_STYLE_MAP[bs.getName("S", this.registry.resolve.bind(this.registry))?.value ?? "S"] ?? "solid"
3635
3638
  };
3636
- const dashArr = bs.getArray("D");
3639
+ const dashArr = bs.getArray("D", this.registry.resolve.bind(this.registry));
3637
3640
  if (dashArr) {
3638
3641
  result.dashArray = [];
3639
3642
  for (let i = 0; i < dashArr.length; i++) {
@@ -3658,9 +3661,8 @@ var PDFAnnotation = class {
3658
3661
  * Check if the annotation has a normal appearance stream.
3659
3662
  */
3660
3663
  hasNormalAppearance() {
3661
- let ap = this.dict.get("AP");
3662
- if (ap instanceof PdfRef) ap = this.registry.resolve(ap) ?? void 0;
3663
- if (ap instanceof PdfDict) return ap.has("N");
3664
+ const ap = this.dict.getDict("AP", this.registry.resolve.bind(this.registry));
3665
+ if (ap) return ap.has("N");
3664
3666
  return false;
3665
3667
  }
3666
3668
  /**
@@ -3703,12 +3705,9 @@ var PDFAnnotation = class {
3703
3705
  * Get an appearance stream by type.
3704
3706
  */
3705
3707
  getAppearance(type) {
3706
- let ap = this.dict.get("AP");
3707
- if (ap instanceof PdfRef) ap = this.registry.resolve(ap) ?? void 0;
3708
- if (!(ap instanceof PdfDict)) return null;
3709
- let entry = ap.get(type);
3710
- if (!entry) return null;
3711
- if (entry instanceof PdfRef) entry = this.registry.resolve(entry) ?? void 0;
3708
+ let ap = this.dict.getDict("AP", this.registry.resolve.bind(this.registry));
3709
+ if (!ap) return null;
3710
+ let entry = ap.get(type, this.registry.resolve.bind(this.registry));
3712
3711
  if (entry instanceof PdfStream) return entry;
3713
3712
  return null;
3714
3713
  }
@@ -3716,8 +3715,7 @@ var PDFAnnotation = class {
3716
3715
  * Set an appearance stream by type.
3717
3716
  */
3718
3717
  setAppearance(type, stream) {
3719
- let ap = this.dict.get("AP");
3720
- if (ap instanceof PdfRef) ap = this.registry.resolve(ap) ?? void 0;
3718
+ let ap = this.dict.getDict("AP", this.registry.resolve.bind(this.registry));
3721
3719
  if (ap instanceof PdfDict) {
3722
3720
  const streamRef = this.registry.register(stream);
3723
3721
  ap.set(type, streamRef);
@@ -3829,7 +3827,7 @@ var PDFMarkupAnnotation = class extends PDFAnnotation {
3829
3827
  * Text label for the annotation (often the author name).
3830
3828
  */
3831
3829
  get title() {
3832
- return this.dict.getString("T")?.asString() ?? null;
3830
+ return this.dict.getString("T", this.registry.resolve.bind(this.registry))?.asString() ?? null;
3833
3831
  }
3834
3832
  /**
3835
3833
  * Set the title/author.
@@ -3843,7 +3841,7 @@ var PDFMarkupAnnotation = class extends PDFAnnotation {
3843
3841
  * Range 0-1, where 0 is fully transparent and 1 is fully opaque.
3844
3842
  */
3845
3843
  get opacity() {
3846
- return this.dict.getNumber("CA")?.value ?? 1;
3844
+ return this.dict.getNumber("CA", this.registry.resolve.bind(this.registry))?.value ?? 1;
3847
3845
  }
3848
3846
  /**
3849
3847
  * Set the opacity.
@@ -3857,7 +3855,7 @@ var PDFMarkupAnnotation = class extends PDFAnnotation {
3857
3855
  * Creation date (CreationDate).
3858
3856
  */
3859
3857
  get creationDate() {
3860
- return this.dict.getString("CreationDate")?.asString() ?? null;
3858
+ return this.dict.getString("CreationDate", this.registry.resolve.bind(this.registry))?.asString() ?? null;
3861
3859
  }
3862
3860
  /**
3863
3861
  * Set the creation date.
@@ -3870,7 +3868,7 @@ var PDFMarkupAnnotation = class extends PDFAnnotation {
3870
3868
  * Subject - the subject of the annotation.
3871
3869
  */
3872
3870
  get subject() {
3873
- return this.dict.getString("Subj")?.asString() ?? null;
3871
+ return this.dict.getString("Subj", this.registry.resolve.bind(this.registry))?.asString() ?? null;
3874
3872
  }
3875
3873
  /**
3876
3874
  * Set the subject.
@@ -3935,7 +3933,7 @@ var PDFMarkupAnnotation = class extends PDFAnnotation {
3935
3933
  * Intent (IT) - the intent of the markup annotation.
3936
3934
  */
3937
3935
  get intent() {
3938
- return this.dict.getName("IT")?.value ?? null;
3936
+ return this.dict.getName("IT", this.registry.resolve.bind(this.registry))?.value ?? null;
3939
3937
  }
3940
3938
  };
3941
3939
 
@@ -3958,7 +3956,7 @@ var PDFCaretAnnotation = class extends PDFMarkupAnnotation {
3958
3956
  * "P" = paragraph symbol, "None" = no symbol.
3959
3957
  */
3960
3958
  get symbol() {
3961
- if (this.dict.getName("Sy")?.value === "P") return "P";
3959
+ if (this.dict.getName("Sy", this.registry.resolve.bind(this.registry))?.value === "P") return "P";
3962
3960
  return "None";
3963
3961
  }
3964
3962
  /**
@@ -3980,7 +3978,7 @@ var PDFFileAttachmentAnnotation = class extends PDFMarkupAnnotation {
3980
3978
  * Icon to display.
3981
3979
  */
3982
3980
  get icon() {
3983
- const name = this.dict.getName("Name");
3981
+ const name = this.dict.getName("Name", this.registry.resolve.bind(this.registry));
3984
3982
  if (!name) return "PushPin";
3985
3983
  if (isFileAttachmentIcon(name.value)) return name.value;
3986
3984
  return "PushPin";
@@ -4003,11 +4001,7 @@ var PDFFileAttachmentAnnotation = class extends PDFMarkupAnnotation {
4003
4001
  * Get the file specification dictionary.
4004
4002
  */
4005
4003
  getFileSpec() {
4006
- const fsRef = this.fileSpecRef;
4007
- if (!fsRef) return this.dict.getDict("FS") ?? null;
4008
- const resolved = this.registry.resolve(fsRef);
4009
- if (resolved && resolved.type === "dict") return resolved;
4010
- return null;
4004
+ return this.dict.getDict("FS", this.registry.resolve.bind(this.registry)) ?? null;
4011
4005
  }
4012
4006
  /**
4013
4007
  * Get the file name from the file specification.
@@ -4015,9 +4009,9 @@ var PDFFileAttachmentAnnotation = class extends PDFMarkupAnnotation {
4015
4009
  getFileName() {
4016
4010
  const fs = this.getFileSpec();
4017
4011
  if (!fs) return null;
4018
- const uf = fs.getString("UF");
4012
+ const uf = fs.getString("UF", this.registry.resolve.bind(this.registry));
4019
4013
  if (uf) return uf.asString();
4020
- const f = fs.getString("F");
4014
+ const f = fs.getString("F", this.registry.resolve.bind(this.registry));
4021
4015
  if (f) return f.asString();
4022
4016
  return null;
4023
4017
  }
@@ -4042,7 +4036,7 @@ var PDFFreeTextAnnotation = class extends PDFMarkupAnnotation {
4042
4036
  * Contains font and color operators.
4043
4037
  */
4044
4038
  get defaultAppearance() {
4045
- return this.dict.getString("DA")?.asString() ?? null;
4039
+ return this.dict.getString("DA", this.registry.resolve.bind(this.registry))?.asString() ?? null;
4046
4040
  }
4047
4041
  /**
4048
4042
  * Set the default appearance.
@@ -4055,7 +4049,7 @@ var PDFFreeTextAnnotation = class extends PDFMarkupAnnotation {
4055
4049
  * Text justification: 0=left, 1=center, 2=right.
4056
4050
  */
4057
4051
  get justification() {
4058
- switch (this.dict.getNumber("Q")?.value ?? 0) {
4052
+ switch (this.dict.getNumber("Q", this.registry.resolve.bind(this.registry))?.value ?? 0) {
4059
4053
  case 1: return "center";
4060
4054
  case 2: return "right";
4061
4055
  default: return "left";
@@ -4076,7 +4070,7 @@ var PDFFreeTextAnnotation = class extends PDFMarkupAnnotation {
4076
4070
  * Contains CSS-style formatting.
4077
4071
  */
4078
4072
  get defaultStyle() {
4079
- return this.dict.getString("DS")?.asString() ?? null;
4073
+ return this.dict.getString("DS", this.registry.resolve.bind(this.registry))?.asString() ?? null;
4080
4074
  }
4081
4075
  /**
4082
4076
  * Set the default style.
@@ -4090,7 +4084,7 @@ var PDFFreeTextAnnotation = class extends PDFMarkupAnnotation {
4090
4084
  * Can be "FreeText", "FreeTextCallout", or "FreeTextTypeWriter".
4091
4085
  */
4092
4086
  get freeTextIntent() {
4093
- return this.dict.getName("IT")?.value ?? null;
4087
+ return this.dict.getName("IT", this.registry.resolve.bind(this.registry))?.value ?? null;
4094
4088
  }
4095
4089
  /**
4096
4090
  * Set the intent.
@@ -4167,7 +4161,7 @@ var PDFInkAnnotation = class extends PDFMarkupAnnotation {
4167
4161
  * Each path is an array of points.
4168
4162
  */
4169
4163
  get inkPaths() {
4170
- const inkList = this.dict.getArray("InkList");
4164
+ const inkList = this.dict.getArray("InkList", this.registry.resolve.bind(this.registry));
4171
4165
  if (!inkList) return [];
4172
4166
  const paths = [];
4173
4167
  for (let i = 0; i < inkList.length; i++) {
@@ -4272,7 +4266,7 @@ var PDFLineAnnotation = class extends PDFMarkupAnnotation {
4272
4266
  * Get the line endpoints.
4273
4267
  */
4274
4268
  get lineEndpoints() {
4275
- const l = this.dict.getArray("L");
4269
+ const l = this.dict.getArray("L", this.registry.resolve.bind(this.registry));
4276
4270
  if (!l || l.length < 4) return {
4277
4271
  start: {
4278
4272
  x: 0,
@@ -4299,7 +4293,7 @@ var PDFLineAnnotation = class extends PDFMarkupAnnotation {
4299
4293
  * Set the line endpoints.
4300
4294
  */
4301
4295
  setLineEndpoints(start, end) {
4302
- const arr = this.dict.getArray("L");
4296
+ const arr = this.dict.getArray("L", this.registry.resolve.bind(this.registry));
4303
4297
  if (arr && arr.length >= 4) {
4304
4298
  arr.set(0, PdfNumber.of(start.x));
4305
4299
  arr.set(1, PdfNumber.of(start.y));
@@ -4329,7 +4323,7 @@ var PDFLineAnnotation = class extends PDFMarkupAnnotation {
4329
4323
  * Line ending styles [start, end].
4330
4324
  */
4331
4325
  get lineEndingStyles() {
4332
- const le = this.dict.getArray("LE");
4326
+ const le = this.dict.getArray("LE", this.registry.resolve.bind(this.registry));
4333
4327
  if (!le || le.length < 2) return ["None", "None"];
4334
4328
  const [startStyle, endStyle] = le.toArray().map((item) => item instanceof PdfName ? item.value : "None");
4335
4329
  return [startStyle ?? "None", endStyle ?? "None"];
@@ -4345,7 +4339,7 @@ var PDFLineAnnotation = class extends PDFMarkupAnnotation {
4345
4339
  * Interior color (fill color for closed arrow heads).
4346
4340
  */
4347
4341
  get interiorColor() {
4348
- return parseColorArray(this.dict.getArray("IC"));
4342
+ return parseColorArray(this.dict.getArray("IC", this.registry.resolve.bind(this.registry)));
4349
4343
  }
4350
4344
  /**
4351
4345
  * Set the interior color.
@@ -4359,19 +4353,19 @@ var PDFLineAnnotation = class extends PDFMarkupAnnotation {
4359
4353
  * Line leader length (for dimension lines).
4360
4354
  */
4361
4355
  get leaderLength() {
4362
- return this.dict.getNumber("LL")?.value ?? 0;
4356
+ return this.dict.getNumber("LL", this.registry.resolve.bind(this.registry))?.value ?? 0;
4363
4357
  }
4364
4358
  /**
4365
4359
  * Line leader line extension.
4366
4360
  */
4367
4361
  get leaderExtension() {
4368
- return this.dict.getNumber("LLE")?.value ?? 0;
4362
+ return this.dict.getNumber("LLE", this.registry.resolve.bind(this.registry))?.value ?? 0;
4369
4363
  }
4370
4364
  /**
4371
4365
  * Caption flag - whether to show caption with the line.
4372
4366
  */
4373
4367
  get hasCaption() {
4374
- return this.dict.getBool("Cap")?.value ?? false;
4368
+ return this.dict.getBool("Cap", this.registry.resolve.bind(this.registry))?.value ?? false;
4375
4369
  }
4376
4370
  /**
4377
4371
  * Line width from border style.
@@ -4878,240 +4872,6 @@ function rectsToQuadPoints(rects) {
4878
4872
  return rects.map(rectToQuadPoints);
4879
4873
  }
4880
4874
 
4881
- //#endregion
4882
- //#region src/helpers/unicode.ts
4883
- /**
4884
- * Unicode utilities for PDF text handling.
4885
- *
4886
- * Provides mappings between Unicode code points and PostScript glyph names.
4887
- */
4888
- /**
4889
- * Map Unicode code point to PostScript glyph name.
4890
- * Returns undefined if no mapping exists.
4891
- */
4892
- function unicodeToGlyphName(unicode) {
4893
- return UNICODE_TO_GLYPH.get(unicode);
4894
- }
4895
- /**
4896
- * Common Unicode to glyph name mappings.
4897
- * Covers ASCII and common Latin-1 extended characters.
4898
- *
4899
- * For a complete mapping, see the Adobe Glyph List:
4900
- * https://github.com/adobe-type-tools/agl-aglfn
4901
- */
4902
- const UNICODE_TO_GLYPH = new Map([
4903
- [32, "space"],
4904
- [33, "exclam"],
4905
- [34, "quotedbl"],
4906
- [35, "numbersign"],
4907
- [36, "dollar"],
4908
- [37, "percent"],
4909
- [38, "ampersand"],
4910
- [39, "quotesingle"],
4911
- [40, "parenleft"],
4912
- [41, "parenright"],
4913
- [42, "asterisk"],
4914
- [43, "plus"],
4915
- [44, "comma"],
4916
- [45, "hyphen"],
4917
- [46, "period"],
4918
- [47, "slash"],
4919
- [48, "zero"],
4920
- [49, "one"],
4921
- [50, "two"],
4922
- [51, "three"],
4923
- [52, "four"],
4924
- [53, "five"],
4925
- [54, "six"],
4926
- [55, "seven"],
4927
- [56, "eight"],
4928
- [57, "nine"],
4929
- [58, "colon"],
4930
- [59, "semicolon"],
4931
- [60, "less"],
4932
- [61, "equal"],
4933
- [62, "greater"],
4934
- [63, "question"],
4935
- [64, "at"],
4936
- [65, "A"],
4937
- [66, "B"],
4938
- [67, "C"],
4939
- [68, "D"],
4940
- [69, "E"],
4941
- [70, "F"],
4942
- [71, "G"],
4943
- [72, "H"],
4944
- [73, "I"],
4945
- [74, "J"],
4946
- [75, "K"],
4947
- [76, "L"],
4948
- [77, "M"],
4949
- [78, "N"],
4950
- [79, "O"],
4951
- [80, "P"],
4952
- [81, "Q"],
4953
- [82, "R"],
4954
- [83, "S"],
4955
- [84, "T"],
4956
- [85, "U"],
4957
- [86, "V"],
4958
- [87, "W"],
4959
- [88, "X"],
4960
- [89, "Y"],
4961
- [90, "Z"],
4962
- [91, "bracketleft"],
4963
- [92, "backslash"],
4964
- [93, "bracketright"],
4965
- [94, "asciicircum"],
4966
- [95, "underscore"],
4967
- [96, "grave"],
4968
- [97, "a"],
4969
- [98, "b"],
4970
- [99, "c"],
4971
- [100, "d"],
4972
- [101, "e"],
4973
- [102, "f"],
4974
- [103, "g"],
4975
- [104, "h"],
4976
- [105, "i"],
4977
- [106, "j"],
4978
- [107, "k"],
4979
- [108, "l"],
4980
- [109, "m"],
4981
- [110, "n"],
4982
- [111, "o"],
4983
- [112, "p"],
4984
- [113, "q"],
4985
- [114, "r"],
4986
- [115, "s"],
4987
- [116, "t"],
4988
- [117, "u"],
4989
- [118, "v"],
4990
- [119, "w"],
4991
- [120, "x"],
4992
- [121, "y"],
4993
- [122, "z"],
4994
- [123, "braceleft"],
4995
- [124, "bar"],
4996
- [125, "braceright"],
4997
- [126, "asciitilde"],
4998
- [160, "nbspace"],
4999
- [161, "exclamdown"],
5000
- [162, "cent"],
5001
- [163, "sterling"],
5002
- [164, "currency"],
5003
- [165, "yen"],
5004
- [166, "brokenbar"],
5005
- [167, "section"],
5006
- [168, "dieresis"],
5007
- [169, "copyright"],
5008
- [170, "ordfeminine"],
5009
- [171, "guillemotleft"],
5010
- [172, "logicalnot"],
5011
- [173, "softhyphen"],
5012
- [174, "registered"],
5013
- [175, "macron"],
5014
- [176, "degree"],
5015
- [177, "plusminus"],
5016
- [178, "twosuperior"],
5017
- [179, "threesuperior"],
5018
- [180, "acute"],
5019
- [181, "mu"],
5020
- [182, "paragraph"],
5021
- [183, "periodcentered"],
5022
- [184, "cedilla"],
5023
- [185, "onesuperior"],
5024
- [186, "ordmasculine"],
5025
- [187, "guillemotright"],
5026
- [188, "onequarter"],
5027
- [189, "onehalf"],
5028
- [190, "threequarters"],
5029
- [191, "questiondown"],
5030
- [192, "Agrave"],
5031
- [193, "Aacute"],
5032
- [194, "Acircumflex"],
5033
- [195, "Atilde"],
5034
- [196, "Adieresis"],
5035
- [197, "Aring"],
5036
- [198, "AE"],
5037
- [199, "Ccedilla"],
5038
- [200, "Egrave"],
5039
- [201, "Eacute"],
5040
- [202, "Ecircumflex"],
5041
- [203, "Edieresis"],
5042
- [204, "Igrave"],
5043
- [205, "Iacute"],
5044
- [206, "Icircumflex"],
5045
- [207, "Idieresis"],
5046
- [208, "Eth"],
5047
- [209, "Ntilde"],
5048
- [210, "Ograve"],
5049
- [211, "Oacute"],
5050
- [212, "Ocircumflex"],
5051
- [213, "Otilde"],
5052
- [214, "Odieresis"],
5053
- [215, "multiply"],
5054
- [216, "Oslash"],
5055
- [217, "Ugrave"],
5056
- [218, "Uacute"],
5057
- [219, "Ucircumflex"],
5058
- [220, "Udieresis"],
5059
- [221, "Yacute"],
5060
- [222, "Thorn"],
5061
- [223, "germandbls"],
5062
- [224, "agrave"],
5063
- [225, "aacute"],
5064
- [226, "acircumflex"],
5065
- [227, "atilde"],
5066
- [228, "adieresis"],
5067
- [229, "aring"],
5068
- [230, "ae"],
5069
- [231, "ccedilla"],
5070
- [232, "egrave"],
5071
- [233, "eacute"],
5072
- [234, "ecircumflex"],
5073
- [235, "edieresis"],
5074
- [236, "igrave"],
5075
- [237, "iacute"],
5076
- [238, "icircumflex"],
5077
- [239, "idieresis"],
5078
- [240, "eth"],
5079
- [241, "ntilde"],
5080
- [242, "ograve"],
5081
- [243, "oacute"],
5082
- [244, "ocircumflex"],
5083
- [245, "otilde"],
5084
- [246, "odieresis"],
5085
- [247, "divide"],
5086
- [248, "oslash"],
5087
- [249, "ugrave"],
5088
- [250, "uacute"],
5089
- [251, "ucircumflex"],
5090
- [252, "udieresis"],
5091
- [253, "yacute"],
5092
- [254, "thorn"],
5093
- [255, "ydieresis"],
5094
- [8211, "endash"],
5095
- [8212, "emdash"],
5096
- [8216, "quoteleft"],
5097
- [8217, "quoteright"],
5098
- [8218, "quotesinglbase"],
5099
- [8220, "quotedblleft"],
5100
- [8221, "quotedblright"],
5101
- [8222, "quotedblbase"],
5102
- [8224, "dagger"],
5103
- [8225, "daggerdbl"],
5104
- [8226, "bullet"],
5105
- [8230, "ellipsis"],
5106
- [8240, "perthousand"],
5107
- [8249, "guilsinglleft"],
5108
- [8250, "guilsinglright"],
5109
- [8364, "Euro"],
5110
- [8482, "trademark"],
5111
- [64257, "fi"],
5112
- [64258, "fl"]
5113
- ]);
5114
-
5115
4875
  //#endregion
5116
4876
  //#region src/io/scanner.ts
5117
4877
  /**
@@ -10961,9 +10721,9 @@ function parseEmbeddedProgram(descriptor, options) {
10961
10721
  * Try to parse a TrueType font from /FontFile2.
10962
10722
  */
10963
10723
  function tryParseFontFile2(descriptor, options) {
10964
- const fontFile2 = resolveValue(descriptor.get("FontFile2"), options);
10965
- if (!fontFile2) return null;
10966
- const data = options.decodeStream(fontFile2);
10724
+ const fontFile2 = descriptor.get("FontFile2", options.resolver);
10725
+ if (!(fontFile2 instanceof PdfStream)) return null;
10726
+ const data = fontFile2.getDecodedData();
10967
10727
  if (!data || data.length === 0) return null;
10968
10728
  try {
10969
10729
  return new TrueTypeFontProgram(parseTTF(data, { isEmbedded: true }), data);
@@ -10976,10 +10736,10 @@ function tryParseFontFile2(descriptor, options) {
10976
10736
  * Try to parse a CFF or OpenType font from /FontFile3.
10977
10737
  */
10978
10738
  function tryParseFontFile3(descriptor, options) {
10979
- const fontFile3 = resolveValue(descriptor.get("FontFile3"), options);
10980
- if (!fontFile3) return null;
10739
+ const fontFile3 = descriptor.get("FontFile3", options.resolver);
10740
+ if (!(fontFile3 instanceof PdfStream)) return null;
10981
10741
  const subtype = getStreamSubtype(fontFile3);
10982
- const data = options.decodeStream(fontFile3);
10742
+ const data = fontFile3.getDecodedData();
10983
10743
  if (!data || data.length === 0) return null;
10984
10744
  try {
10985
10745
  if (subtype === "OpenType") return new TrueTypeFontProgram(parseTTF(data, { isEmbedded: true }), data);
@@ -11000,9 +10760,9 @@ function tryParseFontFile3(descriptor, options) {
11000
10760
  * Try to parse a Type1 font from /FontFile.
11001
10761
  */
11002
10762
  function tryParseFontFile(descriptor, options) {
11003
- const fontFile = resolveValue(descriptor.get("FontFile"), options);
11004
- if (!fontFile) return null;
11005
- const data = options.decodeStream(fontFile);
10763
+ const fontFile = descriptor.get("FontFile", options.resolver);
10764
+ if (!(fontFile instanceof PdfStream)) return null;
10765
+ const data = fontFile.getDecodedData();
11006
10766
  if (!data || data.length === 0) return null;
11007
10767
  try {
11008
10768
  return new Type1FontProgram(parsePfb(data), data);
@@ -11035,15 +10795,7 @@ function tryAutoDetectFontFile3(data) {
11035
10795
  * Get the /Subtype from a stream dictionary.
11036
10796
  */
11037
10797
  function getStreamSubtype(stream) {
11038
- if (stream && stream instanceof PdfStream) return stream.getName("Subtype")?.value;
11039
- }
11040
- /**
11041
- * Resolve a value through indirect references.
11042
- */
11043
- function resolveValue(value, options) {
11044
- if (!value) return null;
11045
- if (options.resolveRef && value instanceof PdfRef) return options.resolveRef(value);
11046
- return value;
10798
+ if (stream) return stream.getName("Subtype")?.value;
11047
10799
  }
11048
10800
  /**
11049
10801
  * Parse a font program directly from bytes.
@@ -11078,119 +10830,838 @@ function parseFontProgram(data) {
11078
10830
  }
11079
10831
 
11080
10832
  //#endregion
11081
- //#region src/fonts/encodings/glyph-list.ts
10833
+ //#region src/fonts/font-descriptor.ts
11082
10834
  /**
11083
- * Glyph name to Unicode mapping.
10835
+ * Font flags as defined in PDF spec Table 123.
10836
+ */
10837
+ const FontFlags = {
10838
+ FIXED_PITCH: 1,
10839
+ SERIF: 2,
10840
+ SYMBOLIC: 4,
10841
+ SCRIPT: 8,
10842
+ NONSYMBOLIC: 32,
10843
+ ITALIC: 64,
10844
+ ALL_CAP: 65536,
10845
+ SMALL_CAP: 1 << 17,
10846
+ FORCE_BOLD: 1 << 18
10847
+ };
10848
+ /**
10849
+ * FontDescriptor contains font metrics and flags.
10850
+ */
10851
+ var FontDescriptor = class FontDescriptor {
10852
+ fontName;
10853
+ flags;
10854
+ fontBBox;
10855
+ italicAngle;
10856
+ ascent;
10857
+ descent;
10858
+ leading;
10859
+ capHeight;
10860
+ xHeight;
10861
+ stemV;
10862
+ stemH;
10863
+ avgWidth;
10864
+ maxWidth;
10865
+ missingWidth;
10866
+ constructor(data) {
10867
+ this.fontName = data.fontName;
10868
+ this.flags = data.flags;
10869
+ this.fontBBox = data.fontBBox;
10870
+ this.italicAngle = data.italicAngle;
10871
+ this.ascent = data.ascent;
10872
+ this.descent = data.descent;
10873
+ this.leading = data.leading;
10874
+ this.capHeight = data.capHeight;
10875
+ this.xHeight = data.xHeight;
10876
+ this.stemV = data.stemV;
10877
+ this.stemH = data.stemH;
10878
+ this.avgWidth = data.avgWidth;
10879
+ this.maxWidth = data.maxWidth;
10880
+ this.missingWidth = data.missingWidth;
10881
+ }
10882
+ /** Check if font is fixed-pitch (monospace) */
10883
+ get isFixedPitch() {
10884
+ return (this.flags & FontFlags.FIXED_PITCH) !== 0;
10885
+ }
10886
+ /** Check if font is serif */
10887
+ get isSerif() {
10888
+ return (this.flags & FontFlags.SERIF) !== 0;
10889
+ }
10890
+ /** Check if font is symbolic (uses custom encoding) */
10891
+ get isSymbolic() {
10892
+ return (this.flags & FontFlags.SYMBOLIC) !== 0;
10893
+ }
10894
+ /** Check if font is script (cursive) */
10895
+ get isScript() {
10896
+ return (this.flags & FontFlags.SCRIPT) !== 0;
10897
+ }
10898
+ /** Check if font is non-symbolic (uses standard encoding) */
10899
+ get isNonSymbolic() {
10900
+ return (this.flags & FontFlags.NONSYMBOLIC) !== 0;
10901
+ }
10902
+ /** Check if font is italic */
10903
+ get isItalic() {
10904
+ return (this.flags & FontFlags.ITALIC) !== 0;
10905
+ }
10906
+ /** Check if font is all caps */
10907
+ get isAllCap() {
10908
+ return (this.flags & FontFlags.ALL_CAP) !== 0;
10909
+ }
10910
+ /** Check if font is small caps */
10911
+ get isSmallCap() {
10912
+ return (this.flags & FontFlags.SMALL_CAP) !== 0;
10913
+ }
10914
+ /** Check if font should be bold */
10915
+ get isForceBold() {
10916
+ return (this.flags & FontFlags.FORCE_BOLD) !== 0;
10917
+ }
10918
+ /**
10919
+ * Parse FontDescriptor from a PDF dictionary.
10920
+ */
10921
+ static parse(dict) {
10922
+ const bboxArray = dict.getArray("FontBBox");
10923
+ const fontBBox = [
10924
+ 0,
10925
+ 0,
10926
+ 0,
10927
+ 0
10928
+ ];
10929
+ if (bboxArray && bboxArray.length >= 4) for (let i = 0; i < 4; i++) {
10930
+ const item = bboxArray.at(i);
10931
+ if (item instanceof PdfNumber) fontBBox[i] = item.value;
10932
+ }
10933
+ return new FontDescriptor({
10934
+ fontName: dict.getName("FontName")?.value ?? "",
10935
+ flags: dict.getNumber("Flags")?.value ?? 0,
10936
+ fontBBox,
10937
+ italicAngle: dict.getNumber("ItalicAngle")?.value ?? 0,
10938
+ ascent: dict.getNumber("Ascent")?.value ?? 0,
10939
+ descent: dict.getNumber("Descent")?.value ?? 0,
10940
+ leading: dict.getNumber("Leading")?.value ?? 0,
10941
+ capHeight: dict.getNumber("CapHeight")?.value ?? 0,
10942
+ xHeight: dict.getNumber("XHeight")?.value ?? 0,
10943
+ stemV: dict.getNumber("StemV")?.value ?? 0,
10944
+ stemH: dict.getNumber("StemH")?.value ?? 0,
10945
+ avgWidth: dict.getNumber("AvgWidth")?.value ?? 0,
10946
+ maxWidth: dict.getNumber("MaxWidth")?.value ?? 0,
10947
+ missingWidth: dict.getNumber("MissingWidth")?.value ?? 0
10948
+ });
10949
+ }
10950
+ };
10951
+
10952
+ //#endregion
10953
+ //#region src/fonts/pdf-font.ts
10954
+ /**
10955
+ * Abstract base class for PDF fonts.
10956
+ */
10957
+ var PdfFont = class {
10958
+ /**
10959
+ * Get width of text in points at a given font size.
10960
+ *
10961
+ * @param text - Unicode text to measure
10962
+ * @param fontSize - Font size in points
10963
+ * @returns Width in points
10964
+ */
10965
+ getTextWidth(text, fontSize) {
10966
+ let totalWidth = 0;
10967
+ const codes = this.encodeText(text);
10968
+ for (const code of codes) totalWidth += this.getWidth(code);
10969
+ return totalWidth * fontSize / 1e3;
10970
+ }
10971
+ };
10972
+
10973
+ //#endregion
10974
+ //#region src/fonts/embedded-font.ts
10975
+ /**
10976
+ * EmbeddedFont represents a font that will be embedded into a PDF.
11084
10977
  *
11085
- * This is a subset of the Adobe Glyph List (AGL) covering the glyphs
11086
- * used in standard PDF encodings. For the full list, see:
11087
- * https://github.com/adobe-type-tools/agl-aglfn
10978
+ * Usage:
10979
+ * ```typescript
10980
+ * const fontBytes = await fs.readFile("NotoSans-Regular.ttf");
10981
+ * const font = EmbeddedFont.fromBytes(fontBytes);
11088
10982
  *
11089
- * Reference: pdf.js glyphlist.js
10983
+ * // Check if text can be encoded
10984
+ * if (font.canEncode("Hello ")) {
10985
+ * const codes = font.encodeText("Hello ");
10986
+ * const width = font.getTextWidth("Hello ", 12);
10987
+ * }
10988
+ * ```
11090
10989
  */
11091
- const GLYPH_TO_UNICODE = {
11092
- space: 32,
11093
- exclam: 33,
11094
- quotedbl: 34,
11095
- numbersign: 35,
11096
- dollar: 36,
11097
- percent: 37,
11098
- ampersand: 38,
11099
- quotesingle: 39,
11100
- parenleft: 40,
11101
- parenright: 41,
11102
- asterisk: 42,
11103
- plus: 43,
11104
- comma: 44,
11105
- hyphen: 45,
11106
- period: 46,
11107
- slash: 47,
11108
- zero: 48,
11109
- one: 49,
11110
- two: 50,
11111
- three: 51,
11112
- four: 52,
11113
- five: 53,
11114
- six: 54,
11115
- seven: 55,
11116
- eight: 56,
11117
- nine: 57,
11118
- colon: 58,
11119
- semicolon: 59,
11120
- less: 60,
11121
- equal: 61,
11122
- greater: 62,
11123
- question: 63,
11124
- at: 64,
11125
- A: 65,
11126
- B: 66,
11127
- C: 67,
11128
- D: 68,
11129
- E: 69,
11130
- F: 70,
11131
- G: 71,
11132
- H: 72,
11133
- I: 73,
11134
- J: 74,
11135
- K: 75,
11136
- L: 76,
11137
- M: 77,
11138
- N: 78,
11139
- O: 79,
11140
- P: 80,
11141
- Q: 81,
11142
- R: 82,
11143
- S: 83,
11144
- T: 84,
11145
- U: 85,
11146
- V: 86,
11147
- W: 87,
11148
- X: 88,
11149
- Y: 89,
11150
- Z: 90,
11151
- bracketleft: 91,
11152
- backslash: 92,
11153
- bracketright: 93,
11154
- asciicircum: 94,
11155
- underscore: 95,
11156
- grave: 96,
11157
- a: 97,
11158
- b: 98,
11159
- c: 99,
11160
- d: 100,
11161
- e: 101,
11162
- f: 102,
11163
- g: 103,
11164
- h: 104,
11165
- i: 105,
11166
- j: 106,
11167
- k: 107,
11168
- l: 108,
11169
- m: 109,
11170
- n: 110,
11171
- o: 111,
11172
- p: 112,
11173
- q: 113,
11174
- r: 114,
11175
- s: 115,
11176
- t: 116,
11177
- u: 117,
11178
- v: 118,
11179
- w: 119,
11180
- x: 120,
11181
- y: 121,
11182
- z: 122,
11183
- braceleft: 123,
11184
- bar: 124,
11185
- braceright: 125,
11186
- asciitilde: 126,
11187
- exclamdown: 161,
11188
- cent: 162,
11189
- sterling: 163,
11190
- currency: 164,
11191
- yen: 165,
11192
- brokenbar: 166,
11193
- section: 167,
10990
+ var EmbeddedFont = class EmbeddedFont extends PdfFont {
10991
+ subtype = "Type0";
10992
+ /** Underlying font program */
10993
+ fontProgram;
10994
+ /** Original font data */
10995
+ fontData;
10996
+ /** Track used glyphs for subsetting (GID -> code points that use it) */
10997
+ usedGlyphs = new Map([[0, /* @__PURE__ */ new Set()]]);
10998
+ /** Track used code points for ToUnicode (codePoint -> GID) */
10999
+ usedCodePoints = /* @__PURE__ */ new Map();
11000
+ /** Subset tag (generated during save) */
11001
+ _subsetTag = null;
11002
+ /** Whether this font is used in a form field (prevents subsetting) */
11003
+ _usedInForm = false;
11004
+ /** Cached descriptor */
11005
+ _descriptor = null;
11006
+ constructor(fontProgram, fontData) {
11007
+ super();
11008
+ this.fontProgram = fontProgram;
11009
+ this.fontData = fontData;
11010
+ }
11011
+ /**
11012
+ * Create an EmbeddedFont from raw font bytes.
11013
+ *
11014
+ * @param data - TTF, OTF, or Type1 font data
11015
+ * @param options - Embedding options
11016
+ * @returns EmbeddedFont instance
11017
+ * @throws {Error} if font format is not recognized
11018
+ */
11019
+ static fromBytes(data, _options) {
11020
+ return new EmbeddedFont(parseFontProgram(data), data);
11021
+ }
11022
+ /**
11023
+ * Create an EmbeddedFont from an already-parsed TrueType font.
11024
+ */
11025
+ static fromTrueTypeFont(font, data) {
11026
+ return new EmbeddedFont(new TrueTypeFontProgram(font, data), data);
11027
+ }
11028
+ /**
11029
+ * Get the base font name.
11030
+ * During save, this will include a subset tag prefix (e.g., "ABCDEF+FontName").
11031
+ */
11032
+ get baseFontName() {
11033
+ const name = this.fontProgram.postScriptName ?? "Unknown";
11034
+ return this._subsetTag ? `${this._subsetTag}+${name}` : name;
11035
+ }
11036
+ /**
11037
+ * Get the font descriptor.
11038
+ */
11039
+ get descriptor() {
11040
+ if (!this._descriptor) this._descriptor = this.buildDescriptor();
11041
+ return this._descriptor;
11042
+ }
11043
+ /**
11044
+ * Get the underlying font program.
11045
+ */
11046
+ get program() {
11047
+ return this.fontProgram;
11048
+ }
11049
+ /**
11050
+ * Get the original font data.
11051
+ */
11052
+ get data() {
11053
+ return this.fontData;
11054
+ }
11055
+ /**
11056
+ * Get the subset tag (only available after save).
11057
+ */
11058
+ get subsetTag() {
11059
+ return this._subsetTag;
11060
+ }
11061
+ /**
11062
+ * Set the subset tag (called during save).
11063
+ */
11064
+ setSubsetTag(tag) {
11065
+ this._subsetTag = tag;
11066
+ }
11067
+ /**
11068
+ * Get all used glyph IDs.
11069
+ */
11070
+ getUsedGlyphIds() {
11071
+ return [...this.usedGlyphs.keys()].sort((a, b) => a - b);
11072
+ }
11073
+ /**
11074
+ * Get mapping from code point to GID.
11075
+ */
11076
+ getCodePointToGidMap() {
11077
+ return new Map(this.usedCodePoints);
11078
+ }
11079
+ /**
11080
+ * Get mapping from GID to Unicode code point.
11081
+ *
11082
+ * This is used for building the /W widths array and ToUnicode CMap.
11083
+ * Since the content stream contains GIDs (with CIDToGIDMap /Identity),
11084
+ * the /W array must be keyed by GID, and ToUnicode must map GID → Unicode.
11085
+ *
11086
+ * If multiple code points map to the same GID, returns the first one found.
11087
+ */
11088
+ getGidToCodePointMap() {
11089
+ const result = /* @__PURE__ */ new Map();
11090
+ for (const [gid, codePoints] of this.usedGlyphs) if (codePoints.size > 0) {
11091
+ const firstCodePoint = codePoints.values().next().value;
11092
+ if (firstCodePoint !== void 0) result.set(gid, firstCodePoint);
11093
+ }
11094
+ return result;
11095
+ }
11096
+ /**
11097
+ * Iterate over text, tracking glyph usage and returning codePoint/GID pairs.
11098
+ * This is the shared implementation for encodeText and encodeTextToGids.
11099
+ */
11100
+ trackAndEncode(text) {
11101
+ const result = [];
11102
+ for (const char of text) {
11103
+ const codePoint = char.codePointAt(0);
11104
+ if (codePoint === void 0) continue;
11105
+ const gid = this.fontProgram.getGlyphId(codePoint);
11106
+ if (!this.usedGlyphs.has(gid)) this.usedGlyphs.set(gid, /* @__PURE__ */ new Set());
11107
+ this.usedGlyphs.get(gid).add(codePoint);
11108
+ this.usedCodePoints.set(codePoint, gid);
11109
+ result.push({
11110
+ codePoint,
11111
+ gid
11112
+ });
11113
+ }
11114
+ return result;
11115
+ }
11116
+ /**
11117
+ * Encode text to character codes.
11118
+ *
11119
+ * Returns Unicode code points, which is intuitive for users.
11120
+ * The conversion to glyph IDs happens internally when writing to the PDF.
11121
+ *
11122
+ * Also tracks glyph usage for subsetting.
11123
+ */
11124
+ encodeText(text) {
11125
+ return this.trackAndEncode(text).map((e) => e.codePoint);
11126
+ }
11127
+ /**
11128
+ * Encode text to glyph IDs for PDF content stream.
11129
+ *
11130
+ * This is an internal method used when writing to the PDF.
11131
+ * With CIDToGIDMap /Identity, the content stream must contain GIDs.
11132
+ *
11133
+ * @internal
11134
+ */
11135
+ encodeTextToGids(text) {
11136
+ return this.trackAndEncode(text).map((e) => e.gid);
11137
+ }
11138
+ /**
11139
+ * Convert a code point to its glyph ID.
11140
+ *
11141
+ * @internal
11142
+ */
11143
+ codePointToGid(codePoint) {
11144
+ return this.fontProgram.getGlyphId(codePoint);
11145
+ }
11146
+ /**
11147
+ * Get width of a character in glyph units (1000 = 1 em).
11148
+ *
11149
+ * Takes a Unicode code point (user-friendly API).
11150
+ */
11151
+ getWidth(code) {
11152
+ const gid = this.fontProgram.getGlyphId(code);
11153
+ const width = this.fontProgram.getAdvanceWidth(gid);
11154
+ return Math.round(width * 1e3 / this.fontProgram.unitsPerEm);
11155
+ }
11156
+ /**
11157
+ * Decode character code to Unicode string.
11158
+ *
11159
+ * For embedded fonts with Identity-H encoding, the code is the code point,
11160
+ * so this just converts the code point back to a string.
11161
+ */
11162
+ toUnicode(code) {
11163
+ return String.fromCodePoint(code);
11164
+ }
11165
+ /**
11166
+ * Check if the font can encode the given text.
11167
+ * Returns true if all characters have glyphs in the font.
11168
+ */
11169
+ canEncode(text) {
11170
+ for (const char of text) {
11171
+ const codePoint = char.codePointAt(0);
11172
+ if (codePoint === void 0) continue;
11173
+ if (!this.fontProgram.hasGlyph(codePoint)) return false;
11174
+ }
11175
+ return true;
11176
+ }
11177
+ /**
11178
+ * Get the characters that cannot be encoded.
11179
+ */
11180
+ getUnencodableCharacters(text) {
11181
+ const unencodable = [];
11182
+ for (const char of text) {
11183
+ const codePoint = char.codePointAt(0);
11184
+ if (codePoint === void 0) continue;
11185
+ if (!this.fontProgram.hasGlyph(codePoint)) unencodable.push(char);
11186
+ }
11187
+ return unencodable;
11188
+ }
11189
+ /**
11190
+ * Reset glyph usage tracking.
11191
+ * Call this before re-encoding if you want a fresh subset.
11192
+ */
11193
+ resetUsage() {
11194
+ this.usedGlyphs.clear();
11195
+ this.usedGlyphs.set(0, /* @__PURE__ */ new Set());
11196
+ this.usedCodePoints.clear();
11197
+ this._subsetTag = null;
11198
+ }
11199
+ /**
11200
+ * Mark this font as used in a form field.
11201
+ *
11202
+ * Fonts used in form fields cannot be subsetted because users may type
11203
+ * any character at runtime. This method is called automatically when
11204
+ * an EmbeddedFont is used in form field appearances.
11205
+ */
11206
+ markUsedInForm() {
11207
+ this._usedInForm = true;
11208
+ }
11209
+ /**
11210
+ * Check if this font is used in a form field.
11211
+ */
11212
+ get usedInForm() {
11213
+ return this._usedInForm;
11214
+ }
11215
+ /**
11216
+ * Check if this font can be subsetted.
11217
+ *
11218
+ * Returns false if the font is used in a form field (since users can
11219
+ * type any character at runtime).
11220
+ */
11221
+ canSubset() {
11222
+ return !this._usedInForm;
11223
+ }
11224
+ /**
11225
+ * Get width of text in points at a given font size.
11226
+ *
11227
+ * Alias for getTextWidth() to match Standard14Font API.
11228
+ *
11229
+ * @param text - The text to measure
11230
+ * @param size - Font size in points
11231
+ * @returns Width in points
11232
+ */
11233
+ widthOfTextAtSize(text, size) {
11234
+ return this.getTextWidth(text, size);
11235
+ }
11236
+ /**
11237
+ * Get the height of the font at a given size.
11238
+ *
11239
+ * This returns the full height from descender to ascender.
11240
+ *
11241
+ * @param size - Font size in points
11242
+ * @returns Height in points
11243
+ */
11244
+ heightAtSize(size) {
11245
+ const desc = this.descriptor;
11246
+ if (!desc) return size;
11247
+ return (desc.ascent - desc.descent) * size / 1e3;
11248
+ }
11249
+ /**
11250
+ * Calculate font size needed to achieve a specific text height.
11251
+ *
11252
+ * @param height - Desired height in points
11253
+ * @returns Font size in points
11254
+ */
11255
+ sizeAtHeight(height) {
11256
+ const desc = this.descriptor;
11257
+ if (!desc) return height;
11258
+ const unitsHeight = desc.ascent - desc.descent;
11259
+ return height * 1e3 / unitsHeight;
11260
+ }
11261
+ /**
11262
+ * Calculate font size needed for text to fit a specific width.
11263
+ *
11264
+ * @param text - The text to measure
11265
+ * @param width - Desired width in points
11266
+ * @returns Font size in points
11267
+ */
11268
+ sizeAtWidth(text, width) {
11269
+ if (text.length === 0) return 0;
11270
+ const codes = this.encodeText(text);
11271
+ let totalWidth = 0;
11272
+ for (const code of codes) totalWidth += this.getWidth(code);
11273
+ if (totalWidth === 0) return 0;
11274
+ return width * 1e3 / totalWidth;
11275
+ }
11276
+ /**
11277
+ * Build a FontDescriptor from the font program.
11278
+ */
11279
+ buildDescriptor() {
11280
+ const program = this.fontProgram;
11281
+ const bbox = program.bbox;
11282
+ const scale = 1e3 / program.unitsPerEm;
11283
+ return new FontDescriptor({
11284
+ fontName: program.postScriptName ?? "Unknown",
11285
+ flags: this.computeFlags(),
11286
+ fontBBox: [
11287
+ Math.round(bbox[0] * scale),
11288
+ Math.round(bbox[1] * scale),
11289
+ Math.round(bbox[2] * scale),
11290
+ Math.round(bbox[3] * scale)
11291
+ ],
11292
+ italicAngle: program.italicAngle,
11293
+ ascent: Math.round(program.ascent * scale),
11294
+ descent: Math.round(program.descent * scale),
11295
+ leading: 0,
11296
+ capHeight: Math.round(program.capHeight * scale),
11297
+ xHeight: Math.round(program.xHeight * scale),
11298
+ stemV: program.stemV,
11299
+ stemH: 0,
11300
+ avgWidth: 0,
11301
+ maxWidth: 0,
11302
+ missingWidth: this.getWidth(0)
11303
+ });
11304
+ }
11305
+ /**
11306
+ * Compute font flags for the descriptor.
11307
+ */
11308
+ computeFlags() {
11309
+ let flags = 0;
11310
+ if (this.fontProgram.isFixedPitch) flags |= 1;
11311
+ flags |= 4;
11312
+ if (this.fontProgram.italicAngle !== 0) flags |= 64;
11313
+ return flags;
11314
+ }
11315
+ };
11316
+
11317
+ //#endregion
11318
+ //#region src/helpers/unicode.ts
11319
+ /**
11320
+ * Unicode utilities for PDF text handling.
11321
+ *
11322
+ * Provides mappings between Unicode code points and PostScript glyph names.
11323
+ */
11324
+ /**
11325
+ * Map Unicode code point to PostScript glyph name.
11326
+ * Returns undefined if no mapping exists.
11327
+ */
11328
+ function unicodeToGlyphName(unicode) {
11329
+ return UNICODE_TO_GLYPH.get(unicode);
11330
+ }
11331
+ /**
11332
+ * Common Unicode to glyph name mappings.
11333
+ * Covers ASCII and common Latin-1 extended characters.
11334
+ *
11335
+ * For a complete mapping, see the Adobe Glyph List:
11336
+ * https://github.com/adobe-type-tools/agl-aglfn
11337
+ */
11338
+ const UNICODE_TO_GLYPH = new Map([
11339
+ [32, "space"],
11340
+ [33, "exclam"],
11341
+ [34, "quotedbl"],
11342
+ [35, "numbersign"],
11343
+ [36, "dollar"],
11344
+ [37, "percent"],
11345
+ [38, "ampersand"],
11346
+ [39, "quotesingle"],
11347
+ [40, "parenleft"],
11348
+ [41, "parenright"],
11349
+ [42, "asterisk"],
11350
+ [43, "plus"],
11351
+ [44, "comma"],
11352
+ [45, "hyphen"],
11353
+ [46, "period"],
11354
+ [47, "slash"],
11355
+ [48, "zero"],
11356
+ [49, "one"],
11357
+ [50, "two"],
11358
+ [51, "three"],
11359
+ [52, "four"],
11360
+ [53, "five"],
11361
+ [54, "six"],
11362
+ [55, "seven"],
11363
+ [56, "eight"],
11364
+ [57, "nine"],
11365
+ [58, "colon"],
11366
+ [59, "semicolon"],
11367
+ [60, "less"],
11368
+ [61, "equal"],
11369
+ [62, "greater"],
11370
+ [63, "question"],
11371
+ [64, "at"],
11372
+ [65, "A"],
11373
+ [66, "B"],
11374
+ [67, "C"],
11375
+ [68, "D"],
11376
+ [69, "E"],
11377
+ [70, "F"],
11378
+ [71, "G"],
11379
+ [72, "H"],
11380
+ [73, "I"],
11381
+ [74, "J"],
11382
+ [75, "K"],
11383
+ [76, "L"],
11384
+ [77, "M"],
11385
+ [78, "N"],
11386
+ [79, "O"],
11387
+ [80, "P"],
11388
+ [81, "Q"],
11389
+ [82, "R"],
11390
+ [83, "S"],
11391
+ [84, "T"],
11392
+ [85, "U"],
11393
+ [86, "V"],
11394
+ [87, "W"],
11395
+ [88, "X"],
11396
+ [89, "Y"],
11397
+ [90, "Z"],
11398
+ [91, "bracketleft"],
11399
+ [92, "backslash"],
11400
+ [93, "bracketright"],
11401
+ [94, "asciicircum"],
11402
+ [95, "underscore"],
11403
+ [96, "grave"],
11404
+ [97, "a"],
11405
+ [98, "b"],
11406
+ [99, "c"],
11407
+ [100, "d"],
11408
+ [101, "e"],
11409
+ [102, "f"],
11410
+ [103, "g"],
11411
+ [104, "h"],
11412
+ [105, "i"],
11413
+ [106, "j"],
11414
+ [107, "k"],
11415
+ [108, "l"],
11416
+ [109, "m"],
11417
+ [110, "n"],
11418
+ [111, "o"],
11419
+ [112, "p"],
11420
+ [113, "q"],
11421
+ [114, "r"],
11422
+ [115, "s"],
11423
+ [116, "t"],
11424
+ [117, "u"],
11425
+ [118, "v"],
11426
+ [119, "w"],
11427
+ [120, "x"],
11428
+ [121, "y"],
11429
+ [122, "z"],
11430
+ [123, "braceleft"],
11431
+ [124, "bar"],
11432
+ [125, "braceright"],
11433
+ [126, "asciitilde"],
11434
+ [160, "nbspace"],
11435
+ [161, "exclamdown"],
11436
+ [162, "cent"],
11437
+ [163, "sterling"],
11438
+ [164, "currency"],
11439
+ [165, "yen"],
11440
+ [166, "brokenbar"],
11441
+ [167, "section"],
11442
+ [168, "dieresis"],
11443
+ [169, "copyright"],
11444
+ [170, "ordfeminine"],
11445
+ [171, "guillemotleft"],
11446
+ [172, "logicalnot"],
11447
+ [173, "softhyphen"],
11448
+ [174, "registered"],
11449
+ [175, "macron"],
11450
+ [176, "degree"],
11451
+ [177, "plusminus"],
11452
+ [178, "twosuperior"],
11453
+ [179, "threesuperior"],
11454
+ [180, "acute"],
11455
+ [181, "mu"],
11456
+ [182, "paragraph"],
11457
+ [183, "periodcentered"],
11458
+ [184, "cedilla"],
11459
+ [185, "onesuperior"],
11460
+ [186, "ordmasculine"],
11461
+ [187, "guillemotright"],
11462
+ [188, "onequarter"],
11463
+ [189, "onehalf"],
11464
+ [190, "threequarters"],
11465
+ [191, "questiondown"],
11466
+ [192, "Agrave"],
11467
+ [193, "Aacute"],
11468
+ [194, "Acircumflex"],
11469
+ [195, "Atilde"],
11470
+ [196, "Adieresis"],
11471
+ [197, "Aring"],
11472
+ [198, "AE"],
11473
+ [199, "Ccedilla"],
11474
+ [200, "Egrave"],
11475
+ [201, "Eacute"],
11476
+ [202, "Ecircumflex"],
11477
+ [203, "Edieresis"],
11478
+ [204, "Igrave"],
11479
+ [205, "Iacute"],
11480
+ [206, "Icircumflex"],
11481
+ [207, "Idieresis"],
11482
+ [208, "Eth"],
11483
+ [209, "Ntilde"],
11484
+ [210, "Ograve"],
11485
+ [211, "Oacute"],
11486
+ [212, "Ocircumflex"],
11487
+ [213, "Otilde"],
11488
+ [214, "Odieresis"],
11489
+ [215, "multiply"],
11490
+ [216, "Oslash"],
11491
+ [217, "Ugrave"],
11492
+ [218, "Uacute"],
11493
+ [219, "Ucircumflex"],
11494
+ [220, "Udieresis"],
11495
+ [221, "Yacute"],
11496
+ [222, "Thorn"],
11497
+ [223, "germandbls"],
11498
+ [224, "agrave"],
11499
+ [225, "aacute"],
11500
+ [226, "acircumflex"],
11501
+ [227, "atilde"],
11502
+ [228, "adieresis"],
11503
+ [229, "aring"],
11504
+ [230, "ae"],
11505
+ [231, "ccedilla"],
11506
+ [232, "egrave"],
11507
+ [233, "eacute"],
11508
+ [234, "ecircumflex"],
11509
+ [235, "edieresis"],
11510
+ [236, "igrave"],
11511
+ [237, "iacute"],
11512
+ [238, "icircumflex"],
11513
+ [239, "idieresis"],
11514
+ [240, "eth"],
11515
+ [241, "ntilde"],
11516
+ [242, "ograve"],
11517
+ [243, "oacute"],
11518
+ [244, "ocircumflex"],
11519
+ [245, "otilde"],
11520
+ [246, "odieresis"],
11521
+ [247, "divide"],
11522
+ [248, "oslash"],
11523
+ [249, "ugrave"],
11524
+ [250, "uacute"],
11525
+ [251, "ucircumflex"],
11526
+ [252, "udieresis"],
11527
+ [253, "yacute"],
11528
+ [254, "thorn"],
11529
+ [255, "ydieresis"],
11530
+ [8211, "endash"],
11531
+ [8212, "emdash"],
11532
+ [8216, "quoteleft"],
11533
+ [8217, "quoteright"],
11534
+ [8218, "quotesinglbase"],
11535
+ [8220, "quotedblleft"],
11536
+ [8221, "quotedblright"],
11537
+ [8222, "quotedblbase"],
11538
+ [8224, "dagger"],
11539
+ [8225, "daggerdbl"],
11540
+ [8226, "bullet"],
11541
+ [8230, "ellipsis"],
11542
+ [8240, "perthousand"],
11543
+ [8249, "guilsinglleft"],
11544
+ [8250, "guilsinglright"],
11545
+ [8364, "Euro"],
11546
+ [8482, "trademark"],
11547
+ [64257, "fi"],
11548
+ [64258, "fl"]
11549
+ ]);
11550
+
11551
+ //#endregion
11552
+ //#region src/fonts/encodings/glyph-list.ts
11553
+ /**
11554
+ * Glyph name to Unicode mapping.
11555
+ *
11556
+ * This is a subset of the Adobe Glyph List (AGL) covering the glyphs
11557
+ * used in standard PDF encodings. For the full list, see:
11558
+ * https://github.com/adobe-type-tools/agl-aglfn
11559
+ *
11560
+ * Reference: pdf.js glyphlist.js
11561
+ */
11562
+ const GLYPH_TO_UNICODE = {
11563
+ space: 32,
11564
+ exclam: 33,
11565
+ quotedbl: 34,
11566
+ numbersign: 35,
11567
+ dollar: 36,
11568
+ percent: 37,
11569
+ ampersand: 38,
11570
+ quotesingle: 39,
11571
+ parenleft: 40,
11572
+ parenright: 41,
11573
+ asterisk: 42,
11574
+ plus: 43,
11575
+ comma: 44,
11576
+ hyphen: 45,
11577
+ period: 46,
11578
+ slash: 47,
11579
+ zero: 48,
11580
+ one: 49,
11581
+ two: 50,
11582
+ three: 51,
11583
+ four: 52,
11584
+ five: 53,
11585
+ six: 54,
11586
+ seven: 55,
11587
+ eight: 56,
11588
+ nine: 57,
11589
+ colon: 58,
11590
+ semicolon: 59,
11591
+ less: 60,
11592
+ equal: 61,
11593
+ greater: 62,
11594
+ question: 63,
11595
+ at: 64,
11596
+ A: 65,
11597
+ B: 66,
11598
+ C: 67,
11599
+ D: 68,
11600
+ E: 69,
11601
+ F: 70,
11602
+ G: 71,
11603
+ H: 72,
11604
+ I: 73,
11605
+ J: 74,
11606
+ K: 75,
11607
+ L: 76,
11608
+ M: 77,
11609
+ N: 78,
11610
+ O: 79,
11611
+ P: 80,
11612
+ Q: 81,
11613
+ R: 82,
11614
+ S: 83,
11615
+ T: 84,
11616
+ U: 85,
11617
+ V: 86,
11618
+ W: 87,
11619
+ X: 88,
11620
+ Y: 89,
11621
+ Z: 90,
11622
+ bracketleft: 91,
11623
+ backslash: 92,
11624
+ bracketright: 93,
11625
+ asciicircum: 94,
11626
+ underscore: 95,
11627
+ grave: 96,
11628
+ a: 97,
11629
+ b: 98,
11630
+ c: 99,
11631
+ d: 100,
11632
+ e: 101,
11633
+ f: 102,
11634
+ g: 103,
11635
+ h: 104,
11636
+ i: 105,
11637
+ j: 106,
11638
+ k: 107,
11639
+ l: 108,
11640
+ m: 109,
11641
+ n: 110,
11642
+ o: 111,
11643
+ p: 112,
11644
+ q: 113,
11645
+ r: 114,
11646
+ s: 115,
11647
+ t: 116,
11648
+ u: 117,
11649
+ v: 118,
11650
+ w: 119,
11651
+ x: 120,
11652
+ y: 121,
11653
+ z: 122,
11654
+ braceleft: 123,
11655
+ bar: 124,
11656
+ braceright: 125,
11657
+ asciitilde: 126,
11658
+ exclamdown: 161,
11659
+ cent: 162,
11660
+ sterling: 163,
11661
+ currency: 164,
11662
+ yen: 165,
11663
+ brokenbar: 166,
11664
+ section: 167,
11194
11665
  dieresis: 168,
11195
11666
  copyright: 169,
11196
11667
  ordfeminine: 170,
@@ -13316,147 +13787,6 @@ var ZapfDingbatsEncoding = class ZapfDingbatsEncoding extends SimpleEncoding {
13316
13787
  }
13317
13788
  };
13318
13789
 
13319
- //#endregion
13320
- //#region src/fonts/font-descriptor.ts
13321
- /**
13322
- * Font flags as defined in PDF spec Table 123.
13323
- */
13324
- const FontFlags = {
13325
- FIXED_PITCH: 1,
13326
- SERIF: 2,
13327
- SYMBOLIC: 4,
13328
- SCRIPT: 8,
13329
- NONSYMBOLIC: 32,
13330
- ITALIC: 64,
13331
- ALL_CAP: 65536,
13332
- SMALL_CAP: 1 << 17,
13333
- FORCE_BOLD: 1 << 18
13334
- };
13335
- /**
13336
- * FontDescriptor contains font metrics and flags.
13337
- */
13338
- var FontDescriptor = class FontDescriptor {
13339
- fontName;
13340
- flags;
13341
- fontBBox;
13342
- italicAngle;
13343
- ascent;
13344
- descent;
13345
- leading;
13346
- capHeight;
13347
- xHeight;
13348
- stemV;
13349
- stemH;
13350
- avgWidth;
13351
- maxWidth;
13352
- missingWidth;
13353
- constructor(data) {
13354
- this.fontName = data.fontName;
13355
- this.flags = data.flags;
13356
- this.fontBBox = data.fontBBox;
13357
- this.italicAngle = data.italicAngle;
13358
- this.ascent = data.ascent;
13359
- this.descent = data.descent;
13360
- this.leading = data.leading;
13361
- this.capHeight = data.capHeight;
13362
- this.xHeight = data.xHeight;
13363
- this.stemV = data.stemV;
13364
- this.stemH = data.stemH;
13365
- this.avgWidth = data.avgWidth;
13366
- this.maxWidth = data.maxWidth;
13367
- this.missingWidth = data.missingWidth;
13368
- }
13369
- /** Check if font is fixed-pitch (monospace) */
13370
- get isFixedPitch() {
13371
- return (this.flags & FontFlags.FIXED_PITCH) !== 0;
13372
- }
13373
- /** Check if font is serif */
13374
- get isSerif() {
13375
- return (this.flags & FontFlags.SERIF) !== 0;
13376
- }
13377
- /** Check if font is symbolic (uses custom encoding) */
13378
- get isSymbolic() {
13379
- return (this.flags & FontFlags.SYMBOLIC) !== 0;
13380
- }
13381
- /** Check if font is script (cursive) */
13382
- get isScript() {
13383
- return (this.flags & FontFlags.SCRIPT) !== 0;
13384
- }
13385
- /** Check if font is non-symbolic (uses standard encoding) */
13386
- get isNonSymbolic() {
13387
- return (this.flags & FontFlags.NONSYMBOLIC) !== 0;
13388
- }
13389
- /** Check if font is italic */
13390
- get isItalic() {
13391
- return (this.flags & FontFlags.ITALIC) !== 0;
13392
- }
13393
- /** Check if font is all caps */
13394
- get isAllCap() {
13395
- return (this.flags & FontFlags.ALL_CAP) !== 0;
13396
- }
13397
- /** Check if font is small caps */
13398
- get isSmallCap() {
13399
- return (this.flags & FontFlags.SMALL_CAP) !== 0;
13400
- }
13401
- /** Check if font should be bold */
13402
- get isForceBold() {
13403
- return (this.flags & FontFlags.FORCE_BOLD) !== 0;
13404
- }
13405
- /**
13406
- * Parse FontDescriptor from a PDF dictionary.
13407
- */
13408
- static parse(dict) {
13409
- const bboxArray = dict.getArray("FontBBox");
13410
- const fontBBox = [
13411
- 0,
13412
- 0,
13413
- 0,
13414
- 0
13415
- ];
13416
- if (bboxArray && bboxArray.length >= 4) for (let i = 0; i < 4; i++) {
13417
- const item = bboxArray.at(i);
13418
- if (item && item.type === "number") fontBBox[i] = item.value;
13419
- }
13420
- return new FontDescriptor({
13421
- fontName: dict.getName("FontName")?.value ?? "",
13422
- flags: dict.getNumber("Flags")?.value ?? 0,
13423
- fontBBox,
13424
- italicAngle: dict.getNumber("ItalicAngle")?.value ?? 0,
13425
- ascent: dict.getNumber("Ascent")?.value ?? 0,
13426
- descent: dict.getNumber("Descent")?.value ?? 0,
13427
- leading: dict.getNumber("Leading")?.value ?? 0,
13428
- capHeight: dict.getNumber("CapHeight")?.value ?? 0,
13429
- xHeight: dict.getNumber("XHeight")?.value ?? 0,
13430
- stemV: dict.getNumber("StemV")?.value ?? 0,
13431
- stemH: dict.getNumber("StemH")?.value ?? 0,
13432
- avgWidth: dict.getNumber("AvgWidth")?.value ?? 0,
13433
- maxWidth: dict.getNumber("MaxWidth")?.value ?? 0,
13434
- missingWidth: dict.getNumber("MissingWidth")?.value ?? 0
13435
- });
13436
- }
13437
- };
13438
-
13439
- //#endregion
13440
- //#region src/fonts/pdf-font.ts
13441
- /**
13442
- * Abstract base class for PDF fonts.
13443
- */
13444
- var PdfFont = class {
13445
- /**
13446
- * Get width of text in points at a given font size.
13447
- *
13448
- * @param text - Unicode text to measure
13449
- * @param fontSize - Font size in points
13450
- * @returns Width in points
13451
- */
13452
- getTextWidth(text, fontSize) {
13453
- let totalWidth = 0;
13454
- const codes = this.encodeText(text);
13455
- for (const code of codes) totalWidth += this.getWidth(code);
13456
- return totalWidth * fontSize / 1e3;
13457
- }
13458
- };
13459
-
13460
13790
  //#endregion
13461
13791
  //#region src/fonts/standard-14.ts
13462
13792
  /**
@@ -16695,25 +17025,6 @@ const FONT_GLYPH_WIDTHS = {
16695
17025
 
16696
17026
  //#endregion
16697
17027
  //#region src/fonts/simple-font.ts
16698
- /**
16699
- * SimpleFont - Base class for single-byte encoded fonts.
16700
- *
16701
- * This handles TrueType, Type1, and Type3 fonts which use single-byte
16702
- * character codes (0-255).
16703
- *
16704
- * Font structure:
16705
- * <<
16706
- * /Type /Font
16707
- * /Subtype /TrueType (or /Type1, /Type3)
16708
- * /BaseFont /Helvetica
16709
- * /FirstChar 32
16710
- * /LastChar 255
16711
- * /Widths [278 278 355 ...]
16712
- * /Encoding /WinAnsiEncoding (or dict with /Differences)
16713
- * /FontDescriptor 10 0 R
16714
- * /ToUnicode 11 0 R
16715
- * >>
16716
- */
16717
17028
  const isSimpleFontSubtype = (subtype) => {
16718
17029
  return subtype === "TrueType" || subtype === "Type1" || subtype === "Type3" || subtype === "MMType1";
16719
17030
  };
@@ -16850,34 +17161,25 @@ var SimpleFont = class extends PdfFont {
16850
17161
  * Parse a SimpleFont from a PDF font dictionary.
16851
17162
  */
16852
17163
  function parseSimpleFont(dict, options = {}) {
16853
- const subtypeName = dict.getName("Subtype");
17164
+ const subtypeName = dict.getName("Subtype", options.resolver);
16854
17165
  const subtype = isSimpleFontSubtype(subtypeName?.value) ? subtypeName.value : "TrueType";
16855
- const baseFontName = dict.getName("BaseFont")?.value ?? "Unknown";
16856
- const firstChar = dict.getNumber("FirstChar")?.value ?? 0;
16857
- const lastChar = dict.getNumber("LastChar")?.value ?? 255;
16858
- let w = dict.get("Widths");
16859
- let widthsArray = null;
16860
- if (w instanceof PdfRef && options.resolveRef) w = options.resolveRef(w) ?? void 0;
16861
- if (w instanceof PdfArray) widthsArray = w;
17166
+ const baseFontName = dict.getName("BaseFont", options.resolver)?.value ?? "Unknown";
17167
+ const firstChar = dict.getNumber("FirstChar", options.resolver)?.value ?? 0;
17168
+ const lastChar = dict.getNumber("LastChar", options.resolver)?.value ?? 255;
17169
+ let widthsArray = dict.getArray("Widths", options.resolver);
16862
17170
  const widths = [];
16863
17171
  if (widthsArray) for (let i = 0; i < widthsArray.length; i++) {
16864
- const item = widthsArray.at(i);
17172
+ const item = widthsArray.at(i, options.resolver);
16865
17173
  if (item instanceof PdfNumber) widths.push(item.value);
16866
17174
  else widths.push(0);
16867
17175
  }
16868
- const encoding = parseEncoding(dict, options.resolveRef);
17176
+ const encoding = parseEncoding(dict, options.resolver);
16869
17177
  let descriptor = null;
16870
17178
  let embeddedProgram = null;
16871
- const descriptorRef = dict.get("FontDescriptor");
16872
- if (descriptorRef && options.resolveRef) {
16873
- const descriptorDict = options.resolveRef(descriptorRef);
16874
- if (descriptorDict && "getString" in descriptorDict) {
16875
- descriptor = FontDescriptor.parse(descriptorDict);
16876
- if (options.decodeStream) embeddedProgram = parseEmbeddedProgram(descriptorDict, {
16877
- decodeStream: options.decodeStream,
16878
- resolveRef: options.resolveRef
16879
- });
16880
- }
17179
+ const fontDescriptor = dict.getDict("FontDescriptor", options.resolver);
17180
+ if (fontDescriptor) {
17181
+ descriptor = FontDescriptor.parse(fontDescriptor);
17182
+ embeddedProgram = parseEmbeddedProgram(fontDescriptor, { resolver: options.resolver });
16881
17183
  }
16882
17184
  return new SimpleFont({
16883
17185
  subtype,
@@ -16894,36 +17196,31 @@ function parseSimpleFont(dict, options = {}) {
16894
17196
  /**
16895
17197
  * Parse encoding from font dictionary.
16896
17198
  */
16897
- function parseEncoding(dict, resolveRef) {
16898
- const encodingValue = dict.get("Encoding");
17199
+ function parseEncoding(dict, resolver) {
17200
+ const encodingValue = dict.get("Encoding", resolver);
16899
17201
  if (!encodingValue) {
16900
- const baseFontName = dict.getName("BaseFont")?.value ?? "";
17202
+ const baseFontName = dict.getName("BaseFont", resolver)?.value ?? "";
16901
17203
  if (baseFontName === "Symbol") return SymbolEncoding.instance;
16902
17204
  if (baseFontName === "ZapfDingbats") return ZapfDingbatsEncoding.instance;
16903
17205
  return StandardEncoding.instance;
16904
17206
  }
16905
- if (encodingValue.type === "name") return getEncodingByName(encodingValue.value);
16906
- if (encodingValue.type === "dict") return parseEncodingDict(encodingValue);
16907
- if (encodingValue.type === "ref" && resolveRef) {
16908
- const resolved = resolveRef(encodingValue);
16909
- if (resolved && resolved.type === "dict") return parseEncodingDict(resolved);
16910
- }
17207
+ if (encodingValue instanceof PdfName) return getEncodingByName(encodingValue.value);
17208
+ if (encodingValue instanceof PdfDict) return parseEncodingDict(encodingValue, resolver);
16911
17209
  return WinAnsiEncoding.instance;
16912
17210
  }
16913
17211
  /**
16914
17212
  * Parse encoding dictionary.
16915
17213
  */
16916
- function parseEncodingDict(dict) {
16917
- const baseEncodingName = dict.getName("BaseEncoding");
17214
+ function parseEncodingDict(dict, resolver) {
17215
+ const baseEncodingName = dict.getName("BaseEncoding", resolver);
16918
17216
  const baseEncoding = baseEncodingName ? getEncodingByName(baseEncodingName.value) : WinAnsiEncoding.instance;
16919
- const differencesArray = dict.getArray("Differences");
17217
+ const differencesArray = dict.getArray("Differences", resolver);
16920
17218
  if (!differencesArray || differencesArray.length === 0) return baseEncoding;
16921
17219
  const items = [];
16922
17220
  for (let i = 0; i < differencesArray.length; i++) {
16923
17221
  const item = differencesArray.at(i);
16924
17222
  if (item) {
16925
- if (item.type === "number") items.push(item.value);
16926
- else if (item.type === "name") items.push(item.value);
17223
+ if (item instanceof PdfNumber || item instanceof PdfName) items.push(item.value);
16927
17224
  }
16928
17225
  }
16929
17226
  return new DifferencesEncoding(baseEncoding, DifferencesEncoding.parseDifferencesArray(items));
@@ -16945,6 +17242,15 @@ function getEncodingByName(name) {
16945
17242
  //#endregion
16946
17243
  //#region src/document/forms/form-font.ts
16947
17244
  /**
17245
+ * Form font types for use in form fields.
17246
+ *
17247
+ * Supports two font types:
17248
+ * - EmbeddedFont: Full font with metrics and subsetting
17249
+ * - ExistingFont: Lightweight wrapper for fonts already in the PDF
17250
+ *
17251
+ * PDF Reference: Section 12.7.3.3 "Variable Text"
17252
+ */
17253
+ /**
16948
17254
  * Existing font from PDF's default resources.
16949
17255
  *
16950
17256
  * This is a lightweight wrapper for fonts already present in the PDF,
@@ -17068,18 +17374,11 @@ function mapToStandardFont(name) {
17068
17374
  function parseExistingFont(name, fontObj, registry) {
17069
17375
  let ref = null;
17070
17376
  let simpleFont = null;
17071
- if (fontObj?.type === "ref") {
17377
+ if (fontObj instanceof PdfRef) {
17072
17378
  ref = fontObj;
17073
17379
  const resolved = registry.getObject(fontObj);
17074
- if (resolved?.type === "dict") try {
17075
- const resolveRef = (r) => {
17076
- if (r instanceof PdfRef) {
17077
- const obj = registry.getObject(r);
17078
- if (obj instanceof PdfDict || obj instanceof PdfArray || obj instanceof PdfStream) return obj;
17079
- }
17080
- return null;
17081
- };
17082
- simpleFont = parseSimpleFont(resolved, { resolveRef });
17380
+ if (resolved instanceof PdfDict) try {
17381
+ simpleFont = parseSimpleFont(resolved, { resolver: registry.resolve.bind(registry) });
17083
17382
  } catch (err) {
17084
17383
  console.warn(err);
17085
17384
  }
@@ -17090,7 +17389,7 @@ function parseExistingFont(name, fontObj, registry) {
17090
17389
  * Check if a font is an EmbeddedFont.
17091
17390
  */
17092
17391
  function isEmbeddedFont(font) {
17093
- return "encodeText" in font && "getUsedGlyphIds" in font;
17392
+ return font instanceof EmbeddedFont;
17094
17393
  }
17095
17394
  /**
17096
17395
  * Check if a font is an ExistingFont.
@@ -18348,11 +18647,11 @@ var WidgetAnnotation = class {
18348
18647
  getOnValue() {
18349
18648
  const ap = this.dict.getDict("AP");
18350
18649
  if (!ap) return null;
18351
- const n = ap.get("N");
18650
+ const resolve = this.registry.resolve.bind(this.registry);
18651
+ const n = ap.get("N", resolve);
18352
18652
  if (!n) return null;
18353
- const nResolved = n.type === "ref" ? this.registry.getObject(n) : n;
18354
- if (nResolved instanceof PdfDict && !(nResolved instanceof PdfStream)) {
18355
- for (const key$1 of nResolved.keys()) if (key$1.value !== "Off") return key$1.value;
18653
+ if (n instanceof PdfDict && !(n instanceof PdfStream)) {
18654
+ for (const key$1 of n.keys()) if (key$1.value !== "Off") return key$1.value;
18356
18655
  }
18357
18656
  return null;
18358
18657
  }
@@ -18365,11 +18664,11 @@ var WidgetAnnotation = class {
18365
18664
  hasAppearancesForStates(states) {
18366
18665
  const ap = this.dict.getDict("AP");
18367
18666
  if (!ap) return false;
18368
- const n = ap.get("N");
18667
+ const resolve = this.registry.resolve.bind(this.registry);
18668
+ const n = ap.get("N", resolve);
18369
18669
  if (!n) return false;
18370
- const nResolved = n.type === "ref" ? this.registry.getObject(n) : n;
18371
- if (nResolved instanceof PdfDict && !(nResolved instanceof PdfStream)) {
18372
- for (const state of states) if (!nResolved.has(state)) return false;
18670
+ if (n instanceof PdfDict && !(n instanceof PdfStream)) {
18671
+ for (const state of states) if (!n.has(state)) return false;
18373
18672
  return true;
18374
18673
  }
18375
18674
  return states.length === 0;
@@ -18390,15 +18689,13 @@ var WidgetAnnotation = class {
18390
18689
  getNormalAppearance(state) {
18391
18690
  const ap = this.dict.getDict("AP");
18392
18691
  if (!ap) return null;
18393
- let n = ap.get("N");
18692
+ const resolve = this.registry.resolve.bind(this.registry);
18693
+ const n = ap.get("N", resolve);
18394
18694
  if (!n) return null;
18395
- if (n instanceof PdfRef) n = this.registry.resolve(n) ?? void 0;
18396
18695
  if (n instanceof PdfStream) return n;
18397
18696
  if (n instanceof PdfDict) {
18398
18697
  const stateKey = state ?? this.appearanceState ?? "Off";
18399
- let stateEntry = n.get(stateKey);
18400
- if (!stateEntry) return null;
18401
- if (stateEntry instanceof PdfRef) stateEntry = this.registry.resolve(stateEntry) ?? void 0;
18698
+ const stateEntry = n.get(stateKey, resolve);
18402
18699
  if (stateEntry instanceof PdfStream) return stateEntry;
18403
18700
  return null;
18404
18701
  }
@@ -18410,15 +18707,13 @@ var WidgetAnnotation = class {
18410
18707
  getRolloverAppearance(state) {
18411
18708
  const ap = this.dict.getDict("AP");
18412
18709
  if (!ap) return null;
18413
- let r = ap.get("R");
18710
+ const resolve = this.registry.resolve.bind(this.registry);
18711
+ const r = ap.get("R", resolve);
18414
18712
  if (!r) return null;
18415
- if (r instanceof PdfRef) r = this.registry.resolve(r) ?? void 0;
18416
18713
  if (r instanceof PdfStream) return r;
18417
18714
  if (r instanceof PdfDict) {
18418
18715
  const stateKey = state ?? this.appearanceState ?? "Off";
18419
- let stateEntry = r.get(stateKey);
18420
- if (!stateEntry) return null;
18421
- if (stateEntry instanceof PdfRef) stateEntry = this.registry.resolve(stateEntry) ?? void 0;
18716
+ const stateEntry = r.get(stateKey, resolve);
18422
18717
  if (stateEntry instanceof PdfStream) return stateEntry;
18423
18718
  return null;
18424
18719
  }
@@ -18430,15 +18725,13 @@ var WidgetAnnotation = class {
18430
18725
  getDownAppearance(state) {
18431
18726
  const ap = this.dict.getDict("AP");
18432
18727
  if (!ap) return null;
18433
- let d = ap.get("D");
18728
+ const resolve = this.registry.resolve.bind(this.registry);
18729
+ const d = ap.get("D", resolve);
18434
18730
  if (!d) return null;
18435
- if (d instanceof PdfRef) d = this.registry.resolve(d) ?? void 0;
18436
18731
  if (d instanceof PdfStream) return d;
18437
18732
  if (d instanceof PdfDict) {
18438
18733
  const stateKey = state ?? this.appearanceState ?? "Off";
18439
- let stateEntry = d.get(stateKey);
18440
- if (!stateEntry) return null;
18441
- if (stateEntry instanceof PdfRef) stateEntry = this.registry.resolve(stateEntry) ?? void 0;
18734
+ const stateEntry = d.get(stateKey, resolve);
18442
18735
  if (stateEntry instanceof PdfStream) return stateEntry;
18443
18736
  return null;
18444
18737
  }
@@ -18468,14 +18761,8 @@ var WidgetAnnotation = class {
18468
18761
  * Get appearance characteristics (/MK dictionary).
18469
18762
  */
18470
18763
  getAppearanceCharacteristics() {
18471
- const mkEntry = this.dict.get("MK");
18472
- if (!mkEntry) return null;
18473
- let mk = null;
18474
- if (mkEntry instanceof PdfDict) mk = mkEntry;
18475
- else if (mkEntry.type === "ref") {
18476
- const resolved = this.registry.getObject(mkEntry);
18477
- if (resolved instanceof PdfDict) mk = resolved;
18478
- }
18764
+ const resolve = this.registry.resolve.bind(this.registry);
18765
+ const mk = this.dict.getDict("MK", resolve);
18479
18766
  if (!mk) return null;
18480
18767
  return {
18481
18768
  rotation: mk.getNumber("R")?.value ?? 0,
@@ -18614,11 +18901,8 @@ var FormField = class {
18614
18901
  while (current) {
18615
18902
  if (visited.has(current)) break;
18616
18903
  visited.add(current);
18617
- const value = current.get(key$1);
18618
- if (value !== void 0) {
18619
- if (value instanceof PdfRef) return this.registry.getObject(value);
18620
- return value;
18621
- }
18904
+ const value = current.get(key$1, this.registry.resolve.bind(this.registry));
18905
+ if (value !== void 0) return value;
18622
18906
  const parentRef = current.getRef("Parent");
18623
18907
  if (!parentRef) break;
18624
18908
  const obj = this.registry.getObject(parentRef);
@@ -18859,8 +19143,7 @@ var TerminalField = class extends FormField {
18859
19143
  * This ensures getAppearanceCharacteristics() can work synchronously.
18860
19144
  */
18861
19145
  resolveMK(dict) {
18862
- const mkEntry = dict.get("MK");
18863
- if (mkEntry instanceof PdfRef) this.registry.resolve(mkEntry);
19146
+ dict.getDict("MK", this.registry.resolve.bind(this.registry));
18864
19147
  }
18865
19148
  /**
18866
19149
  * Add a widget to this field's /Kids array.
@@ -19210,12 +19493,6 @@ var ListBoxField = class extends TerminalField {
19210
19493
  //#endregion
19211
19494
  //#region src/document/forms/fields/other-fields.ts
19212
19495
  /**
19213
- * Other field types: Signature, Button, and Unknown.
19214
- *
19215
- * PDF Reference: Section 12.7.4.5 "Signature Fields"
19216
- * PDF Reference: Section 12.7.4.2 "Button Fields"
19217
- */
19218
- /**
19219
19496
  * Signature field.
19220
19497
  */
19221
19498
  var SignatureField = class extends TerminalField {
@@ -19230,13 +19507,7 @@ var SignatureField = class extends TerminalField {
19230
19507
  * Get signature dictionary (if signed).
19231
19508
  */
19232
19509
  getSignatureDict() {
19233
- const v = this.dict.get("V");
19234
- if (!v) return null;
19235
- if (v instanceof PdfRef) {
19236
- const resolved = this.registry.getObject(v);
19237
- return resolved instanceof PdfDict ? resolved : null;
19238
- }
19239
- return v instanceof PdfDict ? v : null;
19510
+ return this.dict.getDict("V", this.registry.resolve.bind(this.registry)) ?? null;
19240
19511
  }
19241
19512
  /**
19242
19513
  * Signature fields don't have simple values.
@@ -19322,7 +19593,7 @@ var RadioField = class extends TerminalField {
19322
19593
  * that are different from the widget appearance state names.
19323
19594
  */
19324
19595
  getExportValues() {
19325
- const opt = this.dict.getArray("Opt");
19596
+ const opt = this.dict.getArray("Opt", this.registry.resolve.bind(this.registry));
19326
19597
  if (!opt) return this.getOptions();
19327
19598
  const values = [];
19328
19599
  for (let i = 0; i < opt.length; i++) {
@@ -19441,11 +19712,6 @@ var TextField = class extends TerminalField {
19441
19712
  //#endregion
19442
19713
  //#region src/document/forms/fields/factory.ts
19443
19714
  /**
19444
- * Form field factory function.
19445
- *
19446
- * Creates the appropriate field type based on /FT and /Ff values.
19447
- */
19448
- /**
19449
19715
  * Create a terminal FormField instance based on /FT and /Ff.
19450
19716
  *
19451
19717
  * This factory creates only terminal fields (value-holding fields with widgets).
@@ -19473,15 +19739,15 @@ function createFormField(dict, ref, registry, acroForm, name) {
19473
19739
  function getInheritableFieldName(dict, key$1, registry) {
19474
19740
  let current = dict;
19475
19741
  const visited = /* @__PURE__ */ new Set();
19742
+ const resolve = registry.resolve.bind(registry);
19476
19743
  while (current) {
19477
19744
  if (visited.has(current)) break;
19478
19745
  visited.add(current);
19479
- const value = current.get(key$1);
19480
- if (value instanceof PdfName) return value.value;
19481
- const parentRef = current.getRef("Parent");
19482
- if (!parentRef) break;
19483
- const obj = registry.getObject(parentRef);
19484
- current = obj instanceof PdfDict ? obj : null;
19746
+ const value = current.getName(key$1, resolve);
19747
+ if (value) return value.value;
19748
+ const parent = current.getDict("Parent", resolve);
19749
+ if (!parent) break;
19750
+ current = parent;
19485
19751
  }
19486
19752
  return null;
19487
19753
  }
@@ -19491,15 +19757,15 @@ function getInheritableFieldName(dict, key$1, registry) {
19491
19757
  function getInheritableFieldNumber(dict, key$1, registry) {
19492
19758
  let current = dict;
19493
19759
  const visited = /* @__PURE__ */ new Set();
19760
+ const resolve = registry.resolve.bind(registry);
19494
19761
  while (current) {
19495
19762
  if (visited.has(current)) break;
19496
19763
  visited.add(current);
19497
- const value = current.get(key$1);
19498
- if (value instanceof PdfNumber) return value.value;
19499
- const parentRef = current.getRef("Parent");
19500
- if (!parentRef) break;
19501
- const obj = registry.getObject(parentRef);
19502
- current = obj instanceof PdfDict ? obj : null;
19764
+ const value = current.getNumber(key$1, resolve);
19765
+ if (value) return value.value;
19766
+ const parent = current.getDict("Parent", resolve);
19767
+ if (!parent) break;
19768
+ current = parent;
19503
19769
  }
19504
19770
  return 0;
19505
19771
  }
@@ -19554,7 +19820,9 @@ var FieldTree = class FieldTree {
19554
19820
  * @returns A fully-loaded FieldTree
19555
19821
  */
19556
19822
  static load(acroForm, registry) {
19557
- const fieldsArray = acroForm.getDict().getArray("Fields");
19823
+ const dict = acroForm.getDict();
19824
+ const resolve = registry.resolve.bind(registry);
19825
+ const fieldsArray = dict.getArray("Fields", resolve);
19558
19826
  if (!fieldsArray) return new FieldTree([]);
19559
19827
  const visited = /* @__PURE__ */ new Set();
19560
19828
  const fields = [];
@@ -19580,7 +19848,7 @@ var FieldTree = class FieldTree {
19580
19848
  if (item instanceof PdfRef) item = registry.resolve(item) ?? void 0;
19581
19849
  if (item instanceof PdfDict) fieldDict = item;
19582
19850
  if (!fieldDict) continue;
19583
- const partialName = fieldDict.getString("T")?.asString() ?? "";
19851
+ const partialName = fieldDict.getString("T", resolve)?.asString() ?? "";
19584
19852
  const fullName = parentName ? partialName ? `${parentName}.${partialName}` : parentName : partialName;
19585
19853
  if (checkIsTerminalField(fieldDict, registry)) {
19586
19854
  const field = createFormField(fieldDict, ref, registry, acroForm, fullName);
@@ -19593,7 +19861,7 @@ var FieldTree = class FieldTree {
19593
19861
  nonTerminal.parent = parent;
19594
19862
  fields.push(nonTerminal);
19595
19863
  if (parent instanceof NonTerminalField) parent.addChild(nonTerminal);
19596
- const kids = fieldDict.getArray("Kids");
19864
+ const kids = fieldDict.getArray("Kids", resolve);
19597
19865
  if (kids) for (let i = 0; i < kids.length; i++) queue.push({
19598
19866
  item: kids.at(i),
19599
19867
  parentName: fullName,
@@ -19663,7 +19931,8 @@ var FieldTree = class FieldTree {
19663
19931
  * - Its /Kids contain widgets (no /T) rather than child fields (have /T)
19664
19932
  */
19665
19933
  function checkIsTerminalField(dict, registry) {
19666
- const kids = dict.getArray("Kids");
19934
+ const resolve = registry.resolve.bind(registry);
19935
+ const kids = dict.getArray("Kids", resolve);
19667
19936
  if (!kids || kids.length === 0) return true;
19668
19937
  let firstKid = kids.at(0);
19669
19938
  if (!firstKid) return true;
@@ -19773,7 +20042,7 @@ var FormFlattener = class {
19773
20042
  for (const pageRef of pageRefs) {
19774
20043
  const pageDict = this.registry.resolve(pageRef);
19775
20044
  if (!(pageDict instanceof PdfDict)) continue;
19776
- const annots = pageDict.getArray("Annots");
20045
+ const annots = pageDict.getArray("Annots", this.registry.resolve.bind(this.registry));
19777
20046
  if (!annots) continue;
19778
20047
  for (let i = 0; i < annots.length; i++) {
19779
20048
  const annotRef = annots.at(i);
@@ -19794,12 +20063,13 @@ var FormFlattener = class {
19794
20063
  flattenWidgetsOnPage(pageRef, widgets) {
19795
20064
  const pageDict = this.registry.resolve(pageRef);
19796
20065
  if (!(pageDict instanceof PdfDict)) return;
19797
- let resources = pageDict.getDict("Resources");
20066
+ const resolve = this.registry.resolve.bind(this.registry);
20067
+ let resources = pageDict.getDict("Resources", resolve);
19798
20068
  if (!resources) {
19799
20069
  resources = new PdfDict();
19800
20070
  pageDict.set("Resources", resources);
19801
20071
  }
19802
- let xObjects = resources.getDict("XObject");
20072
+ let xObjects = resources.getDict("XObject", resolve);
19803
20073
  if (!xObjects) {
19804
20074
  xObjects = new PdfDict();
19805
20075
  resources.set("XObject", xObjects);
@@ -19833,7 +20103,7 @@ var FormFlattener = class {
19833
20103
  * Per PDFBox: BBox must exist and have width/height > 0.
19834
20104
  */
19835
20105
  isVisibleAppearance(appearance) {
19836
- const bbox = appearance.getArray("BBox");
20106
+ const bbox = appearance.getArray("BBox", this.registry.resolve.bind(this.registry));
19837
20107
  if (!bbox || bbox.length < 4) return false;
19838
20108
  const [x1, y1, x2, y2] = bbox.toArray().map((item) => item instanceof PdfNumber ? item.value : 0);
19839
20109
  const width = Math.abs((x2 ?? 0) - (x1 ?? 0));
@@ -19935,7 +20205,7 @@ var FormFlattener = class {
19935
20205
  * Get the appearance stream's transformation matrix.
19936
20206
  */
19937
20207
  getAppearanceMatrix(appearance) {
19938
- const matrixArray = appearance.getArray("Matrix");
20208
+ const matrixArray = appearance.getArray("Matrix", this.registry.resolve.bind(this.registry));
19939
20209
  if (!matrixArray || matrixArray.length < 6) return Matrix.identity();
19940
20210
  const [a, b, c, d, e, f] = matrixArray.toArray().map((item) => item instanceof PdfNumber ? item.value : 0);
19941
20211
  return new Matrix(a ?? 0, b ?? 0, c ?? 0, d ?? 0, e ?? 0, f ?? 0);
@@ -19944,7 +20214,7 @@ var FormFlattener = class {
19944
20214
  * Get appearance BBox, with fallback.
19945
20215
  */
19946
20216
  getAppearanceBBox(appearance) {
19947
- const bbox = appearance.getArray("BBox");
20217
+ const bbox = appearance.getArray("BBox", this.registry.resolve.bind(this.registry));
19948
20218
  if (!bbox || bbox.length < 4) return [
19949
20219
  0,
19950
20220
  0,
@@ -19963,14 +20233,7 @@ var FormFlattener = class {
19963
20233
  * Remove specific annotations from page.
19964
20234
  */
19965
20235
  removeAnnotations(page, toRemove) {
19966
- const annotsEntry = page.get("Annots");
19967
- if (!annotsEntry) return;
19968
- let annots = null;
19969
- if (annotsEntry instanceof PdfArray) annots = annotsEntry;
19970
- else if (annotsEntry instanceof PdfRef) {
19971
- const resolved = this.registry.resolve(annotsEntry);
19972
- if (resolved instanceof PdfArray) annots = resolved;
19973
- }
20236
+ const annots = page.getArray("Annots", this.registry.resolve.bind(this.registry));
19974
20237
  if (!annots) return;
19975
20238
  const remaining = [];
19976
20239
  for (let i = 0; i < annots.length; i++) {
@@ -20036,11 +20299,8 @@ var AcroForm = class AcroForm {
20036
20299
  * @param pageTree Optional page tree for efficient page lookups during flattening
20037
20300
  */
20038
20301
  static load(catalog, registry, pageTree) {
20039
- let acroFormEntry = catalog.get("AcroForm");
20040
- if (!acroFormEntry) return null;
20041
- let dict = null;
20042
- if (acroFormEntry instanceof PdfRef) acroFormEntry = registry.resolve(acroFormEntry) ?? void 0;
20043
- if (acroFormEntry instanceof PdfDict) dict = acroFormEntry;
20302
+ const resolve = registry.resolve.bind(registry);
20303
+ const dict = catalog.getDict("AcroForm", resolve);
20044
20304
  if (!dict) return null;
20045
20305
  return new AcroForm(dict, registry, pageTree ?? null);
20046
20306
  }
@@ -20048,11 +20308,7 @@ var AcroForm = class AcroForm {
20048
20308
  * Default resources dictionary (fonts, etc.).
20049
20309
  */
20050
20310
  getDefaultResources() {
20051
- let dr = this.dict.get("DR");
20052
- if (!dr) return null;
20053
- if (dr instanceof PdfRef) dr = this.registry.resolve(dr) ?? void 0;
20054
- if (dr instanceof PdfDict) return dr;
20055
- return null;
20311
+ return this.dict.getDict("DR", this.registry.resolve.bind(this.registry)) ?? null;
20056
20312
  }
20057
20313
  /**
20058
20314
  * Default appearance string.
@@ -20216,9 +20472,10 @@ var AcroForm = class AcroForm {
20216
20472
  ensureExistingFontsLoaded() {
20217
20473
  if (this.existingFontsCache !== null) return;
20218
20474
  this.existingFontsCache = /* @__PURE__ */ new Map();
20219
- const dr = this.dict.getDict("DR");
20475
+ const resolve = this.registry.resolve.bind(this.registry);
20476
+ const dr = this.dict.getDict("DR", resolve);
20220
20477
  if (!dr) return;
20221
- const fonts = dr.getDict("Font");
20478
+ const fonts = dr.getDict("Font", resolve);
20222
20479
  if (!fonts) return;
20223
20480
  for (const key$1 of fonts.keys()) {
20224
20481
  const fontName = key$1.value;
@@ -20393,12 +20650,13 @@ var AcroForm = class AcroForm {
20393
20650
  * @returns The font name used in the /DR dictionary
20394
20651
  */
20395
20652
  addFontToResources(fontRef, name) {
20396
- let dr = this.dict.getDict("DR");
20653
+ const resolve = this.registry.resolve.bind(this.registry);
20654
+ let dr = this.dict.getDict("DR", resolve);
20397
20655
  if (!dr) {
20398
20656
  dr = new PdfDict();
20399
20657
  this.dict.set("DR", dr);
20400
20658
  }
20401
- let fontsDict = dr.getDict("Font");
20659
+ let fontsDict = dr.getDict("Font", resolve);
20402
20660
  if (!fontsDict) {
20403
20661
  fontsDict = new PdfDict();
20404
20662
  dr.set("Font", fontsDict);
@@ -20482,371 +20740,8 @@ var AcroForm = class AcroForm {
20482
20740
  }
20483
20741
  };
20484
20742
 
20485
- //#endregion
20486
- //#region src/fonts/embedded-font.ts
20487
- /**
20488
- * EmbeddedFont represents a font that will be embedded into a PDF.
20489
- *
20490
- * Usage:
20491
- * ```typescript
20492
- * const fontBytes = await fs.readFile("NotoSans-Regular.ttf");
20493
- * const font = EmbeddedFont.fromBytes(fontBytes);
20494
- *
20495
- * // Check if text can be encoded
20496
- * if (font.canEncode("Hello ")) {
20497
- * const codes = font.encodeText("Hello ");
20498
- * const width = font.getTextWidth("Hello ", 12);
20499
- * }
20500
- * ```
20501
- */
20502
- var EmbeddedFont = class EmbeddedFont extends PdfFont {
20503
- subtype = "Type0";
20504
- /** Underlying font program */
20505
- fontProgram;
20506
- /** Original font data */
20507
- fontData;
20508
- /** Track used glyphs for subsetting (GID -> code points that use it) */
20509
- usedGlyphs = new Map([[0, /* @__PURE__ */ new Set()]]);
20510
- /** Track used code points for ToUnicode (codePoint -> GID) */
20511
- usedCodePoints = /* @__PURE__ */ new Map();
20512
- /** Subset tag (generated during save) */
20513
- _subsetTag = null;
20514
- /** Whether this font is used in a form field (prevents subsetting) */
20515
- _usedInForm = false;
20516
- /** Cached descriptor */
20517
- _descriptor = null;
20518
- constructor(fontProgram, fontData) {
20519
- super();
20520
- this.fontProgram = fontProgram;
20521
- this.fontData = fontData;
20522
- }
20523
- /**
20524
- * Create an EmbeddedFont from raw font bytes.
20525
- *
20526
- * @param data - TTF, OTF, or Type1 font data
20527
- * @param options - Embedding options
20528
- * @returns EmbeddedFont instance
20529
- * @throws {Error} if font format is not recognized
20530
- */
20531
- static fromBytes(data, _options) {
20532
- return new EmbeddedFont(parseFontProgram(data), data);
20533
- }
20534
- /**
20535
- * Create an EmbeddedFont from an already-parsed TrueType font.
20536
- */
20537
- static fromTrueTypeFont(font, data) {
20538
- return new EmbeddedFont(new TrueTypeFontProgram(font, data), data);
20539
- }
20540
- /**
20541
- * Get the base font name.
20542
- * During save, this will include a subset tag prefix (e.g., "ABCDEF+FontName").
20543
- */
20544
- get baseFontName() {
20545
- const name = this.fontProgram.postScriptName ?? "Unknown";
20546
- return this._subsetTag ? `${this._subsetTag}+${name}` : name;
20547
- }
20548
- /**
20549
- * Get the font descriptor.
20550
- */
20551
- get descriptor() {
20552
- if (!this._descriptor) this._descriptor = this.buildDescriptor();
20553
- return this._descriptor;
20554
- }
20555
- /**
20556
- * Get the underlying font program.
20557
- */
20558
- get program() {
20559
- return this.fontProgram;
20560
- }
20561
- /**
20562
- * Get the original font data.
20563
- */
20564
- get data() {
20565
- return this.fontData;
20566
- }
20567
- /**
20568
- * Get the subset tag (only available after save).
20569
- */
20570
- get subsetTag() {
20571
- return this._subsetTag;
20572
- }
20573
- /**
20574
- * Set the subset tag (called during save).
20575
- */
20576
- setSubsetTag(tag) {
20577
- this._subsetTag = tag;
20578
- }
20579
- /**
20580
- * Get all used glyph IDs.
20581
- */
20582
- getUsedGlyphIds() {
20583
- return [...this.usedGlyphs.keys()].sort((a, b) => a - b);
20584
- }
20585
- /**
20586
- * Get mapping from code point to GID.
20587
- */
20588
- getCodePointToGidMap() {
20589
- return new Map(this.usedCodePoints);
20590
- }
20591
- /**
20592
- * Get mapping from GID to Unicode code point.
20593
- *
20594
- * This is used for building the /W widths array and ToUnicode CMap.
20595
- * Since the content stream contains GIDs (with CIDToGIDMap /Identity),
20596
- * the /W array must be keyed by GID, and ToUnicode must map GID → Unicode.
20597
- *
20598
- * If multiple code points map to the same GID, returns the first one found.
20599
- */
20600
- getGidToCodePointMap() {
20601
- const result = /* @__PURE__ */ new Map();
20602
- for (const [gid, codePoints] of this.usedGlyphs) if (codePoints.size > 0) {
20603
- const firstCodePoint = codePoints.values().next().value;
20604
- if (firstCodePoint !== void 0) result.set(gid, firstCodePoint);
20605
- }
20606
- return result;
20607
- }
20608
- /**
20609
- * Iterate over text, tracking glyph usage and returning codePoint/GID pairs.
20610
- * This is the shared implementation for encodeText and encodeTextToGids.
20611
- */
20612
- trackAndEncode(text) {
20613
- const result = [];
20614
- for (const char of text) {
20615
- const codePoint = char.codePointAt(0);
20616
- if (codePoint === void 0) continue;
20617
- const gid = this.fontProgram.getGlyphId(codePoint);
20618
- if (!this.usedGlyphs.has(gid)) this.usedGlyphs.set(gid, /* @__PURE__ */ new Set());
20619
- this.usedGlyphs.get(gid).add(codePoint);
20620
- this.usedCodePoints.set(codePoint, gid);
20621
- result.push({
20622
- codePoint,
20623
- gid
20624
- });
20625
- }
20626
- return result;
20627
- }
20628
- /**
20629
- * Encode text to character codes.
20630
- *
20631
- * Returns Unicode code points, which is intuitive for users.
20632
- * The conversion to glyph IDs happens internally when writing to the PDF.
20633
- *
20634
- * Also tracks glyph usage for subsetting.
20635
- */
20636
- encodeText(text) {
20637
- return this.trackAndEncode(text).map((e) => e.codePoint);
20638
- }
20639
- /**
20640
- * Encode text to glyph IDs for PDF content stream.
20641
- *
20642
- * This is an internal method used when writing to the PDF.
20643
- * With CIDToGIDMap /Identity, the content stream must contain GIDs.
20644
- *
20645
- * @internal
20646
- */
20647
- encodeTextToGids(text) {
20648
- return this.trackAndEncode(text).map((e) => e.gid);
20649
- }
20650
- /**
20651
- * Convert a code point to its glyph ID.
20652
- *
20653
- * @internal
20654
- */
20655
- codePointToGid(codePoint) {
20656
- return this.fontProgram.getGlyphId(codePoint);
20657
- }
20658
- /**
20659
- * Get width of a character in glyph units (1000 = 1 em).
20660
- *
20661
- * Takes a Unicode code point (user-friendly API).
20662
- */
20663
- getWidth(code) {
20664
- const gid = this.fontProgram.getGlyphId(code);
20665
- const width = this.fontProgram.getAdvanceWidth(gid);
20666
- return Math.round(width * 1e3 / this.fontProgram.unitsPerEm);
20667
- }
20668
- /**
20669
- * Decode character code to Unicode string.
20670
- *
20671
- * For embedded fonts with Identity-H encoding, the code is the code point,
20672
- * so this just converts the code point back to a string.
20673
- */
20674
- toUnicode(code) {
20675
- return String.fromCodePoint(code);
20676
- }
20677
- /**
20678
- * Check if the font can encode the given text.
20679
- * Returns true if all characters have glyphs in the font.
20680
- */
20681
- canEncode(text) {
20682
- for (const char of text) {
20683
- const codePoint = char.codePointAt(0);
20684
- if (codePoint === void 0) continue;
20685
- if (!this.fontProgram.hasGlyph(codePoint)) return false;
20686
- }
20687
- return true;
20688
- }
20689
- /**
20690
- * Get the characters that cannot be encoded.
20691
- */
20692
- getUnencodableCharacters(text) {
20693
- const unencodable = [];
20694
- for (const char of text) {
20695
- const codePoint = char.codePointAt(0);
20696
- if (codePoint === void 0) continue;
20697
- if (!this.fontProgram.hasGlyph(codePoint)) unencodable.push(char);
20698
- }
20699
- return unencodable;
20700
- }
20701
- /**
20702
- * Reset glyph usage tracking.
20703
- * Call this before re-encoding if you want a fresh subset.
20704
- */
20705
- resetUsage() {
20706
- this.usedGlyphs.clear();
20707
- this.usedGlyphs.set(0, /* @__PURE__ */ new Set());
20708
- this.usedCodePoints.clear();
20709
- this._subsetTag = null;
20710
- }
20711
- /**
20712
- * Mark this font as used in a form field.
20713
- *
20714
- * Fonts used in form fields cannot be subsetted because users may type
20715
- * any character at runtime. This method is called automatically when
20716
- * an EmbeddedFont is used in form field appearances.
20717
- */
20718
- markUsedInForm() {
20719
- this._usedInForm = true;
20720
- }
20721
- /**
20722
- * Check if this font is used in a form field.
20723
- */
20724
- get usedInForm() {
20725
- return this._usedInForm;
20726
- }
20727
- /**
20728
- * Check if this font can be subsetted.
20729
- *
20730
- * Returns false if the font is used in a form field (since users can
20731
- * type any character at runtime).
20732
- */
20733
- canSubset() {
20734
- return !this._usedInForm;
20735
- }
20736
- /**
20737
- * Get width of text in points at a given font size.
20738
- *
20739
- * Alias for getTextWidth() to match Standard14Font API.
20740
- *
20741
- * @param text - The text to measure
20742
- * @param size - Font size in points
20743
- * @returns Width in points
20744
- */
20745
- widthOfTextAtSize(text, size) {
20746
- return this.getTextWidth(text, size);
20747
- }
20748
- /**
20749
- * Get the height of the font at a given size.
20750
- *
20751
- * This returns the full height from descender to ascender.
20752
- *
20753
- * @param size - Font size in points
20754
- * @returns Height in points
20755
- */
20756
- heightAtSize(size) {
20757
- const desc = this.descriptor;
20758
- if (!desc) return size;
20759
- return (desc.ascent - desc.descent) * size / 1e3;
20760
- }
20761
- /**
20762
- * Calculate font size needed to achieve a specific text height.
20763
- *
20764
- * @param height - Desired height in points
20765
- * @returns Font size in points
20766
- */
20767
- sizeAtHeight(height) {
20768
- const desc = this.descriptor;
20769
- if (!desc) return height;
20770
- const unitsHeight = desc.ascent - desc.descent;
20771
- return height * 1e3 / unitsHeight;
20772
- }
20773
- /**
20774
- * Calculate font size needed for text to fit a specific width.
20775
- *
20776
- * @param text - The text to measure
20777
- * @param width - Desired width in points
20778
- * @returns Font size in points
20779
- */
20780
- sizeAtWidth(text, width) {
20781
- if (text.length === 0) return 0;
20782
- const codes = this.encodeText(text);
20783
- let totalWidth = 0;
20784
- for (const code of codes) totalWidth += this.getWidth(code);
20785
- if (totalWidth === 0) return 0;
20786
- return width * 1e3 / totalWidth;
20787
- }
20788
- /**
20789
- * Build a FontDescriptor from the font program.
20790
- */
20791
- buildDescriptor() {
20792
- const program = this.fontProgram;
20793
- const bbox = program.bbox;
20794
- const scale = 1e3 / program.unitsPerEm;
20795
- return new FontDescriptor({
20796
- fontName: program.postScriptName ?? "Unknown",
20797
- flags: this.computeFlags(),
20798
- fontBBox: [
20799
- Math.round(bbox[0] * scale),
20800
- Math.round(bbox[1] * scale),
20801
- Math.round(bbox[2] * scale),
20802
- Math.round(bbox[3] * scale)
20803
- ],
20804
- italicAngle: program.italicAngle,
20805
- ascent: Math.round(program.ascent * scale),
20806
- descent: Math.round(program.descent * scale),
20807
- leading: 0,
20808
- capHeight: Math.round(program.capHeight * scale),
20809
- xHeight: Math.round(program.xHeight * scale),
20810
- stemV: program.stemV,
20811
- stemH: 0,
20812
- avgWidth: 0,
20813
- maxWidth: 0,
20814
- missingWidth: this.getWidth(0)
20815
- });
20816
- }
20817
- /**
20818
- * Compute font flags for the descriptor.
20819
- */
20820
- computeFlags() {
20821
- let flags = 0;
20822
- if (this.fontProgram.isFixedPitch) flags |= 1;
20823
- flags |= 4;
20824
- if (this.fontProgram.italicAngle !== 0) flags |= 64;
20825
- return flags;
20826
- }
20827
- };
20828
-
20829
20743
  //#endregion
20830
20744
  //#region src/fonts/cid-font.ts
20831
- /**
20832
- * CIDFont - Descendant font for Type0 composite fonts.
20833
- *
20834
- * CIDFonts contain the actual glyph descriptions and metrics for
20835
- * composite (Type0) fonts. They use CIDs (Character IDs) to identify
20836
- * glyphs rather than character codes.
20837
- *
20838
- * Font structure:
20839
- * <<
20840
- * /Type /Font
20841
- * /Subtype /CIDFontType2 (or /CIDFontType0)
20842
- * /BaseFont /NotoSansCJK-Regular
20843
- * /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >>
20844
- * /FontDescriptor 14 0 R
20845
- * /W [1 [500 600] 100 200 500] % Complex width format
20846
- * /DW 1000
20847
- * /CIDToGIDMap /Identity
20848
- * >>
20849
- */
20850
20745
  const isCIDFontSubtype = (subtype) => {
20851
20746
  return subtype === "CIDFontType0" || subtype === "CIDFontType2";
20852
20747
  };
@@ -21011,7 +20906,7 @@ function parseCIDFont(dict, options = {}) {
21011
20906
  ordering: "Identity",
21012
20907
  supplement: 0
21013
20908
  };
21014
- const sysInfoDict = dict.getDict("CIDSystemInfo");
20909
+ const sysInfoDict = dict.getDict("CIDSystemInfo", options.resolver);
21015
20910
  if (sysInfoDict) cidSystemInfo = {
21016
20911
  registry: sysInfoDict.getString("Registry")?.asString() ?? "Adobe",
21017
20912
  ordering: sysInfoDict.getString("Ordering")?.asString() ?? "Identity",
@@ -21019,30 +20914,23 @@ function parseCIDFont(dict, options = {}) {
21019
20914
  };
21020
20915
  const defaultWidth = dict.getNumber("DW")?.value ?? 1e3;
21021
20916
  let widths = new CIDWidthMap();
21022
- let w = dict.get("W");
20917
+ let w = dict.get("W", options.resolver);
21023
20918
  let wArray = null;
21024
- if (w instanceof PdfRef && options.resolveRef) w = options.resolveRef(w) ?? void 0;
21025
20919
  if (w instanceof PdfArray) wArray = w;
21026
20920
  if (wArray) widths = parseCIDWidths(wArray);
21027
20921
  let descriptor = null;
21028
20922
  let embeddedProgram = null;
21029
- const descriptorRef = dict.get("FontDescriptor");
21030
- if (descriptorRef && options.resolveRef) {
21031
- const descriptorDict = options.resolveRef(descriptorRef);
21032
- if (descriptorDict && descriptorDict.type === "dict") {
21033
- descriptor = FontDescriptor.parse(descriptorDict);
21034
- if (options.decodeStream) embeddedProgram = parseEmbeddedProgram(descriptorDict, {
21035
- decodeStream: options.decodeStream,
21036
- resolveRef: options.resolveRef
21037
- });
21038
- }
20923
+ const fontDescriptor = dict.getDict("FontDescriptor", options.resolver);
20924
+ if (fontDescriptor) {
20925
+ descriptor = FontDescriptor.parse(fontDescriptor);
20926
+ embeddedProgram = parseEmbeddedProgram(fontDescriptor, { resolver: options.resolver });
21039
20927
  }
21040
20928
  let cidToGidMap = "Identity";
21041
- const cidToGidValue = dict.get("CIDToGIDMap");
20929
+ const cidToGidValue = dict.get("CIDToGIDMap", options.resolver);
21042
20930
  if (cidToGidValue) {
21043
- if (cidToGidValue.type === "name" && cidToGidValue.value === "Identity") cidToGidMap = "Identity";
21044
- if (cidToGidValue.type === "stream" && options.decodeStream) {
21045
- const mapData = options.decodeStream(cidToGidValue);
20931
+ if (cidToGidValue instanceof PdfName && cidToGidValue.value === "Identity") cidToGidMap = "Identity";
20932
+ if (cidToGidValue instanceof PdfStream) {
20933
+ const mapData = cidToGidValue.getDecodedData();
21046
20934
  if (mapData && mapData.length >= 2) {
21047
20935
  const numEntries = mapData.length / 2;
21048
20936
  cidToGidMap = new Uint16Array(numEntries);
@@ -21324,24 +21212,6 @@ function bytesToLatin1$1(data) {
21324
21212
  //#endregion
21325
21213
  //#region src/fonts/composite-font.ts
21326
21214
  /**
21327
- * CompositeFont - Type0 composite font for CJK and Unicode text.
21328
- *
21329
- * Composite fonts (Type0) combine:
21330
- * - A CMap (character code to CID mapping)
21331
- * - One or more CIDFonts (the actual glyph data)
21332
- * - Optional ToUnicode map (for text extraction)
21333
- *
21334
- * Font structure:
21335
- * <<
21336
- * /Type /Font
21337
- * /Subtype /Type0
21338
- * /BaseFont /NotoSansCJK-Regular
21339
- * /Encoding /Identity-H (or stream)
21340
- * /DescendantFonts [12 0 R]
21341
- * /ToUnicode 13 0 R
21342
- * >>
21343
- */
21344
- /**
21345
21215
  * CompositeFont handles Type0 composite fonts (CJK, Unicode).
21346
21216
  */
21347
21217
  var CompositeFont = class extends PdfFont {
@@ -21416,40 +21286,28 @@ var CompositeFont = class extends PdfFont {
21416
21286
  * Parse CMap from encoding value.
21417
21287
  */
21418
21288
  function parseCMapFromEncoding(encodingValue, options) {
21419
- if (!encodingValue || typeof encodingValue !== "object") return CMap.identityH();
21420
- const enc = encodingValue;
21421
- if (enc.type === "name" && enc.value) return CMap.getPredefined(enc.value) ?? CMap.identityH();
21422
- if (enc.type === "stream" && options.decodeStream) {
21423
- const data = options.decodeStream(encodingValue);
21289
+ let encoding = encodingValue;
21290
+ if (encoding instanceof PdfRef && options.resolver) encoding = options.resolver(encoding) ?? void 0;
21291
+ if (encoding instanceof PdfName && encoding.value) return CMap.getPredefined(encoding.value) ?? CMap.identityH();
21292
+ if (encoding instanceof PdfStream) {
21293
+ const data = encoding.getDecodedData();
21424
21294
  return data ? parseCMap(data) : CMap.identityH();
21425
21295
  }
21426
- if (enc.type === "ref" && options.resolveRef && options.decodeStream) {
21427
- const resolved = options.resolveRef(encodingValue);
21428
- if (resolved && resolved.type === "stream") {
21429
- const data = options.decodeStream(resolved);
21430
- return data ? parseCMap(data) : CMap.identityH();
21431
- }
21432
- }
21433
21296
  return CMap.identityH();
21434
21297
  }
21435
21298
  /**
21436
21299
  * Parse a CompositeFont from a PDF font dictionary.
21437
21300
  */
21438
21301
  function parseCompositeFont(dict, options = {}) {
21439
- const baseFontName = dict.getName("BaseFont")?.value ?? "Unknown";
21440
- const cmap = parseCMapFromEncoding(dict.get("Encoding"), options);
21302
+ const baseFontName = dict.getName("BaseFont", options.resolver)?.value ?? "Unknown";
21303
+ const cmap = parseCMapFromEncoding(dict.get("Encoding", options.resolver), options);
21441
21304
  let cidFont;
21442
- let descendants = dict.get("DescendantFonts");
21305
+ let descendants = dict.get("DescendantFonts", options.resolver);
21443
21306
  let descendantsArray = null;
21444
- if (descendants instanceof PdfRef && options.resolveRef) descendants = options.resolveRef(descendants) ?? void 0;
21445
21307
  if (descendants instanceof PdfArray) descendantsArray = descendants;
21446
21308
  if (descendantsArray && descendantsArray.length > 0) {
21447
- const firstDescendant = descendantsArray.at(0);
21448
- if (firstDescendant?.type === "ref" && options.resolveRef) {
21449
- const cidFontDict = options.resolveRef(firstDescendant);
21450
- if (cidFontDict?.type === "dict") cidFont = parseCIDFont(cidFontDict, options);
21451
- else cidFont = createDefaultCIDFont(baseFontName);
21452
- } else if (firstDescendant?.type === "dict") cidFont = parseCIDFont(firstDescendant, options);
21309
+ const firstDescendant = descendantsArray.at(0, options.resolver);
21310
+ if (firstDescendant instanceof PdfDict) cidFont = parseCIDFont(firstDescendant, options);
21453
21311
  else cidFont = createDefaultCIDFont(baseFontName);
21454
21312
  } else cidFont = createDefaultCIDFont(baseFontName);
21455
21313
  return new CompositeFont({
@@ -21480,7 +21338,7 @@ function createDefaultCIDFont(baseFontName) {
21480
21338
  * @returns A SimpleFont or CompositeFont instance
21481
21339
  */
21482
21340
  function parseFont(dict, options = {}) {
21483
- switch (dict.getName("Subtype")?.value) {
21341
+ switch (dict.getName("Subtype", options.resolver)?.value) {
21484
21342
  case "Type0": return parseCompositeFont(dict, options);
21485
21343
  case "TrueType":
21486
21344
  case "Type1":
@@ -24306,8 +24164,8 @@ var PDFPage = class PDFPage {
24306
24164
  * Page rotation in degrees (0, 90, 180, or 270).
24307
24165
  */
24308
24166
  get rotation() {
24309
- const rotate = this.dict.get("Rotate");
24310
- if (rotate instanceof PdfNumber) {
24167
+ const rotate = this.dict.getNumber("Rotate", this.ctx.resolve.bind(this.ctx));
24168
+ if (rotate) {
24311
24169
  const value = rotate.value % 360;
24312
24170
  if (value === 90 || value === -270) return 90;
24313
24171
  if (value === 180 || value === -180) return 180;
@@ -24332,8 +24190,7 @@ var PDFPage = class PDFPage {
24332
24190
  * a new empty dict is created on this page.
24333
24191
  */
24334
24192
  getResources() {
24335
- let resources = this.dict.get("Resources");
24336
- if (resources instanceof PdfRef) resources = this.ctx.resolve(resources) ?? void 0;
24193
+ let resources = this.dict.get("Resources", this.ctx.resolve.bind(this.ctx));
24337
24194
  if (resources instanceof PdfDict) return resources;
24338
24195
  resources = new PdfDict();
24339
24196
  this.dict.set("Resources", resources);
@@ -25014,13 +24871,9 @@ var PDFPage = class PDFPage {
25014
24871
  for (let i = 0; i < annotsArray.length; i++) {
25015
24872
  const entry = annotsArray.at(i);
25016
24873
  if (!entry) continue;
25017
- let annotDict = null;
25018
- let annotRef = null;
25019
- if (entry instanceof PdfRef) {
25020
- annotRef = entry;
25021
- const resolved = this.ctx.resolve(entry);
25022
- if (resolved instanceof PdfDict) annotDict = resolved;
25023
- } else if (entry instanceof PdfDict) annotDict = entry;
24874
+ const resolved = entry instanceof PdfRef ? this.ctx.resolve(entry) : entry;
24875
+ const annotRef = entry instanceof PdfRef ? entry : null;
24876
+ const annotDict = resolved instanceof PdfDict ? resolved : null;
25024
24877
  if (!annotDict) continue;
25025
24878
  if (isWidgetAnnotation(annotDict)) continue;
25026
24879
  if (isPopupAnnotation(annotDict)) continue;
@@ -25042,13 +24895,9 @@ var PDFPage = class PDFPage {
25042
24895
  for (let i = 0; i < annotsArray.length; i++) {
25043
24896
  let entry = annotsArray.at(i);
25044
24897
  if (!entry) continue;
25045
- let annotDict = null;
25046
- let annotRef = null;
25047
- if (entry instanceof PdfRef) {
25048
- annotRef = entry;
25049
- entry = this.ctx.resolve(entry) ?? void 0;
25050
- }
25051
- if (entry instanceof PdfDict) annotDict = entry;
24898
+ const resolved = entry instanceof PdfRef ? this.ctx.resolve(entry) : entry;
24899
+ const annotRef = entry instanceof PdfRef ? entry : null;
24900
+ const annotDict = resolved instanceof PdfDict ? resolved : null;
25052
24901
  if (!annotDict || !isPopupAnnotation(annotDict)) continue;
25053
24902
  popups.push(new PDFPopupAnnotation(annotDict, annotRef, this.ctx.registry));
25054
24903
  }
@@ -25497,16 +25346,24 @@ var PDFPage = class PDFPage {
25497
25346
  prependContent(content) {
25498
25347
  const existingContents = this.dict.get("Contents");
25499
25348
  const newContent = this.createContentStream(`${content}\n`);
25500
- if (!existingContents) this.dict.set("Contents", newContent);
25501
- else if (existingContents instanceof PdfRef) {
25349
+ if (!existingContents) {
25350
+ this.dict.set("Contents", newContent);
25351
+ return;
25352
+ }
25353
+ if (existingContents instanceof PdfRef) {
25502
25354
  this.dict.set("Contents", new PdfArray([newContent, existingContents]));
25503
25355
  this._contentWrapped = true;
25504
- } else if (existingContents instanceof PdfStream) {
25356
+ return;
25357
+ }
25358
+ if (existingContents instanceof PdfStream) {
25505
25359
  this.dict.set("Contents", new PdfArray([newContent, existingContents]));
25506
25360
  this._contentWrapped = true;
25507
- } else if (existingContents instanceof PdfArray) {
25361
+ return;
25362
+ }
25363
+ if (existingContents instanceof PdfArray) {
25508
25364
  existingContents.insert(0, newContent);
25509
25365
  this._contentWrapped = true;
25366
+ return;
25510
25367
  }
25511
25368
  }
25512
25369
  /** Track whether we've already wrapped the original content in q/Q */
@@ -25529,19 +25386,25 @@ var PDFPage = class PDFPage {
25529
25386
  this._contentWrapped = true;
25530
25387
  const qStream = this.createContentStream("q\n");
25531
25388
  const QStream = this.createContentStream("\nQ");
25532
- if (existingContents instanceof PdfRef) this.dict.set("Contents", new PdfArray([
25533
- qStream,
25534
- existingContents,
25535
- QStream,
25536
- newContent
25537
- ]));
25538
- else if (existingContents instanceof PdfStream) this.dict.set("Contents", new PdfArray([
25539
- qStream,
25540
- existingContents,
25541
- QStream,
25542
- newContent
25543
- ]));
25544
- else if (existingContents instanceof PdfArray) {
25389
+ if (existingContents instanceof PdfRef) {
25390
+ this.dict.set("Contents", new PdfArray([
25391
+ qStream,
25392
+ existingContents,
25393
+ QStream,
25394
+ newContent
25395
+ ]));
25396
+ return;
25397
+ }
25398
+ if (existingContents instanceof PdfStream) {
25399
+ this.dict.set("Contents", new PdfArray([
25400
+ qStream,
25401
+ existingContents,
25402
+ QStream,
25403
+ newContent
25404
+ ]));
25405
+ return;
25406
+ }
25407
+ if (existingContents instanceof PdfArray) {
25545
25408
  const newArray = new PdfArray([qStream]);
25546
25409
  for (let i = 0; i < existingContents.length; i++) {
25547
25410
  const item = existingContents.at(i);
@@ -25550,18 +25413,20 @@ var PDFPage = class PDFPage {
25550
25413
  newArray.push(QStream);
25551
25414
  newArray.push(newContent);
25552
25415
  this.dict.set("Contents", newArray);
25416
+ return;
25553
25417
  }
25554
- } else {
25555
- const contents = this.dict.get("Contents");
25556
- if (contents instanceof PdfArray) contents.push(newContent);
25557
- else if (contents !== void 0) this.dict.set("Contents", new PdfArray([contents, newContent]));
25558
25418
  }
25419
+ if (existingContents instanceof PdfArray) {
25420
+ existingContents.push(newContent);
25421
+ return;
25422
+ }
25423
+ if (existingContents !== void 0) this.dict.set("Contents", new PdfArray([existingContents, newContent]));
25559
25424
  }
25560
25425
  /**
25561
25426
  * Get a box (MediaBox, CropBox, etc.) from the page dictionary.
25562
25427
  */
25563
25428
  getBox(name) {
25564
- const box = this.dict.get(name);
25429
+ const box = this.dict.get(name, this.ctx.resolve.bind(this.ctx));
25565
25430
  if (!(box instanceof PdfArray) || box.length < 4) return null;
25566
25431
  const x1 = box.at(0);
25567
25432
  const y1 = box.at(1);
@@ -25598,7 +25463,7 @@ var PDFPage = class PDFPage {
25598
25463
  */
25599
25464
  addFontResource(font) {
25600
25465
  const resources = this.getResources();
25601
- let fonts = resources.get("Font");
25466
+ let fonts = resources.get("Font", this.ctx.resolve.bind(this.ctx));
25602
25467
  if (!(fonts instanceof PdfDict)) {
25603
25468
  fonts = new PdfDict();
25604
25469
  resources.set("Font", fonts);
@@ -25606,7 +25471,7 @@ var PDFPage = class PDFPage {
25606
25471
  if (typeof font === "string") {
25607
25472
  if (!isStandard14Font(font)) throw new Error(`Unknown Standard 14 font: ${font}`);
25608
25473
  for (const [existingName, value] of fonts) if (value instanceof PdfDict) {
25609
- const baseFont = value.get("BaseFont");
25474
+ const baseFont = value.get("BaseFont", this.ctx.resolve.bind(this.ctx));
25610
25475
  if (baseFont instanceof PdfName && baseFont.value === font) return existingName.value;
25611
25476
  }
25612
25477
  const fontDict = PdfDict.of({
@@ -25699,21 +25564,14 @@ var PDFPage = class PDFPage {
25699
25564
  * Get the concatenated content stream bytes.
25700
25565
  */
25701
25566
  getContentBytes() {
25702
- const contents = this.dict.get("Contents");
25567
+ const contents = this.dict.get("Contents", this.ctx.resolve.bind(this.ctx));
25703
25568
  if (!contents) return new Uint8Array(0);
25704
- if (contents instanceof PdfRef && this.ctx) {
25705
- const stream = this.ctx.resolve(contents);
25706
- if (stream instanceof PdfStream) return stream.getDecodedData();
25707
- }
25708
25569
  if (contents instanceof PdfStream) return contents.getDecodedData();
25709
25570
  if (contents instanceof PdfArray) {
25710
25571
  const chunks = [];
25711
25572
  for (let i = 0; i < contents.length; i++) {
25712
- const item = contents.at(i);
25713
- if (item instanceof PdfRef && this.ctx) {
25714
- const stream = this.ctx.resolve(item);
25715
- if (stream instanceof PdfStream) chunks.push(stream.getDecodedData());
25716
- } else if (item instanceof PdfStream) chunks.push(item.getDecodedData());
25573
+ const item = contents.at(i, this.ctx.resolve.bind(this.ctx));
25574
+ if (item instanceof PdfStream) chunks.push(item.getDecodedData());
25717
25575
  }
25718
25576
  return this.concatenateChunks(chunks);
25719
25577
  }
@@ -25744,17 +25602,11 @@ var PDFPage = class PDFPage {
25744
25602
  resolveInheritedResources() {
25745
25603
  let currentDict = this.dict;
25746
25604
  while (currentDict) {
25747
- const resourcesEntry = currentDict.get("Resources");
25748
- if (resourcesEntry instanceof PdfRef) {
25749
- const resolved = this.ctx.resolve(resourcesEntry);
25750
- if (resolved instanceof PdfDict) return resolved;
25751
- } else if (resourcesEntry instanceof PdfDict) return resourcesEntry;
25752
- const parentEntry = currentDict.get("Parent");
25753
- if (parentEntry instanceof PdfRef) {
25754
- const parent = this.ctx.resolve(parentEntry);
25755
- if (parent instanceof PdfDict) currentDict = parent;
25756
- else break;
25757
- } else break;
25605
+ const resources = currentDict.get("Resources", this.ctx.resolve.bind(this.ctx));
25606
+ if (resources instanceof PdfDict) return resources;
25607
+ const parent = currentDict.get("Parent", this.ctx.resolve.bind(this.ctx));
25608
+ if (parent instanceof PdfDict) currentDict = parent;
25609
+ else break;
25758
25610
  }
25759
25611
  return null;
25760
25612
  }
@@ -25764,81 +25616,22 @@ var PDFPage = class PDFPage {
25764
25616
  createFontResolver() {
25765
25617
  const resourcesDict = this.resolveInheritedResources();
25766
25618
  if (!resourcesDict) return () => null;
25767
- let fontDict = null;
25768
- const fontEntry = resourcesDict.get("Font");
25769
- if (fontEntry instanceof PdfRef && this.ctx) {
25770
- const resolved = this.ctx.resolve(fontEntry);
25771
- if (resolved instanceof PdfDict) fontDict = resolved;
25772
- } else if (fontEntry instanceof PdfDict) fontDict = fontEntry;
25773
- if (!fontDict) return () => null;
25619
+ const font = resourcesDict.getDict("Font", this.ctx.resolve.bind(this.ctx));
25620
+ if (!font) return () => null;
25774
25621
  const fontCache = /* @__PURE__ */ new Map();
25775
- for (const [nameObj, fontEntry$1] of fontDict) {
25776
- const name = nameObj.value;
25777
- let fontDictEntry = null;
25778
- if (fontEntry$1 instanceof PdfRef && this.ctx) {
25779
- const resolved = this.ctx.resolve(fontEntry$1);
25780
- if (resolved instanceof PdfDict) fontDictEntry = resolved;
25781
- } else if (fontEntry$1 instanceof PdfDict) fontDictEntry = fontEntry$1;
25782
- if (!fontDictEntry) continue;
25622
+ for (const [key$1, entry] of font) {
25623
+ const name = key$1.value;
25624
+ const resolved = entry instanceof PdfRef ? this.ctx.resolve(entry) : entry;
25625
+ let entryDict = resolved instanceof PdfDict ? resolved : null;
25626
+ if (!entryDict) continue;
25783
25627
  let toUnicodeMap = null;
25784
- const toUnicodeEntry = fontDictEntry.get("ToUnicode");
25785
- if (toUnicodeEntry && this.ctx) {
25786
- let toUnicodeStream = null;
25787
- if (toUnicodeEntry instanceof PdfRef) {
25788
- const resolved = this.ctx.resolve(toUnicodeEntry);
25789
- if (resolved instanceof PdfStream) toUnicodeStream = resolved;
25790
- } else if (toUnicodeEntry instanceof PdfStream) toUnicodeStream = toUnicodeEntry;
25791
- if (toUnicodeStream) try {
25792
- toUnicodeMap = parseToUnicode(toUnicodeStream.getDecodedData());
25793
- } catch {}
25794
- }
25795
- const resolvedRefs = /* @__PURE__ */ new Map();
25796
- const decodedStreams = /* @__PURE__ */ new Map();
25797
- const preResolveValue = (value) => {
25798
- if (value instanceof PdfRef) {
25799
- const key$1 = `${value.objectNumber} ${value.generation} R`;
25800
- if (resolvedRefs.has(key$1)) return;
25801
- const resolved = this.ctx.resolve(value);
25802
- if (resolved instanceof PdfDict || resolved instanceof PdfArray || resolved instanceof PdfStream) {
25803
- resolvedRefs.set(key$1, resolved);
25804
- if (resolved instanceof PdfStream) try {
25805
- const decoded = resolved.getDecodedData();
25806
- decodedStreams.set(key$1, decoded);
25807
- } catch {}
25808
- preResolveValue(resolved);
25809
- }
25810
- } else if (value instanceof PdfDict) for (const [, v] of value) preResolveValue(v);
25811
- else if (value instanceof PdfArray) for (let i = 0; i < value.length; i++) preResolveValue(value.at(i));
25812
- };
25813
- preResolveValue(fontDictEntry.get("DescendantFonts"));
25814
- preResolveValue(fontDictEntry.get("FontDescriptor"));
25815
- preResolveValue(fontDictEntry.get("Encoding"));
25816
- preResolveValue(fontDictEntry.get("Widths"));
25817
- const pdfFont = parseFont(fontDictEntry, {
25818
- resolveRef: (ref) => {
25819
- if (ref instanceof PdfRef && this.ctx) {
25820
- const obj = this.ctx.resolve(ref);
25821
- if (obj instanceof PdfDict || obj instanceof PdfArray || obj instanceof PdfStream) return obj;
25822
- }
25823
- return null;
25824
- },
25825
- decodeStream: (stream) => {
25826
- if (stream instanceof PdfRef) {
25827
- const key$1 = `${stream.objectNumber} ${stream.generation} R`;
25828
- const decoded = decodedStreams.get(key$1);
25829
- if (decoded) return decoded;
25830
- const preResolved = resolvedRefs.get(key$1);
25831
- if (preResolved instanceof PdfStream) return preResolved.data;
25832
- }
25833
- if (stream instanceof PdfStream) {
25834
- for (const [key$1, resolved] of resolvedRefs) if (resolved === stream) {
25835
- const decoded = decodedStreams.get(key$1);
25836
- if (decoded) return decoded;
25837
- }
25838
- return stream.data;
25839
- }
25840
- return null;
25841
- },
25628
+ const toUnicode = entryDict.get("ToUnicode", this.ctx.resolve.bind(this.ctx));
25629
+ const toUnicodeStream = toUnicode instanceof PdfStream ? toUnicode : null;
25630
+ if (toUnicodeStream) try {
25631
+ toUnicodeMap = parseToUnicode(toUnicodeStream.getDecodedData());
25632
+ } catch {}
25633
+ const pdfFont = parseFont(entryDict, {
25634
+ resolver: this.ctx.resolve.bind(this.ctx),
25842
25635
  toUnicodeMap
25843
25636
  });
25844
25637
  fontCache.set(name, pdfFont);
@@ -25939,9 +25732,9 @@ var PDFLinkAnnotation = class extends PDFAnnotation {
25939
25732
  * Get the URI if this is an external link.
25940
25733
  */
25941
25734
  get uri() {
25942
- const action = this.dict.getDict("A");
25735
+ const action = this.dict.getDict("A", this.registry.resolve.bind(this.registry));
25943
25736
  if (action) {
25944
- if (action.getName("S")?.value === "URI") return action.getString("URI")?.asString() ?? null;
25737
+ if (action.getName("S", this.registry.resolve.bind(this.registry))?.value === "URI") return action.getString("URI", this.registry.resolve.bind(this.registry))?.asString() ?? null;
25945
25738
  }
25946
25739
  return null;
25947
25740
  }
@@ -25949,12 +25742,12 @@ var PDFLinkAnnotation = class extends PDFAnnotation {
25949
25742
  * Get the destination if this is an internal link.
25950
25743
  */
25951
25744
  get destination() {
25952
- const dest = this.dict.get("Dest");
25745
+ const dest = this.dict.get("Dest", this.registry.resolve.bind(this.registry));
25953
25746
  if (dest) return this.parseDestination(dest);
25954
- const action = this.dict.getDict("A");
25747
+ const action = this.dict.getDict("A", this.registry.resolve.bind(this.registry));
25955
25748
  if (action) {
25956
- if (action.getName("S")?.value === "GoTo") {
25957
- const d = action.get("D");
25749
+ if (action.getName("S", this.registry.resolve.bind(this.registry))?.value === "GoTo") {
25750
+ const d = action.get("D", this.registry.resolve.bind(this.registry));
25958
25751
  if (d) return this.parseDestination(d);
25959
25752
  }
25960
25753
  }
@@ -25974,12 +25767,12 @@ var PDFLinkAnnotation = class extends PDFAnnotation {
25974
25767
  type: "goto",
25975
25768
  destination: dest
25976
25769
  };
25977
- const action = this.dict.getDict("A");
25770
+ const action = this.dict.getDict("A", this.registry.resolve.bind(this.registry));
25978
25771
  if (action) {
25979
- const actionType = action.getName("S")?.value;
25772
+ const actionType = action.getName("S", this.registry.resolve.bind(this.registry))?.value;
25980
25773
  if (actionType === "GoToR") {
25981
- const file = action.getString("F")?.asString() ?? "";
25982
- const d = action.get("D");
25774
+ const file = action.getString("F", this.registry.resolve.bind(this.registry))?.asString() ?? "";
25775
+ const d = action.get("D", this.registry.resolve.bind(this.registry));
25983
25776
  return {
25984
25777
  type: "gotoRemote",
25985
25778
  file,
@@ -25994,7 +25787,7 @@ var PDFLinkAnnotation = class extends PDFAnnotation {
25994
25787
  * Highlight mode when the link is clicked.
25995
25788
  */
25996
25789
  get highlightMode() {
25997
- switch (this.dict.getName("H")?.value) {
25790
+ switch (this.dict.getName("H", this.registry.resolve.bind(this.registry))?.value) {
25998
25791
  case "N": return "None";
25999
25792
  case "I": return "Invert";
26000
25793
  case "O": return "Outline";
@@ -26183,7 +25976,7 @@ var PDFUnknownAnnotation = class extends PDFAnnotation {};
26183
25976
  * @returns The appropriate annotation class instance
26184
25977
  */
26185
25978
  function createAnnotation(dict, ref, registry) {
26186
- const subtypeName = dict.getName("Subtype")?.value;
25979
+ const subtypeName = dict.getName("Subtype", registry.resolve.bind(registry))?.value;
26187
25980
  switch (isAnnotationSubtype(subtypeName) ? subtypeName : "Text") {
26188
25981
  case "Text": return new PDFTextAnnotation(dict, ref, registry);
26189
25982
  case "Link": return new PDFLinkAnnotation(dict, ref, registry);
@@ -26209,14 +26002,14 @@ function createAnnotation(dict, ref, registry) {
26209
26002
  /**
26210
26003
  * Check if an annotation is a Widget (form field).
26211
26004
  */
26212
- function isWidgetAnnotation(dict) {
26213
- return dict.getName("Subtype")?.value === "Widget";
26005
+ function isWidgetAnnotation(dict, registry) {
26006
+ return dict.getName("Subtype", registry?.resolve.bind(registry))?.value === "Widget";
26214
26007
  }
26215
26008
  /**
26216
26009
  * Check if an annotation is a Popup.
26217
26010
  */
26218
- function isPopupAnnotation(dict) {
26219
- return dict.getName("Subtype")?.value === "Popup";
26011
+ function isPopupAnnotation(dict, registry) {
26012
+ return dict.getName("Subtype", registry?.resolve.bind(registry))?.value === "Popup";
26220
26013
  }
26221
26014
 
26222
26015
  //#endregion
@@ -26264,19 +26057,14 @@ var AnnotationFlattener = class {
26264
26057
  * @returns Number of annotations flattened
26265
26058
  */
26266
26059
  flattenPage(pageDict, options = {}) {
26267
- let annotsEntry = pageDict.get("Annots");
26268
- if (!annotsEntry) return 0;
26269
- if (annotsEntry instanceof PdfRef) annotsEntry = this.registry.resolve(annotsEntry) ?? void 0;
26270
- let annots = annotsEntry instanceof PdfArray ? annotsEntry : null;
26060
+ let annots = pageDict.getArray("Annots", this.registry.resolve.bind(this.registry));
26271
26061
  if (!annots || annots.length === 0) return 0;
26272
- let resources = pageDict.get("Resources");
26273
- if (resources instanceof PdfRef) resources = this.registry.resolve(resources) ?? void 0;
26062
+ let resources = pageDict.get("Resources", this.registry.resolve.bind(this.registry));
26274
26063
  if (!(resources instanceof PdfDict)) {
26275
26064
  resources = new PdfDict();
26276
26065
  pageDict.set("Resources", resources);
26277
26066
  }
26278
- let xObjects = resources.get("XObject");
26279
- if (xObjects instanceof PdfRef) xObjects = this.registry.resolve(xObjects) ?? void 0;
26067
+ let xObjects = resources.get("XObject", this.registry.resolve.bind(this.registry));
26280
26068
  if (!(xObjects instanceof PdfDict)) {
26281
26069
  xObjects = new PdfDict();
26282
26070
  resources.set("XObject", xObjects);
@@ -26286,19 +26074,20 @@ var AnnotationFlattener = class {
26286
26074
  let xObjectIndex = 0;
26287
26075
  let flattenedCount = 0;
26288
26076
  for (let i = 0; i < annots.length; i++) {
26289
- const entry = annots.at(i);
26077
+ let entry = annots.at(i);
26290
26078
  if (!entry) continue;
26291
26079
  let annotDict = null;
26292
26080
  let annotRef = null;
26293
26081
  if (entry instanceof PdfRef) {
26294
26082
  annotRef = entry;
26295
- const resolved = this.registry.resolve(entry);
26296
- if (resolved instanceof PdfDict) annotDict = resolved;
26297
- } else if (entry instanceof PdfDict) annotDict = entry;
26083
+ entry = this.registry.resolve(entry) ?? void 0;
26084
+ }
26085
+ if (entry instanceof PdfDict) annotDict = entry;
26298
26086
  if (!annotDict) continue;
26299
26087
  if (isWidgetAnnotation(annotDict)) continue;
26300
26088
  if (isPopupAnnotation(annotDict)) continue;
26301
- const subtype = annotDict.getName("Subtype")?.value;
26089
+ const subtypeName = annotDict.getName("Subtype")?.value;
26090
+ const subtype = isAnnotationSubtype(subtypeName) ? subtypeName : null;
26302
26091
  if (!subtype) continue;
26303
26092
  if (subtype === "Link") {
26304
26093
  if (options.removeLinks) {
@@ -26407,9 +26196,7 @@ var AnnotationFlattener = class {
26407
26196
  * Get annotation rectangle as [x1, y1, x2, y2].
26408
26197
  */
26409
26198
  getAnnotationRect(annotDict) {
26410
- let rectArray = annotDict.get("Rect");
26411
- if (rectArray instanceof PdfRef) rectArray = this.registry.resolve(rectArray) ?? void 0;
26412
- let rect = rectArray instanceof PdfArray ? rectArray : null;
26199
+ const rect = annotDict.getArray("Rect", this.registry.resolve.bind(this.registry));
26413
26200
  if (!rect || rect.length < 4) return [
26414
26201
  0,
26415
26202
  0,
@@ -26471,7 +26258,7 @@ var AnnotationFlattener = class {
26471
26258
  * Get appearance BBox, with fallback.
26472
26259
  */
26473
26260
  getAppearanceBBox(appearance) {
26474
- const bbox = appearance.getArray("BBox");
26261
+ const bbox = appearance.getArray("BBox", this.registry.resolve.bind(this.registry));
26475
26262
  if (!bbox || bbox.length < 4) return [
26476
26263
  0,
26477
26264
  0,
@@ -26490,7 +26277,7 @@ var AnnotationFlattener = class {
26490
26277
  * Get the appearance stream's transformation matrix.
26491
26278
  */
26492
26279
  getAppearanceMatrix(appearance) {
26493
- const matrixArray = appearance.getArray("Matrix");
26280
+ const matrixArray = appearance.getArray("Matrix", this.registry.resolve.bind(this.registry));
26494
26281
  if (!matrixArray || matrixArray.length < 6) return Matrix.identity();
26495
26282
  const [a, b, c, d, e, f] = matrixArray.toArray().map((item) => item instanceof PdfNumber ? item.value : 0);
26496
26283
  return new Matrix(a ?? 0, b ?? 0, c ?? 0, d ?? 0, e ?? 0, f ?? 0);
@@ -26499,7 +26286,7 @@ var AnnotationFlattener = class {
26499
26286
  * Check if appearance stream has valid dimensions.
26500
26287
  */
26501
26288
  isVisibleAppearance(appearance) {
26502
- const bbox = appearance.getArray("BBox");
26289
+ const bbox = appearance.getArray("BBox", this.registry.resolve.bind(this.registry));
26503
26290
  if (!bbox || bbox.length < 4) return false;
26504
26291
  const [x1, y1, x2, y2] = bbox.toArray().map((item) => item instanceof PdfNumber ? item.value : 0);
26505
26292
  const width = Math.abs((x2 ?? 0) - (x1 ?? 0));
@@ -26515,6 +26302,8 @@ var AnnotationFlattener = class {
26515
26302
  }
26516
26303
  /**
26517
26304
  * Wrap existing page content in q...Q and append new content.
26305
+ *
26306
+ * @todo Consider using PDFPage API for this.
26518
26307
  */
26519
26308
  wrapAndAppendContent(page, newContent) {
26520
26309
  const existing = page.get("Contents");
@@ -26563,7 +26352,8 @@ var AnnotationFlattener = class {
26563
26352
  if (annotsEntry instanceof PdfRef) {
26564
26353
  const resolved = this.registry.resolve(annotsEntry);
26565
26354
  annots = resolved instanceof PdfArray ? resolved : void 0;
26566
- } else if (annotsEntry instanceof PdfArray) annots = annotsEntry;
26355
+ }
26356
+ if (annotsEntry instanceof PdfArray) annots = annotsEntry;
26567
26357
  if (!annots) return;
26568
26358
  const indicesToRemove = [];
26569
26359
  for (let i = 0; i < annots.length; i++) {
@@ -27745,17 +27535,10 @@ function parseDefaultConfig(dDict, resolve) {
27745
27535
  function hasLayers(ctx) {
27746
27536
  const catalog = ctx.catalog.getDict();
27747
27537
  if (!catalog) return false;
27748
- let ocProperties = catalog.get("OCProperties");
27749
- if (!ocProperties) return false;
27750
- let ocPropsDict = null;
27751
- if (ocProperties instanceof PdfRef) ocProperties = ctx.resolve(ocProperties) ?? void 0;
27752
- if (ocProperties instanceof PdfDict) ocPropsDict = ocProperties;
27538
+ const resolve = ctx.resolve.bind(ctx);
27539
+ const ocPropsDict = catalog.getDict("OCProperties", resolve);
27753
27540
  if (!ocPropsDict) return false;
27754
- let ocgs = ocPropsDict.get("OCGs");
27755
- if (!ocgs) return false;
27756
- let ocgsArray = null;
27757
- if (ocgs instanceof PdfRef) ocgs = ctx.resolve(ocgs) ?? void 0;
27758
- if (ocgs instanceof PdfArray) ocgsArray = ocgs;
27541
+ const ocgsArray = ocPropsDict.getArray("OCGs", resolve);
27759
27542
  if (!ocgsArray || ocgsArray.length === 0) return false;
27760
27543
  return true;
27761
27544
  }
@@ -27768,19 +27551,12 @@ function hasLayers(ctx) {
27768
27551
  function getLayers(ctx) {
27769
27552
  const catalog = ctx.catalog.getDict();
27770
27553
  if (!catalog) return [];
27771
- let ocProperties = catalog.get("OCProperties");
27772
- if (!ocProperties) return [];
27773
- let ocPropsDict = null;
27774
- if (ocProperties instanceof PdfRef) ocProperties = ctx.resolve(ocProperties) ?? void 0;
27775
- if (ocProperties instanceof PdfDict) ocPropsDict = ocProperties;
27554
+ const resolve = ctx.resolve.bind(ctx);
27555
+ const ocPropsDict = catalog.getDict("OCProperties", resolve);
27776
27556
  if (!ocPropsDict) return [];
27777
- let ocgs = ocPropsDict.get("OCGs");
27778
- if (!ocgs) return [];
27779
- let ocgsArray = null;
27780
- if (ocgs instanceof PdfRef) ocgs = ctx.resolve(ocgs) ?? void 0;
27781
- if (ocgs instanceof PdfArray) ocgsArray = ocgs;
27557
+ const ocgsArray = ocPropsDict.getArray("OCGs", resolve);
27782
27558
  if (!ocgsArray) return [];
27783
- const defaultConfig = parseDefaultConfig(ocPropsDict.get("D"), (ref) => ctx.resolve(ref));
27559
+ const defaultConfig = parseDefaultConfig(ocPropsDict.get("D"), resolve);
27784
27560
  const layers = [];
27785
27561
  for (const item of ocgsArray) {
27786
27562
  if (!(item instanceof PdfRef)) continue;
@@ -30834,22 +30610,36 @@ var DocumentParser = class {
30834
30610
  else throw error;
30835
30611
  }
30836
30612
  const lengthResolver = (ref) => {
30837
- const key$1 = `${ref.objectNumber} ${ref.generation}`;
30838
- const cached = cache.get(key$1);
30839
- if (cached && cached.type === "number") return cached.value;
30613
+ const cacheKey = `${ref.objectNumber} ${ref.generation}`;
30614
+ const cached = cache.get(cacheKey);
30615
+ if (cached instanceof PdfNumber) return cached.value;
30840
30616
  const entry = xref.get(ref.objectNumber);
30841
- if (entry?.type === "uncompressed") {
30842
- const savedPosition = this.scanner.position;
30843
- try {
30844
- const result = new IndirectObjectParser(this.scanner).parseObjectAt(entry.offset);
30845
- if (result.value.type === "number") {
30846
- cache.set(key$1, result.value);
30847
- this.scanner.moveTo(savedPosition);
30848
- return result.value.value;
30617
+ if (!entry || entry.type === "free") return null;
30618
+ const savedPosition = this.scanner.position;
30619
+ try {
30620
+ let lengthObj = null;
30621
+ if (entry.type === "uncompressed") lengthObj = new IndirectObjectParser(this.scanner).parseObjectAt(entry.offset).value;
30622
+ else {
30623
+ const streamEntry = xref.get(entry.streamObjNum);
30624
+ if (streamEntry?.type === "uncompressed") {
30625
+ let objStreamParser = objectStreamCache.get(entry.streamObjNum);
30626
+ if (!objStreamParser) {
30627
+ const streamResult = new IndirectObjectParser(this.scanner).parseObjectAt(streamEntry.offset);
30628
+ if (streamResult.value instanceof PdfStream) {
30629
+ objStreamParser = new ObjectStreamParser(streamResult.value);
30630
+ objectStreamCache.set(entry.streamObjNum, objStreamParser);
30631
+ }
30632
+ }
30633
+ if (objStreamParser) lengthObj = objStreamParser.getObject(entry.indexInStream);
30849
30634
  }
30850
- } catch {
30851
- this.scanner.moveTo(savedPosition);
30852
30635
  }
30636
+ this.scanner.moveTo(savedPosition);
30637
+ if (lengthObj instanceof PdfNumber) {
30638
+ cache.set(cacheKey, lengthObj);
30639
+ return lengthObj.value;
30640
+ }
30641
+ } catch {
30642
+ this.scanner.moveTo(savedPosition);
30853
30643
  }
30854
30644
  return null;
30855
30645
  };
@@ -30944,7 +30734,7 @@ var DocumentParser = class {
30944
30734
  if (type?.value === "Page") {
30945
30735
  if (currentRef) pages.push(currentRef);
30946
30736
  } else if (type?.value === "Pages") {
30947
- const kids = nodeOrRef.getArray("Kids");
30737
+ const kids = nodeOrRef.getArray("Kids", getObject);
30948
30738
  if (kids) for (let i = 0; i < kids.length; i++) {
30949
30739
  const kid = kids.at(i);
30950
30740
  if (kid instanceof PdfRef) walkNode(kid);
@@ -31733,12 +31523,7 @@ function decodeFilename(str) {
31733
31523
  * @returns The stream if found, null if external reference or missing
31734
31524
  */
31735
31525
  function getEmbeddedFileStream(fileSpec, resolver) {
31736
- const efEntry = fileSpec.get("EF");
31737
- let ef = null;
31738
- if (efEntry instanceof PdfRef) {
31739
- const resolved = resolver(efEntry);
31740
- if (resolved instanceof PdfDict) ef = resolved;
31741
- } else if (efEntry instanceof PdfDict) ef = efEntry;
31526
+ const ef = fileSpec.getDict("EF", resolver);
31742
31527
  if (!ef) return null;
31743
31528
  const streamRef = ef.getRef("F") ?? ef.getRef("UF");
31744
31529
  if (!streamRef) return null;
@@ -31765,12 +31550,7 @@ function parseFileSpec(fileSpec, name, resolver) {
31765
31550
  if (desc) info.description = desc.asString();
31766
31551
  const subtype = stream.getName("Subtype");
31767
31552
  if (subtype) info.mimeType = subtype.value.replaceAll("#2F", "/").replaceAll("#20", " ");
31768
- const paramsEntry = stream.get("Params");
31769
- let params = null;
31770
- if (paramsEntry instanceof PdfRef) {
31771
- const resolved = resolver(paramsEntry);
31772
- if (resolved instanceof PdfDict) params = resolved;
31773
- } else if (paramsEntry instanceof PdfDict) params = paramsEntry;
31553
+ const params = stream.getDict("Params", resolver);
31774
31554
  if (params) {
31775
31555
  const size = params.getNumber("Size");
31776
31556
  if (size) info.size = size.value;
@@ -31881,12 +31661,7 @@ var NameTree = class {
31881
31661
  let found = false;
31882
31662
  while (lo$1 <= hi$1) {
31883
31663
  const mid = lo$1 + hi$1 >>> 1;
31884
- const kidRef = kids.at(mid);
31885
- if (!(kidRef instanceof PdfRef)) {
31886
- lo$1 = mid + 1;
31887
- continue;
31888
- }
31889
- const kid = this.resolver(kidRef);
31664
+ const kid = kids.at(mid, this.resolver);
31890
31665
  if (!(kid instanceof PdfDict)) {
31891
31666
  lo$1 = mid + 1;
31892
31667
  continue;
@@ -31929,16 +31704,10 @@ var NameTree = class {
31929
31704
  else if (cmp > 0) lo = mid + 1;
31930
31705
  else {
31931
31706
  const valueIndex = keyIndex + 1;
31932
- const value = names.at(valueIndex);
31933
- if (value instanceof PdfRef) return this.resolver(value);
31934
- return value ?? null;
31707
+ return names.at(valueIndex, this.resolver) ?? null;
31935
31708
  }
31936
31709
  }
31937
- for (let i = 0; i < names.length; i += 2) if (extractKey(names.at(i)) === key$1) {
31938
- const value = names.at(i + 1);
31939
- if (value instanceof PdfRef) return this.resolver(value);
31940
- return value ?? null;
31941
- }
31710
+ for (let i = 0; i < names.length; i += 2) if (extractKey(names.at(i)) === key$1) return names.at(i + 1, this.resolver) ?? null;
31942
31711
  return null;
31943
31712
  }
31944
31713
  /**
@@ -31965,15 +31734,17 @@ var NameTree = class {
31965
31734
  }
31966
31735
  if (node.has("Kids")) {
31967
31736
  const kids = node.getArray("Kids");
31968
- if (kids) for (const kidRef of kids) {
31969
- if (!(kidRef instanceof PdfRef)) continue;
31970
- const refKey$1 = `${kidRef.objectNumber}:${kidRef.generation}`;
31971
- if (visited.has(refKey$1)) {
31972
- console.warn(`NameTree: circular reference detected at ${refKey$1}`);
31973
- continue;
31737
+ if (kids) for (let i = 0; i < kids.length; i++) {
31738
+ const kidRef = kids.at(i);
31739
+ if (kidRef instanceof PdfRef) {
31740
+ const refKey$1 = `${kidRef.objectNumber}:${kidRef.generation}`;
31741
+ if (visited.has(refKey$1)) {
31742
+ console.warn(`NameTree: circular reference detected at ${refKey$1}`);
31743
+ continue;
31744
+ }
31745
+ visited.add(refKey$1);
31974
31746
  }
31975
- visited.add(refKey$1);
31976
- const kid = this.resolver(kidRef);
31747
+ const kid = kids.at(i, this.resolver);
31977
31748
  if (kid instanceof PdfDict) queue.push({
31978
31749
  node: kid,
31979
31750
  depth: depth + 1
@@ -31984,9 +31755,8 @@ var NameTree = class {
31984
31755
  if (names) for (let i = 0; i < names.length; i += 2) {
31985
31756
  const key$1 = extractKey(names.at(i));
31986
31757
  if (key$1 === null) continue;
31987
- let value = names.at(i + 1) ?? null;
31988
- if (value instanceof PdfRef) value = this.resolver(value);
31989
- if (value !== null && value !== void 0) yield [key$1, value];
31758
+ const value = names.at(i + 1, this.resolver);
31759
+ if (value !== void 0) yield [key$1, value];
31990
31760
  }
31991
31761
  }
31992
31762
  }
@@ -32253,9 +32023,7 @@ var PDFCatalog = class {
32253
32023
  * Get the /Names dictionary.
32254
32024
  */
32255
32025
  getNames() {
32256
- let namesEntry = this.dict.get("Names");
32257
- if (namesEntry instanceof PdfRef) namesEntry = this.registry.resolve(namesEntry) ?? void 0;
32258
- return namesEntry instanceof PdfDict ? namesEntry : null;
32026
+ return this.dict.getDict("Names", this.registry.resolve.bind(this.registry)) ?? null;
32259
32027
  }
32260
32028
  /**
32261
32029
  * Get or create the /Names dictionary.
@@ -32279,12 +32047,7 @@ var PDFCatalog = class {
32279
32047
  this._embeddedFilesTree = null;
32280
32048
  return null;
32281
32049
  }
32282
- const embeddedFilesEntry = names.get("EmbeddedFiles");
32283
- let embeddedFiles = null;
32284
- if (embeddedFilesEntry instanceof PdfRef) {
32285
- const resolved = this.registry.resolve(embeddedFilesEntry);
32286
- if (resolved instanceof PdfDict) embeddedFiles = resolved;
32287
- } else if (embeddedFilesEntry instanceof PdfDict) embeddedFiles = embeddedFilesEntry;
32050
+ const embeddedFiles = names.getDict("EmbeddedFiles", this.registry.resolve.bind(this.registry));
32288
32051
  if (!embeddedFiles) {
32289
32052
  this._embeddedFilesTree = null;
32290
32053
  return null;
@@ -34978,14 +34741,7 @@ var PDFForm = class PDFForm {
34978
34741
  for (const pageRef of pageRefs) {
34979
34742
  const pageDict = this._ctx.registry.resolve(pageRef);
34980
34743
  if (!(pageDict instanceof PdfDict)) continue;
34981
- const annotsEntry = pageDict.get("Annots");
34982
- if (!annotsEntry) continue;
34983
- let annots = null;
34984
- if (annotsEntry instanceof PdfArray) annots = annotsEntry;
34985
- else if (annotsEntry instanceof PdfRef) {
34986
- const resolved = this._ctx.registry.resolve(annotsEntry);
34987
- if (resolved instanceof PdfArray) annots = resolved;
34988
- }
34744
+ const annots = pageDict.getArray("Annots", this._ctx.registry.resolve.bind(this._ctx.registry));
34989
34745
  if (!annots) continue;
34990
34746
  for (let i = annots.length - 1; i >= 0; i--) {
34991
34747
  const item = annots.at(i);
@@ -35946,49 +35702,28 @@ var DSSBuilder = class DSSBuilder {
35946
35702
  */
35947
35703
  static async fromCatalog(catalog, registry, options) {
35948
35704
  const builder = new DSSBuilder(registry, options);
35949
- const dssVal = catalog.get("DSS");
35950
- if (!dssVal) return builder;
35951
- let dss;
35952
- if (dssVal instanceof PdfDict) dss = dssVal;
35953
- else if (dssVal instanceof PdfRef) {
35954
- const resolved = registry.resolve(dssVal);
35955
- if (!(resolved instanceof PdfDict)) return builder;
35956
- dss = resolved;
35957
- } else return builder;
35705
+ const resolve = registry.resolve.bind(registry);
35706
+ const dss = catalog.getDict("DSS", resolve);
35707
+ if (!dss) return builder;
35958
35708
  await builder.loadExistingData(dss, "Certs", builder.certMap, builder.existingCertRefs);
35959
35709
  await builder.loadExistingData(dss, "OCSPs", builder.ocspMap, builder.existingOcspRefs);
35960
35710
  await builder.loadExistingData(dss, "CRLs", builder.crlMap, builder.existingCrlRefs);
35961
- const vriVal = dss.get("VRI");
35962
- if (vriVal) {
35963
- let vri;
35964
- if (vriVal instanceof PdfDict) vri = vriVal;
35965
- else if (vriVal instanceof PdfRef) {
35966
- const resolved = registry.resolve(vriVal);
35967
- if (!(resolved instanceof PdfDict)) return builder;
35968
- vri = resolved;
35969
- } else return builder;
35970
- for (const key$1 of vri.keys()) {
35971
- const entryVal = vri.get(key$1);
35972
- if (entryVal) {
35973
- let entry;
35974
- if (entryVal instanceof PdfDict) entry = entryVal;
35975
- else if (entryVal instanceof PdfRef) {
35976
- const resolved = registry.resolve(entryVal);
35977
- if (!(resolved instanceof PdfDict)) continue;
35978
- entry = resolved;
35979
- } else continue;
35980
- const certHashes = await builder.extractRefHashes(entry, "Cert", builder.certMap);
35981
- const ocspHashes = await builder.extractRefHashes(entry, "OCSP", builder.ocspMap);
35982
- const crlHashes = await builder.extractRefHashes(entry, "CRL", builder.crlMap);
35983
- let timestamp;
35984
- if (entry.get("TU") instanceof PdfString) timestamp = /* @__PURE__ */ new Date();
35985
- builder.vriEntries.set(key$1.value.toUpperCase(), {
35986
- certHashes,
35987
- ocspHashes,
35988
- crlHashes,
35989
- timestamp
35990
- });
35991
- }
35711
+ const vri = dss.getDict("VRI", resolve);
35712
+ if (vri) for (const key$1 of vri.keys()) {
35713
+ const entryVal = vri.get(key$1, resolve);
35714
+ const entry = entryVal instanceof PdfDict ? entryVal : null;
35715
+ if (entry) {
35716
+ const certHashes = await builder.extractRefHashes(entry, "Cert", builder.certMap);
35717
+ const ocspHashes = await builder.extractRefHashes(entry, "OCSP", builder.ocspMap);
35718
+ const crlHashes = await builder.extractRefHashes(entry, "CRL", builder.crlMap);
35719
+ let timestamp;
35720
+ if (entry.getString("TU", resolve)) timestamp = /* @__PURE__ */ new Date();
35721
+ builder.vriEntries.set(key$1.value.toUpperCase(), {
35722
+ certHashes,
35723
+ ocspHashes,
35724
+ crlHashes,
35725
+ timestamp
35726
+ });
35992
35727
  }
35993
35728
  }
35994
35729
  return builder;
@@ -36069,11 +35804,8 @@ var DSSBuilder = class DSSBuilder {
36069
35804
  * Load existing data from DSS array.
36070
35805
  */
36071
35806
  async loadExistingData(dss, key$1, dataMap, refMap) {
36072
- let arrayVal = dss.get(key$1);
36073
- if (!arrayVal) return;
36074
- let array;
36075
- if (arrayVal instanceof PdfRef) arrayVal = this.registry.resolve(arrayVal) ?? void 0;
36076
- if (arrayVal instanceof PdfArray) array = arrayVal;
35807
+ const resolve = this.registry.resolve.bind(this.registry);
35808
+ const array = dss.getArray(key$1, resolve);
36077
35809
  if (!array) return;
36078
35810
  for (const item of array) if (item instanceof PdfRef) {
36079
35811
  const stream = this.registry.resolve(item);
@@ -36093,10 +35825,8 @@ var DSSBuilder = class DSSBuilder {
36093
35825
  */
36094
35826
  async extractRefHashes(entry, key$1, dataMap) {
36095
35827
  const hashes = [];
36096
- let arrayVal = entry.get(key$1);
36097
- if (!arrayVal) return hashes;
36098
- if (arrayVal instanceof PdfRef) arrayVal = this.registry.resolve(arrayVal) ?? void 0;
36099
- const array = arrayVal instanceof PdfArray ? arrayVal : null;
35828
+ const resolve = this.registry.resolve.bind(this.registry);
35829
+ const array = entry.getArray(key$1, resolve);
36100
35830
  if (!array) return hashes;
36101
35831
  for (const item of array) if (item instanceof PdfRef) {
36102
35832
  const stream = this.registry.resolve(item);
@@ -38324,12 +38054,8 @@ var PDF = class PDF {
38324
38054
  */
38325
38055
  getOrCreateViewerPreferences() {
38326
38056
  const catalog = this.ctx.catalog.getDict();
38327
- const existing = catalog.get("ViewerPreferences");
38328
- if (existing instanceof PdfDict) return existing;
38329
- if (existing instanceof PdfRef) {
38330
- const resolved = this.ctx.registry.getObject(existing);
38331
- if (resolved instanceof PdfDict) return resolved;
38332
- }
38057
+ const existing = catalog.getDict("ViewerPreferences", this.ctx.resolve.bind(this.ctx));
38058
+ if (existing) return existing;
38333
38059
  const prefs = new PdfDict();
38334
38060
  catalog.set("ViewerPreferences", prefs);
38335
38061
  return prefs;
@@ -38380,24 +38106,9 @@ var PDF = class PDF {
38380
38106
  if (!ref) return null;
38381
38107
  const dict = this.ctx.resolve(ref);
38382
38108
  if (!(dict instanceof PdfDict)) return null;
38383
- this.ensurePageResourcesResolved(dict);
38384
38109
  return new PDFPage(ref, dict, index, this.ctx);
38385
38110
  }
38386
38111
  /**
38387
- * Ensure page resources are resolved (not a reference).
38388
- *
38389
- * Pages may have Resources as a PdfRef pointing to a shared resources dict.
38390
- * The sync getResources() method on PDFPage needs the actual dict, not a ref.
38391
- * This resolves the reference and replaces it in the page dict.
38392
- */
38393
- ensurePageResourcesResolved(pageDict) {
38394
- const resources = pageDict.get("Resources");
38395
- if (resources instanceof PdfRef) {
38396
- const resolved = this.ctx.resolve(resources);
38397
- if (resolved instanceof PdfDict) pageDict.set("Resources", resolved.clone());
38398
- }
38399
- }
38400
- /**
38401
38112
  * Add a new blank page.
38402
38113
  *
38403
38114
  * @param options - Page size, rotation, and insertion position
@@ -38582,14 +38293,12 @@ var PDF = class PDF {
38582
38293
  if (!srcPage) throw new RangeError(`Page index ${pageIndex} out of bounds`);
38583
38294
  const contentData = this.getPageContentData(source, srcPage);
38584
38295
  const copier = new ObjectCopier(source, this, { includeAnnotations: false });
38585
- let srcResources = srcPage.dict.get("Resources");
38586
- let resources = void 0;
38587
- if (srcResources instanceof PdfRef) srcResources = source.getObject(srcResources) ?? void 0;
38588
- if (srcResources instanceof PdfDict) {
38296
+ const srcResources = srcPage.dict.getDict("Resources", source.getObject.bind(source));
38297
+ let resources;
38298
+ if (srcResources) {
38589
38299
  const copied = await copier.copyObject(srcResources);
38590
- if (copied instanceof PdfDict) resources = copied;
38591
- }
38592
- if (!resources) resources = new PdfDict();
38300
+ resources = copied instanceof PdfDict ? copied : new PdfDict();
38301
+ } else resources = new PdfDict();
38593
38302
  const mediaBox = srcPage.getMediaBox();
38594
38303
  const formXObject = PdfStream.fromDict({
38595
38304
  Type: PdfName.of("XObject"),
@@ -38609,13 +38318,9 @@ var PDF = class PDF {
38609
38318
  * Get the concatenated content stream data from a page.
38610
38319
  */
38611
38320
  getPageContentData(source, page) {
38612
- const contents = page.dict.get("Contents");
38321
+ const contents = page.dict.get("Contents", source.getObject.bind(source));
38613
38322
  if (!contents) return new Uint8Array(0);
38614
- if (contents instanceof PdfRef) {
38615
- const stream = source.getObject(contents);
38616
- if (stream instanceof PdfStream) return stream.getDecodedData();
38617
- return new Uint8Array(0);
38618
- }
38323
+ if (contents instanceof PdfStream) return contents.getDecodedData();
38619
38324
  if (contents instanceof PdfArray) {
38620
38325
  const chunks = [];
38621
38326
  for (let i = 0; i < contents.length; i++) {
@@ -38637,7 +38342,6 @@ var PDF = class PDF {
38637
38342
  }
38638
38343
  return result;
38639
38344
  }
38640
- if (contents instanceof PdfStream) return contents.getDecodedData();
38641
38345
  return new Uint8Array(0);
38642
38346
  }
38643
38347
  /**