pdfjs-dist 2.5.207 → 2.6.347

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.

Potentially problematic release.


This version of pdfjs-dist might be problematic. Click here for more details.

Files changed (133) hide show
  1. package/bower.json +1 -1
  2. package/build/pdf.js +867 -216
  3. package/build/pdf.js.map +1 -1
  4. package/build/pdf.min.js +1 -1
  5. package/build/pdf.worker.js +10214 -8547
  6. package/build/pdf.worker.js.map +1 -1
  7. package/build/pdf.worker.min.js +1 -1
  8. package/es5/build/pdf.js +2023 -1046
  9. package/es5/build/pdf.js.map +1 -1
  10. package/es5/build/pdf.min.js +22 -0
  11. package/es5/build/pdf.worker.js +11136 -8144
  12. package/es5/build/pdf.worker.js.map +1 -1
  13. package/es5/build/pdf.worker.min.js +22 -0
  14. package/es5/image_decoders/pdf.image_decoders.js +12529 -0
  15. package/es5/image_decoders/pdf.image_decoders.js.map +1 -0
  16. package/es5/image_decoders/pdf.image_decoders.min.js +22 -0
  17. package/es5/web/images/shadow.png +0 -0
  18. package/es5/web/pdf_viewer.css +8 -5
  19. package/es5/web/pdf_viewer.js +195 -51
  20. package/es5/web/pdf_viewer.js.map +1 -1
  21. package/image_decoders/pdf.image_decoders.js +24 -16
  22. package/image_decoders/pdf.image_decoders.js.map +1 -1
  23. package/image_decoders/pdf.image_decoders.min.js +1 -1
  24. package/lib/core/annotation.js +479 -43
  25. package/lib/core/cff_parser.js +643 -615
  26. package/lib/core/chunked_stream.js +64 -50
  27. package/lib/core/colorspace.js +126 -104
  28. package/lib/core/crypto.js +37 -0
  29. package/lib/core/document.js +128 -75
  30. package/lib/core/evaluator.js +3015 -2754
  31. package/lib/core/fonts.js +47 -46
  32. package/lib/core/function.js +79 -6
  33. package/lib/core/image.js +364 -357
  34. package/lib/core/image_utils.js +109 -8
  35. package/lib/core/jpg.js +8 -3
  36. package/lib/core/obj.js +255 -34
  37. package/lib/core/operator_list.js +17 -15
  38. package/lib/core/parser.js +40 -3
  39. package/lib/core/pattern.js +24 -11
  40. package/lib/core/primitives.js +112 -53
  41. package/lib/core/type1_parser.js +2 -0
  42. package/lib/core/worker.js +102 -37
  43. package/lib/core/writer.js +242 -0
  44. package/lib/display/annotation_layer.js +51 -10
  45. package/lib/display/annotation_storage.js +89 -0
  46. package/lib/display/api.js +140 -54
  47. package/lib/display/canvas.js +215 -46
  48. package/lib/display/display_utils.js +55 -18
  49. package/lib/display/fetch_stream.js +6 -0
  50. package/lib/display/font_loader.js +26 -15
  51. package/lib/display/metadata.js +1 -7
  52. package/lib/display/network.js +0 -14
  53. package/lib/display/node_utils.js +87 -0
  54. package/lib/display/optional_content_config.js +184 -0
  55. package/lib/display/svg.js +1 -1
  56. package/lib/display/text_layer.js +4 -1
  57. package/lib/pdf.js +2 -2
  58. package/lib/pdf.worker.js +2 -2
  59. package/lib/shared/is_node.js +1 -1
  60. package/lib/shared/util.js +13 -10
  61. package/lib/test/unit/annotation_spec.js +520 -50
  62. package/lib/test/unit/annotation_storage_spec.js +83 -0
  63. package/lib/test/unit/api_spec.js +16 -6
  64. package/lib/test/unit/cmap_spec.js +4 -4
  65. package/lib/test/unit/colorspace_spec.js +216 -24
  66. package/lib/test/unit/crypto_spec.js +51 -4
  67. package/lib/test/unit/custom_spec.js +129 -1
  68. package/lib/test/unit/document_spec.js +112 -1
  69. package/lib/test/unit/evaluator_spec.js +29 -10
  70. package/lib/test/unit/jasmine-boot.js +1 -1
  71. package/lib/test/unit/metadata_spec.js +3 -3
  72. package/lib/test/unit/primitives_spec.js +242 -63
  73. package/lib/test/unit/test_utils.js +42 -89
  74. package/lib/test/unit/testreporter.js +17 -6
  75. package/lib/test/unit/util_spec.js +13 -12
  76. package/lib/test/unit/writer_spec.js +84 -0
  77. package/lib/web/annotation_layer_builder.js +13 -9
  78. package/lib/web/app.js +231 -26
  79. package/lib/web/app_options.js +1 -6
  80. package/lib/web/base_tree_viewer.js +100 -0
  81. package/lib/web/base_viewer.js +53 -4
  82. package/lib/web/download_manager.js +3 -10
  83. package/lib/web/firefox_print_service.js +32 -12
  84. package/lib/web/firefoxcom.js +20 -6
  85. package/lib/web/interfaces.js +1 -1
  86. package/lib/web/pdf_attachment_viewer.js +80 -38
  87. package/lib/web/pdf_find_controller.js +2 -1
  88. package/lib/web/pdf_layer_viewer.js +208 -0
  89. package/lib/web/pdf_outline_viewer.js +24 -57
  90. package/lib/web/pdf_page_view.js +29 -6
  91. package/lib/web/pdf_print_service.js +13 -11
  92. package/lib/web/pdf_sidebar.js +46 -25
  93. package/lib/web/pdf_thumbnail_view.js +16 -3
  94. package/lib/web/pdf_thumbnail_viewer.js +17 -1
  95. package/lib/web/pdf_viewer.component.js +2 -2
  96. package/lib/web/preferences.js +1 -1
  97. package/lib/web/toolbar.js +1 -1
  98. package/lib/web/ui_utils.js +7 -1
  99. package/package.json +3 -1
  100. package/types/display/annotation_layer.d.ts +61 -0
  101. package/types/display/annotation_storage.d.ts +36 -0
  102. package/types/display/api.d.ts +1107 -0
  103. package/types/display/api_compatibility.d.ts +1 -0
  104. package/types/display/canvas.d.ts +4 -0
  105. package/types/display/content_disposition.d.ts +7 -0
  106. package/types/display/display_utils.d.ts +243 -0
  107. package/types/display/fetch_stream.d.ts +67 -0
  108. package/types/display/font_loader.d.ts +19 -0
  109. package/types/display/metadata.d.ts +9 -0
  110. package/types/display/network.d.ts +80 -0
  111. package/types/display/network_utils.d.ts +14 -0
  112. package/types/display/node_stream.d.ts +72 -0
  113. package/types/display/node_utils.d.ts +6 -0
  114. package/types/display/optional_content_config.d.ts +12 -0
  115. package/types/display/pattern_helper.d.ts +5 -0
  116. package/types/display/svg.d.ts +2 -0
  117. package/types/display/text_layer.d.ts +83 -0
  118. package/types/display/transport_stream.d.ts +57 -0
  119. package/types/display/webgl.d.ts +20 -0
  120. package/types/display/worker_options.d.ts +27 -0
  121. package/types/display/xml_parser.d.ts +35 -0
  122. package/types/pdf.d.ts +33 -0
  123. package/types/shared/compatibility.d.ts +1 -0
  124. package/types/shared/is_node.d.ts +1 -0
  125. package/types/shared/message_handler.d.ts +62 -0
  126. package/types/shared/util.d.ts +421 -0
  127. package/web/images/shadow.png +0 -0
  128. package/web/pdf_viewer.css +8 -5
  129. package/web/pdf_viewer.js +109 -33
  130. package/web/pdf_viewer.js.map +1 -1
  131. package/webpack.js +1 -9
  132. package/es5/web/images/texture.png +0 -0
  133. package/web/images/texture.png +0 -0
@@ -41,12 +41,16 @@ var _operator_list = require("./operator_list.js");
41
41
 
42
42
  var _stream = require("./stream.js");
43
43
 
44
+ var _writer = require("./writer.js");
45
+
44
46
  class AnnotationFactory {
45
47
  static create(xref, ref, pdfManager, idFactory) {
46
- return pdfManager.ensure(this, "_create", [xref, ref, pdfManager, idFactory]);
48
+ return pdfManager.ensureCatalog("acroForm").then(acroForm => {
49
+ return pdfManager.ensure(this, "_create", [xref, ref, pdfManager, idFactory, acroForm]);
50
+ });
47
51
  }
48
52
 
49
- static _create(xref, ref, pdfManager, idFactory) {
53
+ static _create(xref, ref, pdfManager, idFactory, acroForm) {
50
54
  const dict = xref.fetchIfRef(ref);
51
55
 
52
56
  if (!(0, _primitives.isDict)(dict)) {
@@ -58,10 +62,12 @@ class AnnotationFactory {
58
62
  subtype = (0, _primitives.isName)(subtype) ? subtype.name : null;
59
63
  const parameters = {
60
64
  xref,
65
+ ref,
61
66
  dict,
62
67
  subtype,
63
68
  id,
64
- pdfManager
69
+ pdfManager,
70
+ acroForm: acroForm instanceof _primitives.Dict ? acroForm : _primitives.Dict.empty
65
71
  };
66
72
 
67
73
  switch (subtype) {
@@ -384,13 +390,14 @@ class Annotation {
384
390
  });
385
391
  }
386
392
 
387
- getOperatorList(evaluator, task, renderForms) {
393
+ getOperatorList(evaluator, task, renderForms, annotationStorage) {
388
394
  if (!this.appearance) {
389
395
  return Promise.resolve(new _operator_list.OperatorList());
390
396
  }
391
397
 
398
+ const appearance = this.appearance;
392
399
  const data = this.data;
393
- const appearanceDict = this.appearance.dict;
400
+ const appearanceDict = appearance.dict;
394
401
  const resourcesPromise = this.loadResources(["ExtGState", "ColorSpace", "Pattern", "Shading", "XObject", "Font"]);
395
402
  const bbox = appearanceDict.getArray("BBox") || [0, 0, 1, 1];
396
403
  const matrix = appearanceDict.getArray("Matrix") || [1, 0, 0, 1, 0, 0];
@@ -399,18 +406,22 @@ class Annotation {
399
406
  const opList = new _operator_list.OperatorList();
400
407
  opList.addOp(_util.OPS.beginAnnotation, [data.rect, transform, matrix]);
401
408
  return evaluator.getOperatorList({
402
- stream: this.appearance,
409
+ stream: appearance,
403
410
  task,
404
411
  resources,
405
412
  operatorList: opList
406
413
  }).then(() => {
407
414
  opList.addOp(_util.OPS.endAnnotation, []);
408
- this.appearance.reset();
415
+ appearance.reset();
409
416
  return opList;
410
417
  });
411
418
  });
412
419
  }
413
420
 
421
+ async save(evaluator, task, annotationStorage) {
422
+ return null;
423
+ }
424
+
414
425
  }
415
426
 
416
427
  exports.Annotation = Annotation;
@@ -583,18 +594,20 @@ class WidgetAnnotation extends Annotation {
583
594
  super(params);
584
595
  const dict = params.dict;
585
596
  const data = this.data;
597
+ this.ref = params.ref;
586
598
  data.annotationType = _util.AnnotationType.WIDGET;
587
599
  data.fieldName = this._constructFieldName(dict);
588
- data.fieldValue = (0, _core_utils.getInheritableProperty)({
600
+ const fieldValue = (0, _core_utils.getInheritableProperty)({
589
601
  dict,
590
602
  key: "V",
591
603
  getArray: true
592
604
  });
605
+ data.fieldValue = this._decodeFormValue(fieldValue);
593
606
  data.alternativeText = (0, _util.stringToPDFString)(dict.get("TU") || "");
594
607
  data.defaultAppearance = (0, _core_utils.getInheritableProperty)({
595
608
  dict,
596
609
  key: "DA"
597
- }) || "";
610
+ }) || params.acroForm.get("DA") || "";
598
611
  const fieldType = (0, _core_utils.getInheritableProperty)({
599
612
  dict,
600
613
  key: "FT"
@@ -603,7 +616,7 @@ class WidgetAnnotation extends Annotation {
603
616
  this.fieldResources = (0, _core_utils.getInheritableProperty)({
604
617
  dict,
605
618
  key: "DR"
606
- }) || _primitives.Dict.empty;
619
+ }) || params.acroForm.get("DR") || _primitives.Dict.empty;
607
620
  data.fieldFlags = (0, _core_utils.getInheritableProperty)({
608
621
  dict,
609
622
  key: "Ff"
@@ -654,16 +667,225 @@ class WidgetAnnotation extends Annotation {
654
667
  return fieldName.join(".");
655
668
  }
656
669
 
670
+ _decodeFormValue(formValue) {
671
+ if (Array.isArray(formValue)) {
672
+ return formValue.filter(item => (0, _util.isString)(item)).map(item => (0, _util.stringToPDFString)(item));
673
+ } else if ((0, _primitives.isName)(formValue)) {
674
+ return (0, _util.stringToPDFString)(formValue.name);
675
+ } else if ((0, _util.isString)(formValue)) {
676
+ return (0, _util.stringToPDFString)(formValue);
677
+ }
678
+
679
+ return null;
680
+ }
681
+
657
682
  hasFieldFlag(flag) {
658
683
  return !!(this.data.fieldFlags & flag);
659
684
  }
660
685
 
661
- getOperatorList(evaluator, task, renderForms) {
686
+ getOperatorList(evaluator, task, renderForms, annotationStorage) {
662
687
  if (renderForms) {
663
688
  return Promise.resolve(new _operator_list.OperatorList());
664
689
  }
665
690
 
666
- return super.getOperatorList(evaluator, task, renderForms);
691
+ if (!this._hasText) {
692
+ return super.getOperatorList(evaluator, task, renderForms, annotationStorage);
693
+ }
694
+
695
+ return this._getAppearance(evaluator, task, annotationStorage).then(content => {
696
+ if (this.appearance && content === null) {
697
+ return super.getOperatorList(evaluator, task, renderForms, annotationStorage);
698
+ }
699
+
700
+ const operatorList = new _operator_list.OperatorList();
701
+
702
+ if (!this.data.defaultAppearance || content === null) {
703
+ return operatorList;
704
+ }
705
+
706
+ const matrix = [1, 0, 0, 1, 0, 0];
707
+ const bbox = [0, 0, this.data.rect[2] - this.data.rect[0], this.data.rect[3] - this.data.rect[1]];
708
+ const transform = getTransformMatrix(this.data.rect, bbox, matrix);
709
+ operatorList.addOp(_util.OPS.beginAnnotation, [this.data.rect, transform, matrix]);
710
+ const stream = new _stream.StringStream(content);
711
+ return evaluator.getOperatorList({
712
+ stream,
713
+ task,
714
+ resources: this.fieldResources,
715
+ operatorList
716
+ }).then(function () {
717
+ operatorList.addOp(_util.OPS.endAnnotation, []);
718
+ return operatorList;
719
+ });
720
+ });
721
+ }
722
+
723
+ async save(evaluator, task, annotationStorage) {
724
+ if (this.data.fieldValue === annotationStorage[this.data.id]) {
725
+ return null;
726
+ }
727
+
728
+ let appearance = await this._getAppearance(evaluator, task, annotationStorage);
729
+
730
+ if (appearance === null) {
731
+ return null;
732
+ }
733
+
734
+ const dict = evaluator.xref.fetchIfRef(this.ref);
735
+
736
+ if (!(0, _primitives.isDict)(dict)) {
737
+ return null;
738
+ }
739
+
740
+ const bbox = [0, 0, this.data.rect[2] - this.data.rect[0], this.data.rect[3] - this.data.rect[1]];
741
+ const newRef = evaluator.xref.getNewRef();
742
+ const AP = new _primitives.Dict(evaluator.xref);
743
+ AP.set("N", newRef);
744
+ const value = annotationStorage[this.data.id];
745
+ const encrypt = evaluator.xref.encrypt;
746
+ let originalTransform = null;
747
+ let newTransform = null;
748
+
749
+ if (encrypt) {
750
+ originalTransform = encrypt.createCipherTransform(this.ref.num, this.ref.gen);
751
+ newTransform = encrypt.createCipherTransform(newRef.num, newRef.gen);
752
+ appearance = newTransform.encryptString(appearance);
753
+ }
754
+
755
+ dict.set("V", value);
756
+ dict.set("AP", AP);
757
+ dict.set("M", `D:${(0, _util.getModificationDate)()}`);
758
+ const appearanceDict = new _primitives.Dict(evaluator.xref);
759
+ appearanceDict.set("Length", appearance.length);
760
+ appearanceDict.set("Subtype", _primitives.Name.get("Form"));
761
+ appearanceDict.set("Resources", this.fieldResources);
762
+ appearanceDict.set("BBox", bbox);
763
+ const bufferOriginal = [`${this.ref.num} ${this.ref.gen} obj\n`];
764
+ (0, _writer.writeDict)(dict, bufferOriginal, originalTransform);
765
+ bufferOriginal.push("\nendobj\n");
766
+ const bufferNew = [`${newRef.num} ${newRef.gen} obj\n`];
767
+ (0, _writer.writeDict)(appearanceDict, bufferNew, newTransform);
768
+ bufferNew.push(" stream\n");
769
+ bufferNew.push(appearance);
770
+ bufferNew.push("\nendstream\nendobj\n");
771
+ return [{
772
+ ref: this.ref,
773
+ data: bufferOriginal.join("")
774
+ }, {
775
+ ref: newRef,
776
+ data: bufferNew.join("")
777
+ }];
778
+ }
779
+
780
+ async _getAppearance(evaluator, task, annotationStorage) {
781
+ const isPassword = this.hasFieldFlag(_util.AnnotationFieldFlag.PASSWORD);
782
+
783
+ if (!annotationStorage || isPassword) {
784
+ return null;
785
+ }
786
+
787
+ const value = annotationStorage[this.data.id];
788
+
789
+ if (value === "") {
790
+ return "";
791
+ }
792
+
793
+ const defaultPadding = 2;
794
+ const hPadding = defaultPadding;
795
+ const totalHeight = this.data.rect[3] - this.data.rect[1];
796
+ const totalWidth = this.data.rect[2] - this.data.rect[0];
797
+ const fontInfo = await this._getFontData(evaluator, task);
798
+ const [font, fontName] = fontInfo;
799
+ let fontSize = fontInfo[2];
800
+ fontSize = this._computeFontSize(font, fontName, fontSize, totalHeight);
801
+ let descent = font.descent;
802
+
803
+ if (isNaN(descent)) {
804
+ descent = 0;
805
+ }
806
+
807
+ const vPadding = defaultPadding + Math.abs(descent) * fontSize;
808
+ const defaultAppearance = this.data.defaultAppearance;
809
+ const alignment = this.data.textAlignment;
810
+
811
+ if (this.data.comb) {
812
+ return this._getCombAppearance(defaultAppearance, value, totalWidth, hPadding, vPadding);
813
+ }
814
+
815
+ if (this.data.multiLine) {
816
+ return this._getMultilineAppearance(defaultAppearance, value, font, fontSize, totalWidth, totalHeight, alignment, hPadding, vPadding);
817
+ }
818
+
819
+ if (alignment === 0 || alignment > 2) {
820
+ return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 ${hPadding} ${vPadding} Tm (${(0, _util.escapeString)(value)}) Tj` + " ET Q EMC";
821
+ }
822
+
823
+ const renderedText = this._renderText(value, font, fontSize, totalWidth, alignment, hPadding, vPadding);
824
+
825
+ return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 0 0 Tm ${renderedText}` + " ET Q EMC";
826
+ }
827
+
828
+ async _getFontData(evaluator, task) {
829
+ const operatorList = new _operator_list.OperatorList();
830
+ const initialState = {
831
+ fontSize: 0,
832
+ font: null,
833
+ fontName: null,
834
+
835
+ clone() {
836
+ return this;
837
+ }
838
+
839
+ };
840
+ await evaluator.getOperatorList({
841
+ stream: new _stream.StringStream(this.data.defaultAppearance),
842
+ task,
843
+ resources: this.fieldResources,
844
+ operatorList,
845
+ initialState
846
+ });
847
+ return [initialState.font, initialState.fontName, initialState.fontSize];
848
+ }
849
+
850
+ _computeFontSize(font, fontName, fontSize, height) {
851
+ if (fontSize === null || fontSize === 0) {
852
+ const em = font.charsToGlyphs("M", true)[0].width / 1000;
853
+ const capHeight = 0.7 * em;
854
+ fontSize = Math.max(1, Math.floor(height / (1.5 * capHeight)));
855
+ let fontRegex = new RegExp(`/${fontName}\\s+[0-9\.]+\\s+Tf`);
856
+
857
+ if (this.data.defaultAppearance.search(fontRegex) === -1) {
858
+ fontRegex = new RegExp(`/${fontName}\\s+Tf`);
859
+ }
860
+
861
+ this.data.defaultAppearance = this.data.defaultAppearance.replace(fontRegex, `/${fontName} ${fontSize} Tf`);
862
+ }
863
+
864
+ return fontSize;
865
+ }
866
+
867
+ _renderText(text, font, fontSize, totalWidth, alignment, hPadding, vPadding) {
868
+ const glyphs = font.charsToGlyphs(text);
869
+ const scale = fontSize / 1000;
870
+ let width = 0;
871
+
872
+ for (const glyph of glyphs) {
873
+ width += glyph.width * scale;
874
+ }
875
+
876
+ let shift;
877
+
878
+ if (alignment === 1) {
879
+ shift = (totalWidth - width) / 2;
880
+ } else if (alignment === 2) {
881
+ shift = totalWidth - width - hPadding;
882
+ } else {
883
+ shift = hPadding;
884
+ }
885
+
886
+ shift = shift.toFixed(2);
887
+ vPadding = vPadding.toFixed(2);
888
+ return `${shift} ${vPadding} Td (${(0, _util.escapeString)(text)}) Tj`;
667
889
  }
668
890
 
669
891
  }
@@ -671,8 +893,13 @@ class WidgetAnnotation extends Annotation {
671
893
  class TextWidgetAnnotation extends WidgetAnnotation {
672
894
  constructor(params) {
673
895
  super(params);
896
+ this._hasText = true;
674
897
  const dict = params.dict;
675
- this.data.fieldValue = (0, _util.stringToPDFString)(this.data.fieldValue || "");
898
+
899
+ if (!(0, _util.isString)(this.data.fieldValue)) {
900
+ this.data.fieldValue = "";
901
+ }
902
+
676
903
  let alignment = (0, _core_utils.getInheritableProperty)({
677
904
  dict,
678
905
  key: "Q"
@@ -697,26 +924,86 @@ class TextWidgetAnnotation extends WidgetAnnotation {
697
924
  this.data.comb = this.hasFieldFlag(_util.AnnotationFieldFlag.COMB) && !this.hasFieldFlag(_util.AnnotationFieldFlag.MULTILINE) && !this.hasFieldFlag(_util.AnnotationFieldFlag.PASSWORD) && !this.hasFieldFlag(_util.AnnotationFieldFlag.FILESELECT) && this.data.maxLen !== null;
698
925
  }
699
926
 
700
- getOperatorList(evaluator, task, renderForms) {
701
- if (renderForms || this.appearance) {
702
- return super.getOperatorList(evaluator, task, renderForms);
927
+ _getCombAppearance(defaultAppearance, text, width, hPadding, vPadding) {
928
+ const combWidth = (width / this.data.maxLen).toFixed(2);
929
+ const buf = [];
930
+
931
+ for (const character of text) {
932
+ buf.push(`(${(0, _util.escapeString)(character)}) Tj`);
933
+ }
934
+
935
+ const renderedComb = buf.join(` ${combWidth} 0 Td `);
936
+ return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 ${hPadding} ${vPadding} Tm ${renderedComb}` + " ET Q EMC";
937
+ }
938
+
939
+ _getMultilineAppearance(defaultAppearance, text, font, fontSize, width, height, alignment, hPadding, vPadding) {
940
+ const lines = text.split(/\r\n|\r|\n/);
941
+ const buf = [];
942
+ const totalWidth = width - 2 * hPadding;
943
+
944
+ for (const line of lines) {
945
+ const chunks = this._splitLine(line, font, fontSize, totalWidth);
946
+
947
+ for (const chunk of chunks) {
948
+ const padding = buf.length === 0 ? hPadding : 0;
949
+ buf.push(this._renderText(chunk, font, fontSize, width, alignment, padding, -fontSize));
950
+ }
703
951
  }
704
952
 
705
- const operatorList = new _operator_list.OperatorList();
953
+ const renderedText = buf.join("\n");
954
+ return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 0 ${height} Tm ${renderedText}` + " ET Q EMC";
955
+ }
706
956
 
707
- if (!this.data.defaultAppearance) {
708
- return Promise.resolve(operatorList);
957
+ _splitLine(line, font, fontSize, width) {
958
+ if (line.length <= 1) {
959
+ return [line];
709
960
  }
710
961
 
711
- const stream = new _stream.Stream((0, _util.stringToBytes)(this.data.defaultAppearance));
712
- return evaluator.getOperatorList({
713
- stream,
714
- task,
715
- resources: this.fieldResources,
716
- operatorList
717
- }).then(function () {
718
- return operatorList;
719
- });
962
+ const scale = fontSize / 1000;
963
+ const whitespace = font.charsToGlyphs(" ", true)[0].width * scale;
964
+ const chunks = [];
965
+ let lastSpacePos = -1,
966
+ startChunk = 0,
967
+ currentWidth = 0;
968
+
969
+ for (let i = 0, ii = line.length; i < ii; i++) {
970
+ const character = line.charAt(i);
971
+
972
+ if (character === " ") {
973
+ if (currentWidth + whitespace > width) {
974
+ chunks.push(line.substring(startChunk, i));
975
+ startChunk = i;
976
+ currentWidth = whitespace;
977
+ lastSpacePos = -1;
978
+ } else {
979
+ currentWidth += whitespace;
980
+ lastSpacePos = i;
981
+ }
982
+ } else {
983
+ const charWidth = font.charsToGlyphs(character, false)[0].width * scale;
984
+
985
+ if (currentWidth + charWidth > width) {
986
+ if (lastSpacePos !== -1) {
987
+ chunks.push(line.substring(startChunk, lastSpacePos + 1));
988
+ startChunk = i = lastSpacePos + 1;
989
+ lastSpacePos = -1;
990
+ currentWidth = 0;
991
+ } else {
992
+ chunks.push(line.substring(startChunk, i));
993
+ startChunk = i;
994
+ currentWidth = charWidth;
995
+ }
996
+ } else {
997
+ currentWidth += charWidth;
998
+ }
999
+ }
1000
+ }
1001
+
1002
+ if (startChunk < line.length) {
1003
+ chunks.push(line.substring(startChunk, line.length));
1004
+ }
1005
+
1006
+ return chunks;
720
1007
  }
721
1008
 
722
1009
  }
@@ -724,6 +1011,8 @@ class TextWidgetAnnotation extends WidgetAnnotation {
724
1011
  class ButtonWidgetAnnotation extends WidgetAnnotation {
725
1012
  constructor(params) {
726
1013
  super(params);
1014
+ this.checkedAppearance = null;
1015
+ this.uncheckedAppearance = null;
727
1016
  this.data.checkBox = !this.hasFieldFlag(_util.AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
728
1017
  this.data.radioButton = this.hasFieldFlag(_util.AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
729
1018
  this.data.pushButton = this.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
@@ -739,31 +1028,171 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
739
1028
  }
740
1029
  }
741
1030
 
742
- _processCheckBox(params) {
743
- if ((0, _primitives.isName)(this.data.fieldValue)) {
744
- this.data.fieldValue = this.data.fieldValue.name;
1031
+ getOperatorList(evaluator, task, renderForms, annotationStorage) {
1032
+ if (this.data.pushButton) {
1033
+ return super.getOperatorList(evaluator, task, false, annotationStorage);
1034
+ }
1035
+
1036
+ if (annotationStorage) {
1037
+ const value = annotationStorage[this.data.id] || false;
1038
+ let appearance;
1039
+
1040
+ if (value) {
1041
+ appearance = this.checkedAppearance;
1042
+ } else {
1043
+ appearance = this.uncheckedAppearance;
1044
+ }
1045
+
1046
+ if (appearance) {
1047
+ const savedAppearance = this.appearance;
1048
+ this.appearance = appearance;
1049
+ const operatorList = super.getOperatorList(evaluator, task, renderForms, annotationStorage);
1050
+ this.appearance = savedAppearance;
1051
+ return operatorList;
1052
+ }
1053
+
1054
+ return Promise.resolve(new _operator_list.OperatorList());
745
1055
  }
746
1056
 
1057
+ return super.getOperatorList(evaluator, task, renderForms, annotationStorage);
1058
+ }
1059
+
1060
+ async save(evaluator, task, annotationStorage) {
1061
+ if (this.data.checkBox) {
1062
+ return this._saveCheckbox(evaluator, task, annotationStorage);
1063
+ }
1064
+
1065
+ if (this.data.radioButton) {
1066
+ return this._saveRadioButton(evaluator, task, annotationStorage);
1067
+ }
1068
+
1069
+ return super.save(evaluator, task, annotationStorage);
1070
+ }
1071
+
1072
+ async _saveCheckbox(evaluator, task, annotationStorage) {
1073
+ const defaultValue = this.data.fieldValue && this.data.fieldValue !== "Off";
1074
+ const value = annotationStorage[this.data.id];
1075
+
1076
+ if (defaultValue === value) {
1077
+ return null;
1078
+ }
1079
+
1080
+ const dict = evaluator.xref.fetchIfRef(this.ref);
1081
+
1082
+ if (!(0, _primitives.isDict)(dict)) {
1083
+ return null;
1084
+ }
1085
+
1086
+ const name = _primitives.Name.get(value ? this.data.exportValue : "Off");
1087
+
1088
+ dict.set("V", name);
1089
+ dict.set("AS", name);
1090
+ dict.set("M", `D:${(0, _util.getModificationDate)()}`);
1091
+ const encrypt = evaluator.xref.encrypt;
1092
+ let originalTransform = null;
1093
+
1094
+ if (encrypt) {
1095
+ originalTransform = encrypt.createCipherTransform(this.ref.num, this.ref.gen);
1096
+ }
1097
+
1098
+ const buffer = [`${this.ref.num} ${this.ref.gen} obj\n`];
1099
+ (0, _writer.writeDict)(dict, buffer, originalTransform);
1100
+ buffer.push("\nendobj\n");
1101
+ return [{
1102
+ ref: this.ref,
1103
+ data: buffer.join("")
1104
+ }];
1105
+ }
1106
+
1107
+ async _saveRadioButton(evaluator, task, annotationStorage) {
1108
+ const defaultValue = this.data.fieldValue === this.data.buttonValue;
1109
+ const value = annotationStorage[this.data.id];
1110
+
1111
+ if (defaultValue === value) {
1112
+ return null;
1113
+ }
1114
+
1115
+ const dict = evaluator.xref.fetchIfRef(this.ref);
1116
+
1117
+ if (!(0, _primitives.isDict)(dict)) {
1118
+ return null;
1119
+ }
1120
+
1121
+ const name = _primitives.Name.get(value ? this.data.buttonValue : "Off");
1122
+
1123
+ let parentBuffer = null;
1124
+ const encrypt = evaluator.xref.encrypt;
1125
+
1126
+ if (value) {
1127
+ if ((0, _primitives.isRef)(this.parent)) {
1128
+ const parent = evaluator.xref.fetch(this.parent);
1129
+ let parentTransform = null;
1130
+
1131
+ if (encrypt) {
1132
+ parentTransform = encrypt.createCipherTransform(this.parent.num, this.parent.gen);
1133
+ }
1134
+
1135
+ parent.set("V", name);
1136
+ parentBuffer = [`${this.parent.num} ${this.parent.gen} obj\n`];
1137
+ (0, _writer.writeDict)(parent, parentBuffer, parentTransform);
1138
+ parentBuffer.push("\nendobj\n");
1139
+ } else if ((0, _primitives.isDict)(this.parent)) {
1140
+ this.parent.set("V", name);
1141
+ }
1142
+ }
1143
+
1144
+ dict.set("AS", name);
1145
+ dict.set("M", `D:${(0, _util.getModificationDate)()}`);
1146
+ let originalTransform = null;
1147
+
1148
+ if (encrypt) {
1149
+ originalTransform = encrypt.createCipherTransform(this.ref.num, this.ref.gen);
1150
+ }
1151
+
1152
+ const buffer = [`${this.ref.num} ${this.ref.gen} obj\n`];
1153
+ (0, _writer.writeDict)(dict, buffer, originalTransform);
1154
+ buffer.push("\nendobj\n");
1155
+ const newRefs = [{
1156
+ ref: this.ref,
1157
+ data: buffer.join("")
1158
+ }];
1159
+
1160
+ if (parentBuffer !== null) {
1161
+ newRefs.push({
1162
+ ref: this.parent,
1163
+ data: parentBuffer.join("")
1164
+ });
1165
+ }
1166
+
1167
+ return newRefs;
1168
+ }
1169
+
1170
+ _processCheckBox(params) {
747
1171
  const customAppearance = params.dict.get("AP");
748
1172
 
749
1173
  if (!(0, _primitives.isDict)(customAppearance)) {
750
1174
  return;
751
1175
  }
752
1176
 
753
- const exportValueOptionsDict = customAppearance.get("D");
1177
+ const normalAppearance = customAppearance.get("N");
754
1178
 
755
- if (!(0, _primitives.isDict)(exportValueOptionsDict)) {
1179
+ if (!(0, _primitives.isDict)(normalAppearance)) {
756
1180
  return;
757
1181
  }
758
1182
 
759
- const exportValues = exportValueOptionsDict.getKeys();
760
- const hasCorrectOptionCount = exportValues.length === 2;
1183
+ const exportValues = normalAppearance.getKeys();
761
1184
 
762
- if (!hasCorrectOptionCount) {
1185
+ if (!exportValues.includes("Off")) {
1186
+ exportValues.push("Off");
1187
+ }
1188
+
1189
+ if (exportValues.length !== 2) {
763
1190
  return;
764
1191
  }
765
1192
 
766
1193
  this.data.exportValue = exportValues[0] === "Off" ? exportValues[1] : exportValues[0];
1194
+ this.checkedAppearance = normalAppearance.get(this.data.exportValue);
1195
+ this.uncheckedAppearance = normalAppearance.get("Off") || null;
767
1196
  }
768
1197
 
769
1198
  _processRadioButton(params) {
@@ -774,7 +1203,8 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
774
1203
  const fieldParentValue = fieldParent.get("V");
775
1204
 
776
1205
  if ((0, _primitives.isName)(fieldParentValue)) {
777
- this.data.fieldValue = fieldParentValue.name;
1206
+ this.parent = params.dict.getRaw("Parent");
1207
+ this.data.fieldValue = this._decodeFormValue(fieldParentValue);
778
1208
  }
779
1209
  }
780
1210
 
@@ -784,18 +1214,21 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
784
1214
  return;
785
1215
  }
786
1216
 
787
- const normalAppearanceState = appearanceStates.get("N");
1217
+ const normalAppearance = appearanceStates.get("N");
788
1218
 
789
- if (!(0, _primitives.isDict)(normalAppearanceState)) {
1219
+ if (!(0, _primitives.isDict)(normalAppearance)) {
790
1220
  return;
791
1221
  }
792
1222
 
793
- for (const key of normalAppearanceState.getKeys()) {
1223
+ for (const key of normalAppearance.getKeys()) {
794
1224
  if (key !== "Off") {
795
1225
  this.data.buttonValue = key;
796
1226
  break;
797
1227
  }
798
1228
  }
1229
+
1230
+ this.checkedAppearance = normalAppearance.get(this.data.buttonValue);
1231
+ this.uncheckedAppearance = normalAppearance.get("Off") || null;
799
1232
  }
800
1233
 
801
1234
  _processPushButton(params) {
@@ -829,18 +1262,21 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation {
829
1262
  const option = xref.fetchIfRef(options[i]);
830
1263
  const isOptionArray = Array.isArray(option);
831
1264
  this.data.options[i] = {
832
- exportValue: isOptionArray ? xref.fetchIfRef(option[0]) : option,
833
- displayValue: (0, _util.stringToPDFString)(isOptionArray ? xref.fetchIfRef(option[1]) : option)
1265
+ exportValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[0]) : option),
1266
+ displayValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[1]) : option)
834
1267
  };
835
1268
  }
836
1269
  }
837
1270
 
838
- if (!Array.isArray(this.data.fieldValue)) {
1271
+ if ((0, _util.isString)(this.data.fieldValue)) {
839
1272
  this.data.fieldValue = [this.data.fieldValue];
1273
+ } else if (!this.data.fieldValue) {
1274
+ this.data.fieldValue = [];
840
1275
  }
841
1276
 
842
1277
  this.data.combo = this.hasFieldFlag(_util.AnnotationFieldFlag.COMBO);
843
1278
  this.data.multiSelect = this.hasFieldFlag(_util.AnnotationFieldFlag.MULTISELECT);
1279
+ this._hasText = true;
844
1280
  }
845
1281
 
846
1282
  }