Преглед на файлове

PDF.js version 3.2.146 - See https://github.com/mozilla/pdf.js/releases/tag/v3.2.146

pdfjsbot преди 2 години
родител
ревизия
5f07d5a415
променени са 100 файла, в които са добавени 4205 реда и са изтрити 3599 реда
  1. 681 178
      build/pdf.js
  2. 0 0
      build/pdf.js.map
  3. 0 0
      build/pdf.min.js
  4. 2 2
      build/pdf.sandbox.js
  5. 0 0
      build/pdf.sandbox.js.map
  6. 0 0
      build/pdf.sandbox.min.js
  7. 83 56
      build/pdf.worker.js
  8. 0 0
      build/pdf.worker.js.map
  9. 0 0
      build/pdf.worker.min.js
  10. 14 2
      image_decoders/pdf.image_decoders.js
  11. 0 0
      image_decoders/pdf.image_decoders.js.map
  12. 0 0
      image_decoders/pdf.image_decoders.min.js
  13. 746 199
      legacy/build/pdf.js
  14. 0 0
      legacy/build/pdf.js.map
  15. 0 0
      legacy/build/pdf.min.js
  16. 2 2
      legacy/build/pdf.sandbox.js
  17. 0 0
      legacy/build/pdf.sandbox.js.map
  18. 0 0
      legacy/build/pdf.sandbox.min.js
  19. 90 60
      legacy/build/pdf.worker.js
  20. 0 0
      legacy/build/pdf.worker.js.map
  21. 0 0
      legacy/build/pdf.worker.min.js
  22. 14 2
      legacy/image_decoders/pdf.image_decoders.js
  23. 0 0
      legacy/image_decoders/pdf.image_decoders.js.map
  24. 0 0
      legacy/image_decoders/pdf.image_decoders.min.js
  25. 6 0
      legacy/web/images/annotation-paperclip.svg
  26. 7 0
      legacy/web/images/annotation-pushpin.svg
  27. 18 1
      legacy/web/pdf_viewer.css
  28. 692 1220
      legacy/web/pdf_viewer.js
  29. 0 0
      legacy/web/pdf_viewer.js.map
  30. 15 2
      lib/core/annotation.js
  31. 9 1
      lib/core/cff_parser.js
  32. 9 12
      lib/core/document.js
  33. 1 1
      lib/core/worker.js
  34. 35 38
      lib/core/xref.js
  35. 117 102
      lib/display/annotation_layer.js
  36. 33 26
      lib/display/api.js
  37. 2 4
      lib/display/canvas.js
  38. 41 5
      lib/display/display_utils.js
  39. 31 50
      lib/display/editor/annotation_editor_layer.js
  40. 67 24
      lib/display/editor/editor.js
  41. 35 17
      lib/display/editor/freetext.js
  42. 52 29
      lib/display/editor/ink.js
  43. 51 9
      lib/display/editor/tools.js
  44. 1 1
      lib/display/fetch_stream.js
  45. 4 6
      lib/display/font_loader.js
  46. 1 1
      lib/display/network.js
  47. 1 1
      lib/display/node_stream.js
  48. 160 107
      lib/display/text_layer.js
  49. 27 3
      lib/pdf.js
  50. 2 2
      lib/pdf.sandbox.js
  51. 2 2
      lib/pdf.worker.js
  52. 12 0
      lib/shared/util.js
  53. 1 0
      lib/test/unit/api_spec.js
  54. 20 0
      lib/test/unit/pdf_find_controller_spec.js
  55. 11 3
      lib/test/unit/scripting_spec.js
  56. 1 1
      lib/test/unit/testreporter.js
  57. 3 3
      lib/test/unit/text_layer_spec.js
  58. 13 18
      lib/web/annotation_editor_layer_builder.js
  59. 37 27
      lib/web/annotation_layer_builder.js
  60. 167 176
      lib/web/app.js
  61. 4 0
      lib/web/app_options.js
  62. 1 1
      lib/web/chromecom.js
  63. 1 1
      lib/web/debugger.js
  64. 0 132
      lib/web/default_factory.js
  65. 1 1
      lib/web/firefoxcom.js
  66. 1 1
      lib/web/genericcom.js
  67. 1 54
      lib/web/interfaces.js
  68. 2 1
      lib/web/pdf_find_controller.js
  69. 277 198
      lib/web/pdf_page_view.js
  70. 7 26
      lib/web/pdf_scripting_manager.js
  71. 27 27
      lib/web/pdf_viewer.component.js
  72. 117 165
      lib/web/pdf_viewer.js
  73. 1 0
      lib/web/preferences.js
  74. 14 10
      lib/web/struct_tree_layer_builder.js
  75. 4 3
      lib/web/text_highlighter.js
  76. 71 39
      lib/web/text_layer_builder.js
  77. 1 2
      lib/web/ui_utils.js
  78. 82 0
      lib/web/viewer-geckoview.js
  79. 24 28
      lib/web/xfa_layer_builder.js
  80. 2 2
      package.json
  81. 14 14
      types/src/display/annotation_layer.d.ts
  82. 14 5
      types/src/display/api.d.ts
  83. 2 2
      types/src/display/canvas.d.ts
  84. 14 1
      types/src/display/display_utils.d.ts
  85. 13 24
      types/src/display/editor/annotation_editor_layer.d.ts
  86. 24 3
      types/src/display/editor/editor.d.ts
  87. 2 2
      types/src/display/editor/freetext.d.ts
  88. 3 2
      types/src/display/editor/ink.d.ts
  89. 20 2
      types/src/display/editor/tools.d.ts
  90. 2 2
      types/src/display/fetch_stream.d.ts
  91. 85 32
      types/src/display/text_layer.d.ts
  92. 6 1
      types/src/pdf.d.ts
  93. 1 0
      types/src/shared/util.d.ts
  94. 13 22
      types/web/annotation_editor_layer_builder.d.ts
  95. 3 6
      types/web/annotation_layer_builder.d.ts
  96. 0 174
      types/web/default_factory.d.ts
  97. 0 172
      types/web/interfaces.d.ts
  98. 0 4
      types/web/l10n_utils.d.ts
  99. 1 1
      types/web/pdf_link_service.d.ts
  100. 34 46
      types/web/pdf_page_view.d.ts

Файловите разлики са ограничени, защото са твърде много
+ 681 - 178
build/pdf.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
build/pdf.js.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
build/pdf.min.js


Файловите разлики са ограничени, защото са твърде много
+ 2 - 2
build/pdf.sandbox.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
build/pdf.sandbox.js.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
build/pdf.sandbox.min.js


+ 83 - 56
build/pdf.worker.js

@@ -101,7 +101,7 @@ class WorkerMessageHandler {
       docId,
       apiVersion
     } = docParams;
-    const workerVersion = '3.1.81';
+    const workerVersion = '3.2.146';
     if (apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
     }
@@ -1251,6 +1251,18 @@ class FeatureTest {
   static get isOffscreenCanvasSupported() {
     return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined");
   }
+  static get platform() {
+    if (typeof navigator === "undefined") {
+      return shadow(this, "platform", {
+        isWin: false,
+        isMac: false
+      });
+    }
+    return shadow(this, "platform", {
+      isWin: navigator.platform.includes("Win"),
+      isMac: navigator.platform.includes("Mac")
+    });
+  }
 }
 exports.FeatureTest = FeatureTest;
 const hexNumbers = [...Array(256).keys()].map(n => n.toString(16).padStart(2, "0"));
@@ -3108,12 +3120,13 @@ class Page {
     if (this.xfaData) {
       return this.xfaData.bbox;
     }
-    const box = this._getInheritableProperty(name, true);
+    let box = this._getInheritableProperty(name, true);
     if (Array.isArray(box) && box.length === 4) {
-      if (box[2] - box[0] !== 0 && box[3] - box[1] !== 0) {
+      box = _util.Util.normalizeRect(box);
+      if (box[2] - box[0] > 0 && box[3] - box[1] > 0) {
         return box;
       }
-      (0, _util.warn)(`Empty /${name} entry.`);
+      (0, _util.warn)(`Empty, or invalid, /${name} entry.`);
     }
     return null;
   }
@@ -3135,18 +3148,14 @@ class Page {
       cropBox,
       mediaBox
     } = this;
-    let view;
-    if (cropBox === mediaBox || (0, _util.isArrayEqual)(cropBox, mediaBox)) {
-      view = mediaBox;
-    } else {
+    if (cropBox !== mediaBox && !(0, _util.isArrayEqual)(cropBox, mediaBox)) {
       const box = _util.Util.intersect(cropBox, mediaBox);
-      if (box && box[2] - box[0] !== 0 && box[3] - box[1] !== 0) {
-        view = box;
-      } else {
-        (0, _util.warn)("Empty /CropBox and /MediaBox intersection.");
+      if (box && box[2] - box[0] > 0 && box[3] - box[1] > 0) {
+        return (0, _util.shadow)(this, "view", box);
       }
+      (0, _util.warn)("Empty /CropBox and /MediaBox intersection.");
     }
-    return (0, _util.shadow)(this, "view", view || mediaBox);
+    return (0, _util.shadow)(this, "view", mediaBox);
   }
   get rotate() {
     let rotate = this._getInheritableProperty("Rotate") || 0;
@@ -5514,7 +5523,14 @@ class WidgetAnnotation extends Annotation {
       value = value[0];
     }
     (0, _util.assert)(typeof value === "string", "Expected `value` to be a string.");
-    value = value.trim();
+    if (!this.data.combo) {
+      value = value.trim();
+    } else {
+      const option = this.data.options.find(({
+        exportValue
+      }) => value === exportValue) || this.data.options[0];
+      value = option && option.displayValue || "";
+    }
     if (value === "") {
       return `/Tx BMC q ${colors}Q EMC`;
     }
@@ -7124,9 +7140,15 @@ class StampAnnotation extends MarkupAnnotation {
 class FileAttachmentAnnotation extends MarkupAnnotation {
   constructor(params) {
     super(params);
-    const file = new _file_spec.FileSpec(params.dict.get("FS"), params.xref);
+    const {
+      dict,
+      xref
+    } = params;
+    const file = new _file_spec.FileSpec(dict.get("FS"), xref);
     this.data.annotationType = _util.AnnotationType.FILEATTACHMENT;
     this.data.file = file.serializable;
+    const name = dict.get("Name");
+    this.data.name = name instanceof _primitives.Name ? (0, _util.stringToPDFString)(name.name) : "PushPin";
   }
 }
 
@@ -23456,7 +23478,7 @@ class CFFParser {
     }
     let stackSize = state.stackSize;
     const stack = state.stack;
-    const length = data.length;
+    let length = data.length;
     for (let j = 0; j < length;) {
       const value = data[j++];
       let validationCommand = null;
@@ -23537,6 +23559,11 @@ class CFFParser {
       } else if (value === 0 && j === data.length) {
         data[j - 1] = 14;
         validationCommand = CharstringValidationData[14];
+      } else if (value === 9) {
+        data.copyWithin(j - 1, j, -1);
+        j -= 1;
+        length -= 1;
+        continue;
       } else {
         validationCommand = CharstringValidationData[value];
       }
@@ -23589,6 +23616,9 @@ class CFFParser {
         }
       }
     }
+    if (length < data.length) {
+      data.fill(14, length);
+    }
     state.stackSize = stackSize;
     return true;
   }
@@ -63432,19 +63462,18 @@ class XRef {
       }
       return skipped;
     }
+    const gEndobjRegExp = /\b(endobj|\d+\s+\d+\s+obj|xref|trailer)\b/g;
+    const gStartxrefRegExp = /\b(startxref|\d+\s+\d+\s+obj)\b/g;
     const objRegExp = /^(\d+)\s+(\d+)\s+obj\b/;
-    const endobjRegExp = /\bendobj[\b\s]$/;
-    const nestedObjRegExp = /\s+(\d+\s+\d+\s+obj[\b\s<])$/;
-    const CHECK_CONTENT_LENGTH = 25;
     const trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]);
     const startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]);
-    const objBytes = new Uint8Array([111, 98, 106]);
     const xrefBytes = new Uint8Array([47, 88, 82, 101, 102]);
     this.entries.length = 0;
     this._cacheMap.clear();
     const stream = this.stream;
     stream.pos = 0;
     const buffer = stream.getBytes(),
+      bufferStr = (0, _util.bytesToString)(buffer),
       length = buffer.length;
     let position = stream.start;
     const trailers = [],
@@ -63474,8 +63503,8 @@ class XRef {
       } else if (m = objRegExp.exec(token)) {
         const num = m[1] | 0,
           gen = m[2] | 0;
+        const startPos = position + token.length;
         let contentLength,
-          startPos = position + token.length,
           updateEntries = false;
         if (!this.entries[num]) {
           updateEntries = true;
@@ -63501,22 +63530,17 @@ class XRef {
             uncompressed: true
           };
         }
-        while (startPos < length) {
-          const endPos = startPos + skipUntil(buffer, startPos, objBytes) + 4;
+        gEndobjRegExp.lastIndex = startPos;
+        const match = gEndobjRegExp.exec(bufferStr);
+        if (match) {
+          const endPos = gEndobjRegExp.lastIndex + 1;
           contentLength = endPos - position;
-          const checkPos = Math.max(endPos - CHECK_CONTENT_LENGTH, startPos);
-          const tokenStr = (0, _util.bytesToString)(buffer.subarray(checkPos, endPos));
-          if (endobjRegExp.test(tokenStr)) {
-            break;
-          } else {
-            const objToken = nestedObjRegExp.exec(tokenStr);
-            if (objToken && objToken[1]) {
-              (0, _util.warn)('indexObjects: Found new "obj" inside of another "obj", ' + 'caused by missing "endobj" -- trying to recover.');
-              contentLength -= objToken[1].length;
-              break;
-            }
+          if (match[1] !== "endobj") {
+            (0, _util.warn)(`indexObjects: Found "${match[1]}" inside of another "obj", ` + 'caused by missing "endobj" -- trying to recover.');
+            contentLength -= match[1].length + 1;
           }
-          startPos = endPos;
+        } else {
+          contentLength = length - position;
         }
         const content = buffer.subarray(position, position + contentLength);
         const xrefTagOffset = skipUntil(content, 0, xrefBytes);
@@ -63527,17 +63551,19 @@ class XRef {
         position += contentLength;
       } else if (token.startsWith("trailer") && (token.length === 7 || /\s/.test(token[7]))) {
         trailers.push(position);
-        const contentLength = skipUntil(buffer, position, startxrefBytes);
-        if (position + contentLength >= length) {
-          const endPos = position + skipUntil(buffer, position, objBytes) + 4;
-          const checkPos = Math.max(endPos - CHECK_CONTENT_LENGTH, position);
-          const tokenStr = (0, _util.bytesToString)(buffer.subarray(checkPos, endPos));
-          const objToken = nestedObjRegExp.exec(tokenStr);
-          if (objToken && objToken[1]) {
-            (0, _util.warn)('indexObjects: Found first "obj" after "trailer", ' + 'caused by missing "startxref" -- trying to recover.');
-            position = endPos - objToken[1].length;
-            continue;
+        const startPos = position + token.length;
+        let contentLength;
+        gStartxrefRegExp.lastIndex = startPos;
+        const match = gStartxrefRegExp.exec(bufferStr);
+        if (match) {
+          const endPos = gStartxrefRegExp.lastIndex + 1;
+          contentLength = endPos - position;
+          if (match[1] !== "startxref") {
+            (0, _util.warn)(`indexObjects: Found "${match[1]}" after "trailer", ` + 'caused by missing "startxref" -- trying to recover.');
+            contentLength -= match[1].length + 1;
           }
+        } else {
+          contentLength = length - position;
         }
         position += contentLength;
       } else {
@@ -63606,8 +63632,8 @@ class XRef {
   readXRef(recoveryMode = false) {
     const stream = this.stream;
     const startXRefParsedCache = new Set();
-    try {
-      while (this.startXRefQueue.length) {
+    while (this.startXRefQueue.length) {
+      try {
         const startXRef = this.startXRefQueue[0];
         if (startXRefParsedCache.has(startXRef)) {
           (0, _util.warn)("readXRef - skipping XRef table since it was already parsed.");
@@ -63656,16 +63682,17 @@ class XRef {
         } else if (obj instanceof _primitives.Ref) {
           this.startXRefQueue.push(obj.num);
         }
-        this.startXRefQueue.shift();
-      }
-      return this.topDict;
-    } catch (e) {
-      if (e instanceof _core_utils.MissingDataException) {
-        throw e;
+      } catch (e) {
+        if (e instanceof _core_utils.MissingDataException) {
+          throw e;
+        }
+        (0, _util.info)("(while reading XRef): " + e);
       }
-      (0, _util.info)("(while reading XRef): " + e);
       this.startXRefQueue.shift();
     }
+    if (this.topDict) {
+      return this.topDict;
+    }
     if (recoveryMode) {
       return undefined;
     }
@@ -64467,8 +64494,8 @@ Object.defineProperty(exports, "WorkerMessageHandler", ({
   }
 }));
 var _worker = __w_pdfjs_require__(1);
-const pdfjsVersion = '3.1.81';
-const pdfjsBuild = '0766898d5';
+const pdfjsVersion = '3.2.146';
+const pdfjsBuild = '3fd2a3548';
 })();
 
 /******/ 	return __webpack_exports__;

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
build/pdf.worker.js.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
build/pdf.worker.min.js


+ 14 - 2
image_decoders/pdf.image_decoders.js

@@ -659,6 +659,18 @@ class FeatureTest {
   static get isOffscreenCanvasSupported() {
     return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined");
   }
+  static get platform() {
+    if (typeof navigator === "undefined") {
+      return shadow(this, "platform", {
+        isWin: false,
+        isMac: false
+      });
+    }
+    return shadow(this, "platform", {
+      isWin: navigator.platform.includes("Win"),
+      isMac: navigator.platform.includes("Mac")
+    });
+  }
 }
 exports.FeatureTest = FeatureTest;
 const hexNumbers = [...Array(256).keys()].map(n => n.toString(16).padStart(2, "0"));
@@ -7419,8 +7431,8 @@ var _util = __w_pdfjs_require__(1);
 var _jbig = __w_pdfjs_require__(2);
 var _jpg = __w_pdfjs_require__(8);
 var _jpx = __w_pdfjs_require__(9);
-const pdfjsVersion = '3.1.81';
-const pdfjsBuild = '0766898d5';
+const pdfjsVersion = '3.2.146';
+const pdfjsBuild = '3fd2a3548';
 })();
 
 /******/ 	return __webpack_exports__;

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
image_decoders/pdf.image_decoders.js.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
image_decoders/pdf.image_decoders.min.js


Файловите разлики са ограничени, защото са твърде много
+ 746 - 199
legacy/build/pdf.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
legacy/build/pdf.js.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
legacy/build/pdf.min.js


Файловите разлики са ограничени, защото са твърде много
+ 2 - 2
legacy/build/pdf.sandbox.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
legacy/build/pdf.sandbox.js.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
legacy/build/pdf.sandbox.min.js


+ 90 - 60
legacy/build/pdf.worker.js

@@ -101,7 +101,7 @@ class WorkerMessageHandler {
       docId,
       apiVersion
     } = docParams;
-    const workerVersion = '3.1.81';
+    const workerVersion = '3.2.146';
     if (apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
     }
@@ -1266,6 +1266,18 @@ class FeatureTest {
   static get isOffscreenCanvasSupported() {
     return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined");
   }
+  static get platform() {
+    if (typeof navigator === "undefined") {
+      return shadow(this, "platform", {
+        isWin: false,
+        isMac: false
+      });
+    }
+    return shadow(this, "platform", {
+      isWin: navigator.platform.includes("Win"),
+      isMac: navigator.platform.includes("Mac")
+    });
+  }
 }
 exports.FeatureTest = FeatureTest;
 const hexNumbers = [...Array(256).keys()].map(n => n.toString(16).padStart(2, "0"));
@@ -6520,12 +6532,13 @@ class Page {
     if (this.xfaData) {
       return this.xfaData.bbox;
     }
-    const box = this._getInheritableProperty(name, true);
+    let box = this._getInheritableProperty(name, true);
     if (Array.isArray(box) && box.length === 4) {
-      if (box[2] - box[0] !== 0 && box[3] - box[1] !== 0) {
+      box = _util.Util.normalizeRect(box);
+      if (box[2] - box[0] > 0 && box[3] - box[1] > 0) {
         return box;
       }
-      (0, _util.warn)(`Empty /${name} entry.`);
+      (0, _util.warn)(`Empty, or invalid, /${name} entry.`);
     }
     return null;
   }
@@ -6547,18 +6560,14 @@ class Page {
       cropBox,
       mediaBox
     } = this;
-    let view;
-    if (cropBox === mediaBox || (0, _util.isArrayEqual)(cropBox, mediaBox)) {
-      view = mediaBox;
-    } else {
+    if (cropBox !== mediaBox && !(0, _util.isArrayEqual)(cropBox, mediaBox)) {
       const box = _util.Util.intersect(cropBox, mediaBox);
-      if (box && box[2] - box[0] !== 0 && box[3] - box[1] !== 0) {
-        view = box;
-      } else {
-        (0, _util.warn)("Empty /CropBox and /MediaBox intersection.");
+      if (box && box[2] - box[0] > 0 && box[3] - box[1] > 0) {
+        return (0, _util.shadow)(this, "view", box);
       }
+      (0, _util.warn)("Empty /CropBox and /MediaBox intersection.");
     }
-    return (0, _util.shadow)(this, "view", view || mediaBox);
+    return (0, _util.shadow)(this, "view", mediaBox);
   }
   get rotate() {
     let rotate = this._getInheritableProperty("Rotate") || 0;
@@ -8950,7 +8959,17 @@ class WidgetAnnotation extends Annotation {
       value = value[0];
     }
     (0, _util.assert)(typeof value === "string", "Expected `value` to be a string.");
-    value = value.trim();
+    if (!this.data.combo) {
+      value = value.trim();
+    } else {
+      const option = this.data.options.find(_ref3 => {
+        let {
+          exportValue
+        } = _ref3;
+        return value === exportValue;
+      }) || this.data.options[0];
+      value = option && option.displayValue || "";
+    }
     if (value === "") {
       return `/Tx BMC q ${colors}Q EMC`;
     }
@@ -9960,11 +9979,11 @@ class FreeTextAnnotation extends MarkupAnnotation {
   get hasTextContent() {
     return !!this.appearance;
   }
-  static createNewDict(annotation, xref, _ref3) {
+  static createNewDict(annotation, xref, _ref4) {
     let {
       apRef,
       ap
-    } = _ref3;
+    } = _ref4;
     const {
       color,
       fontSize,
@@ -10337,11 +10356,11 @@ class InkAnnotation extends MarkupAnnotation {
       });
     }
   }
-  static createNewDict(annotation, xref, _ref4) {
+  static createNewDict(annotation, xref, _ref5) {
     let {
       apRef,
       ap
-    } = _ref4;
+    } = _ref5;
     const {
       paths,
       rect,
@@ -10563,9 +10582,15 @@ class StampAnnotation extends MarkupAnnotation {
 class FileAttachmentAnnotation extends MarkupAnnotation {
   constructor(params) {
     super(params);
-    const file = new _file_spec.FileSpec(params.dict.get("FS"), params.xref);
+    const {
+      dict,
+      xref
+    } = params;
+    const file = new _file_spec.FileSpec(dict.get("FS"), xref);
     this.data.annotationType = _util.AnnotationType.FILEATTACHMENT;
     this.data.file = file.serializable;
+    const name = dict.get("Name");
+    this.data.name = name instanceof _primitives.Name ? (0, _util.stringToPDFString)(name.name) : "PushPin";
   }
 }
 
@@ -26965,7 +26990,7 @@ class CFFParser {
     }
     let stackSize = state.stackSize;
     const stack = state.stack;
-    const length = data.length;
+    let length = data.length;
     for (let j = 0; j < length;) {
       const value = data[j++];
       let validationCommand = null;
@@ -27046,6 +27071,11 @@ class CFFParser {
       } else if (value === 0 && j === data.length) {
         data[j - 1] = 14;
         validationCommand = CharstringValidationData[14];
+      } else if (value === 9) {
+        data.copyWithin(j - 1, j, -1);
+        j -= 1;
+        length -= 1;
+        continue;
       } else {
         validationCommand = CharstringValidationData[value];
       }
@@ -27098,6 +27128,9 @@ class CFFParser {
         }
       }
     }
+    if (length < data.length) {
+      data.fill(14, length);
+    }
     state.stackSize = stackSize;
     return true;
   }
@@ -67111,19 +67144,18 @@ class XRef {
       }
       return skipped;
     }
+    const gEndobjRegExp = /\b(endobj|\d+\s+\d+\s+obj|xref|trailer)\b/g;
+    const gStartxrefRegExp = /\b(startxref|\d+\s+\d+\s+obj)\b/g;
     const objRegExp = /^(\d+)\s+(\d+)\s+obj\b/;
-    const endobjRegExp = /\bendobj[\b\s]$/;
-    const nestedObjRegExp = /\s+(\d+\s+\d+\s+obj[\b\s<])$/;
-    const CHECK_CONTENT_LENGTH = 25;
     const trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]);
     const startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]);
-    const objBytes = new Uint8Array([111, 98, 106]);
     const xrefBytes = new Uint8Array([47, 88, 82, 101, 102]);
     this.entries.length = 0;
     this._cacheMap.clear();
     const stream = this.stream;
     stream.pos = 0;
     const buffer = stream.getBytes(),
+      bufferStr = (0, _util.bytesToString)(buffer),
       length = buffer.length;
     let position = stream.start;
     const trailers = [],
@@ -67153,8 +67185,8 @@ class XRef {
       } else if (m = objRegExp.exec(token)) {
         const num = m[1] | 0,
           gen = m[2] | 0;
+        const startPos = position + token.length;
         let contentLength,
-          startPos = position + token.length,
           updateEntries = false;
         if (!this.entries[num]) {
           updateEntries = true;
@@ -67180,22 +67212,17 @@ class XRef {
             uncompressed: true
           };
         }
-        while (startPos < length) {
-          const endPos = startPos + skipUntil(buffer, startPos, objBytes) + 4;
+        gEndobjRegExp.lastIndex = startPos;
+        const match = gEndobjRegExp.exec(bufferStr);
+        if (match) {
+          const endPos = gEndobjRegExp.lastIndex + 1;
           contentLength = endPos - position;
-          const checkPos = Math.max(endPos - CHECK_CONTENT_LENGTH, startPos);
-          const tokenStr = (0, _util.bytesToString)(buffer.subarray(checkPos, endPos));
-          if (endobjRegExp.test(tokenStr)) {
-            break;
-          } else {
-            const objToken = nestedObjRegExp.exec(tokenStr);
-            if (objToken && objToken[1]) {
-              (0, _util.warn)('indexObjects: Found new "obj" inside of another "obj", ' + 'caused by missing "endobj" -- trying to recover.');
-              contentLength -= objToken[1].length;
-              break;
-            }
+          if (match[1] !== "endobj") {
+            (0, _util.warn)(`indexObjects: Found "${match[1]}" inside of another "obj", ` + 'caused by missing "endobj" -- trying to recover.');
+            contentLength -= match[1].length + 1;
           }
-          startPos = endPos;
+        } else {
+          contentLength = length - position;
         }
         const content = buffer.subarray(position, position + contentLength);
         const xrefTagOffset = skipUntil(content, 0, xrefBytes);
@@ -67206,17 +67233,19 @@ class XRef {
         position += contentLength;
       } else if (token.startsWith("trailer") && (token.length === 7 || /\s/.test(token[7]))) {
         trailers.push(position);
-        const contentLength = skipUntil(buffer, position, startxrefBytes);
-        if (position + contentLength >= length) {
-          const endPos = position + skipUntil(buffer, position, objBytes) + 4;
-          const checkPos = Math.max(endPos - CHECK_CONTENT_LENGTH, position);
-          const tokenStr = (0, _util.bytesToString)(buffer.subarray(checkPos, endPos));
-          const objToken = nestedObjRegExp.exec(tokenStr);
-          if (objToken && objToken[1]) {
-            (0, _util.warn)('indexObjects: Found first "obj" after "trailer", ' + 'caused by missing "startxref" -- trying to recover.');
-            position = endPos - objToken[1].length;
-            continue;
+        const startPos = position + token.length;
+        let contentLength;
+        gStartxrefRegExp.lastIndex = startPos;
+        const match = gStartxrefRegExp.exec(bufferStr);
+        if (match) {
+          const endPos = gStartxrefRegExp.lastIndex + 1;
+          contentLength = endPos - position;
+          if (match[1] !== "startxref") {
+            (0, _util.warn)(`indexObjects: Found "${match[1]}" after "trailer", ` + 'caused by missing "startxref" -- trying to recover.');
+            contentLength -= match[1].length + 1;
           }
+        } else {
+          contentLength = length - position;
         }
         position += contentLength;
       } else {
@@ -67286,8 +67315,8 @@ class XRef {
     let recoveryMode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
     const stream = this.stream;
     const startXRefParsedCache = new Set();
-    try {
-      while (this.startXRefQueue.length) {
+    while (this.startXRefQueue.length) {
+      try {
         const startXRef = this.startXRefQueue[0];
         if (startXRefParsedCache.has(startXRef)) {
           (0, _util.warn)("readXRef - skipping XRef table since it was already parsed.");
@@ -67336,16 +67365,17 @@ class XRef {
         } else if (obj instanceof _primitives.Ref) {
           this.startXRefQueue.push(obj.num);
         }
-        this.startXRefQueue.shift();
-      }
-      return this.topDict;
-    } catch (e) {
-      if (e instanceof _core_utils.MissingDataException) {
-        throw e;
+      } catch (e) {
+        if (e instanceof _core_utils.MissingDataException) {
+          throw e;
+        }
+        (0, _util.info)("(while reading XRef): " + e);
       }
-      (0, _util.info)("(while reading XRef): " + e);
       this.startXRefQueue.shift();
     }
+    if (this.topDict) {
+      return this.topDict;
+    }
     if (recoveryMode) {
       return undefined;
     }
@@ -68143,8 +68173,8 @@ Object.defineProperty(exports, "WorkerMessageHandler", ({
   }
 }));
 var _worker = __w_pdfjs_require__(1);
-const pdfjsVersion = '3.1.81';
-const pdfjsBuild = '0766898d5';
+const pdfjsVersion = '3.2.146';
+const pdfjsBuild = '3fd2a3548';
 })();
 
 /******/ 	return __webpack_exports__;

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
legacy/build/pdf.worker.js.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
legacy/build/pdf.worker.min.js


+ 14 - 2
legacy/image_decoders/pdf.image_decoders.js

@@ -665,6 +665,18 @@ class FeatureTest {
   static get isOffscreenCanvasSupported() {
     return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined");
   }
+  static get platform() {
+    if (typeof navigator === "undefined") {
+      return shadow(this, "platform", {
+        isWin: false,
+        isMac: false
+      });
+    }
+    return shadow(this, "platform", {
+      isWin: navigator.platform.includes("Win"),
+      isMac: navigator.platform.includes("Mac")
+    });
+  }
 }
 exports.FeatureTest = FeatureTest;
 const hexNumbers = [...Array(256).keys()].map(n => n.toString(16).padStart(2, "0"));
@@ -9105,8 +9117,8 @@ var _util = __w_pdfjs_require__(1);
 var _jbig = __w_pdfjs_require__(88);
 var _jpg = __w_pdfjs_require__(94);
 var _jpx = __w_pdfjs_require__(95);
-const pdfjsVersion = '3.1.81';
-const pdfjsBuild = '0766898d5';
+const pdfjsVersion = '3.2.146';
+const pdfjsBuild = '3fd2a3548';
 })();
 
 /******/ 	return __webpack_exports__;

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
legacy/image_decoders/pdf.image_decoders.js.map


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
legacy/image_decoders/pdf.image_decoders.min.js


+ 6 - 0
legacy/web/images/annotation-paperclip.svg

@@ -0,0 +1,6 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="40" width="40">
+  <path d="M9 3.5a1.5 1.5 0 0 0-3-.001v7.95C6 12.83 7.12 14 8.5 14s2.5-1.17 2.5-2.55V5.5a.5.5 0 0 1 1 0v6.03C11.955 13.427 10.405 15 8.5 15S5.044 13.426 5 11.53V3.5a2.5 2.5 0 0 1 5 0v7.003a1.5 1.5 0 0 1-3-.003v-5a.5.5 0 0 1 1 0v5a.5.5 0 0 0 1 0Z"/>
+</svg>

+ 7 - 0
legacy/web/images/annotation-pushpin.svg

@@ -0,0 +1,7 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="40" width="40">
+  <path d="M8.156 12.5a.99.99 0 0 0 .707-.294l.523-2.574L10.5 8.499l1.058-1.04 2.65-.601a.996.996 0 0 0 0-1.414l-3.657-3.658a.996.996 0 0 0-1.414 0l-.523 2.576L7.5 5.499 6.442 6.535l-2.65.6a.996.996 0 0 0 0 1.413l3.657 3.658a.999.999 0 0 0 .707.295z"/>
+  <path d="M9.842.996c-.386 0-.77.146-1.06.44a.5.5 0 0 0-.136.251l-.492 2.43-1.008 1.03-.953.933-2.511.566a.5.5 0 0 0-.243.133 1.505 1.505 0 0 0-.002 2.123l1.477 1.477-2.768 2.767a.5.5 0 0 0 0 .707.5.5 0 0 0 .708 0l2.767-2.767 1.475 1.474a1.494 1.494 0 0 0 2.123-.002.5.5 0 0 0 .135-.254l.492-2.427 1.008-1.024.953-.937 2.511-.57a.5.5 0 0 0 .243-.132c.586-.58.583-1.543.002-2.125l-3.659-3.656A1.501 1.501 0 0 0 9.842.996Zm.05 1.025a.394.394 0 0 1 .305.12l3.658 3.657c.18.18.141.432.002.627l-2.41.545a.5.5 0 0 0-.24.131L10.15 8.142a.5.5 0 0 0-.007.006L9.029 9.283a.5.5 0 0 0-.133.25l-.48 2.36c-.082.053-.165.109-.26.109a.492.492 0 0 1-.353-.149L4.145 8.195c-.18-.18-.141-.432-.002-.627l2.41-.545a.5.5 0 0 0 .238-.13L7.85 5.857a.5.5 0 0 0 .007-.008l1.114-1.138a.5.5 0 0 0 .133-.25l.472-2.323a.619.619 0 0 1 .317-.117Z"/>
+</svg>

+ 18 - 1
legacy/web/pdf_viewer.css

@@ -27,6 +27,8 @@
      -moz-text-size-adjust: none;
           text-size-adjust: none;
   forced-color-adjust: none;
+  transform-origin: 0 0;
+  z-index: 2;
 }
 
 .textLayer span,
@@ -140,6 +142,7 @@
   left: 0;
   pointer-events: none;
   transform-origin: 0 0;
+  z-index: 3;
 }
 
 .annotationLayer section {
@@ -765,6 +768,11 @@
   --editorInk-editing-cursor: pointer;
 }
 
+@media (-webkit-min-device-pixel-ratio: 1.1), (min-resolution: 1.1dppx) {
+  :root {
+  }
+}
+
 @media (forced-colors: active) {
   :root {
     --focus-outline: solid 3px ButtonText;
@@ -790,7 +798,7 @@
   font-size: calc(100px * var(--scale-factor));
   transform-origin: 0 0;
   cursor: auto;
-  z-index: 20000;
+  z-index: 4;
 }
 
 .annotationEditorLayer.freeTextEditing {
@@ -930,6 +938,9 @@
 
 .pdfViewer .canvasWrapper {
   overflow: hidden;
+  width: 100%;
+  height: 100%;
+  z-index: 1;
 }
 
 .pdfViewer .page {
@@ -1019,6 +1030,11 @@
   display: none;
 }
 
+.pdfViewer .page canvas[zooming] {
+  width: 100%;
+  height: 100%;
+}
+
 .pdfViewer .page .loadingIcon {
   position: absolute;
   display: block;
@@ -1027,6 +1043,7 @@
   right: 0;
   bottom: 0;
   background: url("images/loading-icon.gif") center no-repeat;
+  z-index: 5;
 }
 .pdfViewer .page .loadingIcon.notVisible {
   background: none;

Файловите разлики са ограничени, защото са твърде много
+ 692 - 1220
legacy/web/pdf_viewer.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
legacy/web/pdf_viewer.js.map


+ 15 - 2
lib/core/annotation.js

@@ -1250,7 +1250,14 @@ class WidgetAnnotation extends Annotation {
       value = value[0];
     }
     (0, _util.assert)(typeof value === "string", "Expected `value` to be a string.");
-    value = value.trim();
+    if (!this.data.combo) {
+      value = value.trim();
+    } else {
+      const option = this.data.options.find(({
+        exportValue
+      }) => value === exportValue) || this.data.options[0];
+      value = option && option.displayValue || "";
+    }
     if (value === "") {
       return `/Tx BMC q ${colors}Q EMC`;
     }
@@ -2860,8 +2867,14 @@ class StampAnnotation extends MarkupAnnotation {
 class FileAttachmentAnnotation extends MarkupAnnotation {
   constructor(params) {
     super(params);
-    const file = new _file_spec.FileSpec(params.dict.get("FS"), params.xref);
+    const {
+      dict,
+      xref
+    } = params;
+    const file = new _file_spec.FileSpec(dict.get("FS"), xref);
     this.data.annotationType = _util.AnnotationType.FILEATTACHMENT;
     this.data.file = file.serializable;
+    const name = dict.get("Name");
+    this.data.name = name instanceof _primitives.Name ? (0, _util.stringToPDFString)(name.name) : "PushPin";
   }
 }

+ 9 - 1
lib/core/cff_parser.js

@@ -457,7 +457,7 @@ class CFFParser {
     }
     let stackSize = state.stackSize;
     const stack = state.stack;
-    const length = data.length;
+    let length = data.length;
     for (let j = 0; j < length;) {
       const value = data[j++];
       let validationCommand = null;
@@ -538,6 +538,11 @@ class CFFParser {
       } else if (value === 0 && j === data.length) {
         data[j - 1] = 14;
         validationCommand = CharstringValidationData[14];
+      } else if (value === 9) {
+        data.copyWithin(j - 1, j, -1);
+        j -= 1;
+        length -= 1;
+        continue;
       } else {
         validationCommand = CharstringValidationData[value];
       }
@@ -590,6 +595,9 @@ class CFFParser {
         }
       }
     }
+    if (length < data.length) {
+      data.fill(14, length);
+    }
     state.stackSize = stackSize;
     return true;
   }

+ 9 - 12
lib/core/document.js

@@ -116,12 +116,13 @@ class Page {
     if (this.xfaData) {
       return this.xfaData.bbox;
     }
-    const box = this._getInheritableProperty(name, true);
+    let box = this._getInheritableProperty(name, true);
     if (Array.isArray(box) && box.length === 4) {
-      if (box[2] - box[0] !== 0 && box[3] - box[1] !== 0) {
+      box = _util.Util.normalizeRect(box);
+      if (box[2] - box[0] > 0 && box[3] - box[1] > 0) {
         return box;
       }
-      (0, _util.warn)(`Empty /${name} entry.`);
+      (0, _util.warn)(`Empty, or invalid, /${name} entry.`);
     }
     return null;
   }
@@ -143,18 +144,14 @@ class Page {
       cropBox,
       mediaBox
     } = this;
-    let view;
-    if (cropBox === mediaBox || (0, _util.isArrayEqual)(cropBox, mediaBox)) {
-      view = mediaBox;
-    } else {
+    if (cropBox !== mediaBox && !(0, _util.isArrayEqual)(cropBox, mediaBox)) {
       const box = _util.Util.intersect(cropBox, mediaBox);
-      if (box && box[2] - box[0] !== 0 && box[3] - box[1] !== 0) {
-        view = box;
-      } else {
-        (0, _util.warn)("Empty /CropBox and /MediaBox intersection.");
+      if (box && box[2] - box[0] > 0 && box[3] - box[1] > 0) {
+        return (0, _util.shadow)(this, "view", box);
       }
+      (0, _util.warn)("Empty /CropBox and /MediaBox intersection.");
     }
-    return (0, _util.shadow)(this, "view", view || mediaBox);
+    return (0, _util.shadow)(this, "view", mediaBox);
   }
   get rotate() {
     let rotate = this._getInheritableProperty("Rotate") || 0;

+ 1 - 1
lib/core/worker.js

@@ -83,7 +83,7 @@ class WorkerMessageHandler {
       docId,
       apiVersion
     } = docParams;
-    const workerVersion = '3.1.81';
+    const workerVersion = '3.2.146';
     if (apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
     }

+ 35 - 38
lib/core/xref.js

@@ -322,19 +322,18 @@ class XRef {
       }
       return skipped;
     }
+    const gEndobjRegExp = /\b(endobj|\d+\s+\d+\s+obj|xref|trailer)\b/g;
+    const gStartxrefRegExp = /\b(startxref|\d+\s+\d+\s+obj)\b/g;
     const objRegExp = /^(\d+)\s+(\d+)\s+obj\b/;
-    const endobjRegExp = /\bendobj[\b\s]$/;
-    const nestedObjRegExp = /\s+(\d+\s+\d+\s+obj[\b\s<])$/;
-    const CHECK_CONTENT_LENGTH = 25;
     const trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]);
     const startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]);
-    const objBytes = new Uint8Array([111, 98, 106]);
     const xrefBytes = new Uint8Array([47, 88, 82, 101, 102]);
     this.entries.length = 0;
     this._cacheMap.clear();
     const stream = this.stream;
     stream.pos = 0;
     const buffer = stream.getBytes(),
+      bufferStr = (0, _util.bytesToString)(buffer),
       length = buffer.length;
     let position = stream.start;
     const trailers = [],
@@ -364,8 +363,8 @@ class XRef {
       } else if (m = objRegExp.exec(token)) {
         const num = m[1] | 0,
           gen = m[2] | 0;
+        const startPos = position + token.length;
         let contentLength,
-          startPos = position + token.length,
           updateEntries = false;
         if (!this.entries[num]) {
           updateEntries = true;
@@ -391,22 +390,17 @@ class XRef {
             uncompressed: true
           };
         }
-        while (startPos < length) {
-          const endPos = startPos + skipUntil(buffer, startPos, objBytes) + 4;
+        gEndobjRegExp.lastIndex = startPos;
+        const match = gEndobjRegExp.exec(bufferStr);
+        if (match) {
+          const endPos = gEndobjRegExp.lastIndex + 1;
           contentLength = endPos - position;
-          const checkPos = Math.max(endPos - CHECK_CONTENT_LENGTH, startPos);
-          const tokenStr = (0, _util.bytesToString)(buffer.subarray(checkPos, endPos));
-          if (endobjRegExp.test(tokenStr)) {
-            break;
-          } else {
-            const objToken = nestedObjRegExp.exec(tokenStr);
-            if (objToken && objToken[1]) {
-              (0, _util.warn)('indexObjects: Found new "obj" inside of another "obj", ' + 'caused by missing "endobj" -- trying to recover.');
-              contentLength -= objToken[1].length;
-              break;
-            }
+          if (match[1] !== "endobj") {
+            (0, _util.warn)(`indexObjects: Found "${match[1]}" inside of another "obj", ` + 'caused by missing "endobj" -- trying to recover.');
+            contentLength -= match[1].length + 1;
           }
-          startPos = endPos;
+        } else {
+          contentLength = length - position;
         }
         const content = buffer.subarray(position, position + contentLength);
         const xrefTagOffset = skipUntil(content, 0, xrefBytes);
@@ -417,17 +411,19 @@ class XRef {
         position += contentLength;
       } else if (token.startsWith("trailer") && (token.length === 7 || /\s/.test(token[7]))) {
         trailers.push(position);
-        const contentLength = skipUntil(buffer, position, startxrefBytes);
-        if (position + contentLength >= length) {
-          const endPos = position + skipUntil(buffer, position, objBytes) + 4;
-          const checkPos = Math.max(endPos - CHECK_CONTENT_LENGTH, position);
-          const tokenStr = (0, _util.bytesToString)(buffer.subarray(checkPos, endPos));
-          const objToken = nestedObjRegExp.exec(tokenStr);
-          if (objToken && objToken[1]) {
-            (0, _util.warn)('indexObjects: Found first "obj" after "trailer", ' + 'caused by missing "startxref" -- trying to recover.');
-            position = endPos - objToken[1].length;
-            continue;
+        const startPos = position + token.length;
+        let contentLength;
+        gStartxrefRegExp.lastIndex = startPos;
+        const match = gStartxrefRegExp.exec(bufferStr);
+        if (match) {
+          const endPos = gStartxrefRegExp.lastIndex + 1;
+          contentLength = endPos - position;
+          if (match[1] !== "startxref") {
+            (0, _util.warn)(`indexObjects: Found "${match[1]}" after "trailer", ` + 'caused by missing "startxref" -- trying to recover.');
+            contentLength -= match[1].length + 1;
           }
+        } else {
+          contentLength = length - position;
         }
         position += contentLength;
       } else {
@@ -496,8 +492,8 @@ class XRef {
   readXRef(recoveryMode = false) {
     const stream = this.stream;
     const startXRefParsedCache = new Set();
-    try {
-      while (this.startXRefQueue.length) {
+    while (this.startXRefQueue.length) {
+      try {
         const startXRef = this.startXRefQueue[0];
         if (startXRefParsedCache.has(startXRef)) {
           (0, _util.warn)("readXRef - skipping XRef table since it was already parsed.");
@@ -546,16 +542,17 @@ class XRef {
         } else if (obj instanceof _primitives.Ref) {
           this.startXRefQueue.push(obj.num);
         }
-        this.startXRefQueue.shift();
-      }
-      return this.topDict;
-    } catch (e) {
-      if (e instanceof _core_utils.MissingDataException) {
-        throw e;
+      } catch (e) {
+        if (e instanceof _core_utils.MissingDataException) {
+          throw e;
+        }
+        (0, _util.info)("(while reading XRef): " + e);
       }
-      (0, _util.info)("(while reading XRef): " + e);
       this.startXRefQueue.shift();
     }
+    if (this.topDict) {
+      return this.topDict;
+    }
     if (recoveryMode) {
       return undefined;
     }

+ 117 - 102
lib/display/annotation_layer.js

@@ -118,7 +118,6 @@ class AnnotationElement {
     this.enableScripting = parameters.enableScripting;
     this.hasJSActions = parameters.hasJSActions;
     this._fieldObjects = parameters.fieldObjects;
-    this._mouseState = parameters.mouseState;
     if (isRenderable) {
       this.container = this._createContainer(ignoreBorder);
     }
@@ -127,18 +126,23 @@ class AnnotationElement {
     }
   }
   _createContainer(ignoreBorder = false) {
-    const data = this.data,
-      page = this.page,
-      viewport = this.viewport;
+    const {
+      data,
+      page,
+      viewport
+    } = this;
     const container = document.createElement("section");
+    container.setAttribute("data-annotation-id", data.id);
+    const {
+      pageWidth,
+      pageHeight,
+      pageX,
+      pageY
+    } = viewport.rawDims;
     const {
       width,
       height
     } = getRectDims(data.rect);
-    const [pageLLx, pageLLy, pageURx, pageURy] = viewport.viewBox;
-    const pageWidth = pageURx - pageLLx;
-    const pageHeight = pageURy - pageLLy;
-    container.setAttribute("data-annotation-id", data.id);
     const rect = _util.Util.normalizeRect([data.rect[0], page.view[3] - data.rect[1] + page.view[1], data.rect[2], page.view[3] - data.rect[3] + page.view[1]]);
     if (!ignoreBorder && data.borderStyle.width > 0) {
       container.style.borderWidth = `${data.borderStyle.width}px`;
@@ -177,8 +181,8 @@ class AnnotationElement {
         container.style.borderWidth = 0;
       }
     }
-    container.style.left = `${100 * (rect[0] - pageLLx) / pageWidth}%`;
-    container.style.top = `${100 * (rect[1] - pageLLy) / pageHeight}%`;
+    container.style.left = `${100 * (rect[0] - pageX) / pageWidth}%`;
+    container.style.top = `${100 * (rect[1] - pageY) / pageHeight}%`;
     const {
       rotation
     } = data;
@@ -191,9 +195,10 @@ class AnnotationElement {
     return container;
   }
   setRotation(angle, container = this.container) {
-    const [pageLLx, pageLLy, pageURx, pageURy] = this.viewport.viewBox;
-    const pageWidth = pageURx - pageLLx;
-    const pageHeight = pageURy - pageLLy;
+    const {
+      pageWidth,
+      pageHeight
+    } = this.viewport.rawDims;
     const {
       width,
       height
@@ -407,13 +412,6 @@ class AnnotationElement {
     }
     return fields;
   }
-  static get platform() {
-    const platform = typeof navigator !== "undefined" ? navigator.platform : "";
-    return (0, _util.shadow)(this, "platform", {
-      isWin: platform.includes("Win"),
-      isMac: platform.includes("Mac")
-    });
-  }
 }
 class LinkAnnotationElement extends AnnotationElement {
   constructor(parameters, options = null) {
@@ -673,7 +671,7 @@ class WidgetAnnotationElement extends AnnotationElement {
     const {
       isWin,
       isMac
-    } = AnnotationElement.platform;
+    } = _util.FeatureTest.platform;
     return isWin && event.ctrlKey || isMac && event.metaKey;
   }
   _setEventListener(element, baseName, eventName, valueGetter) {
@@ -785,7 +783,8 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
       const elementData = {
         userValue: textContent,
         formattedValue: null,
-        valueOnFocus: ""
+        lastCommittedValue: null,
+        commitKey: 1
       };
       if (this.data.multiLine) {
         element = document.createElement("textarea");
@@ -832,10 +831,14 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
       };
       if (this.enableScripting && this.hasJSActions) {
         element.addEventListener("focus", event => {
+          const {
+            target
+          } = event;
           if (elementData.userValue) {
-            event.target.value = elementData.userValue;
+            target.value = elementData.userValue;
           }
-          elementData.valueOnFocus = event.target.value;
+          elementData.lastCommittedValue = target.value;
+          elementData.commitKey = 1;
         });
         element.addEventListener("updatefromsandbox", jsEvent => {
           const actions = {
@@ -899,13 +902,14 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
           this._dispatchEventFromSandbox(actions, jsEvent);
         });
         element.addEventListener("keydown", event => {
+          elementData.commitKey = 1;
           let commitKey = -1;
           if (event.key === "Escape") {
             commitKey = 0;
           } else if (event.key === "Enter" && !this.data.multiLine) {
             commitKey = 2;
           } else if (event.key === "Tab") {
-            commitKey = 3;
+            elementData.commitKey = 3;
           }
           if (commitKey === -1) {
             return;
@@ -913,9 +917,10 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
           const {
             value
           } = event.target;
-          if (elementData.valueOnFocus === value) {
+          if (elementData.lastCommittedValue === value) {
             return;
           }
+          elementData.lastCommittedValue = value;
           elementData.userValue = value;
           this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
             source: this,
@@ -933,11 +938,14 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
         const _blurListener = blurListener;
         blurListener = null;
         element.addEventListener("blur", event => {
+          if (!event.relatedTarget) {
+            return;
+          }
           const {
             value
           } = event.target;
           elementData.userValue = value;
-          if (this._mouseState.isDown && elementData.valueOnFocus !== value) {
+          if (elementData.lastCommittedValue !== value) {
             this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
               source: this,
               detail: {
@@ -945,7 +953,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
                 name: "Keystroke",
                 value,
                 willCommit: true,
-                commitKey: 1,
+                commitKey: elementData.commitKey,
                 selStart: event.target.selectionStart,
                 selEnd: event.target.selectionEnd
               }
@@ -955,6 +963,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
         });
         if (this.data.actions?.Keystroke) {
           element.addEventListener("beforeinput", event => {
+            elementData.lastCommittedValue = null;
             const {
               data,
               target
@@ -1262,14 +1271,18 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
       };
       selectElement.addEventListener("input", removeEmptyEntry);
     }
-    const getValue = (event, isExport) => {
+    const getValue = isExport => {
       const name = isExport ? "value" : "textContent";
-      const options = event.target.options;
-      if (!event.target.multiple) {
+      const {
+        options,
+        multiple
+      } = selectElement;
+      if (!multiple) {
         return options.selectedIndex === -1 ? null : options[options.selectedIndex][name];
       }
       return Array.prototype.filter.call(options, option => option.selected).map(option => option[name]);
     };
+    let selectedValues = getValue(false);
     const getItems = event => {
       const options = event.target.options;
       return Array.prototype.map.call(options, option => {
@@ -1290,8 +1303,9 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
               option.selected = values.has(option.value);
             }
             storage.setValue(id, {
-              value: getValue(event, true)
+              value: getValue(true)
             });
+            selectedValues = getValue(false);
           },
           multipleSelection(event) {
             selectElement.multiple = true;
@@ -1308,9 +1322,10 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
               }
             }
             storage.setValue(id, {
-              value: getValue(event, true),
+              value: getValue(true),
               items: getItems(event)
             });
+            selectedValues = getValue(false);
           },
           clear(event) {
             while (selectElement.length !== 0) {
@@ -1320,6 +1335,7 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
               value: null,
               items: []
             });
+            selectedValues = getValue(false);
           },
           insert(event) {
             const {
@@ -1337,9 +1353,10 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
               selectElement.append(optionElement);
             }
             storage.setValue(id, {
-              value: getValue(event, true),
+              value: getValue(true),
               items: getItems(event)
             });
+            selectedValues = getValue(false);
           },
           items(event) {
             const {
@@ -1362,9 +1379,10 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
               selectElement.options[0].selected = true;
             }
             storage.setValue(id, {
-              value: getValue(event, true),
+              value: getValue(true),
               items: getItems(event)
             });
+            selectedValues = getValue(false);
           },
           indices(event) {
             const indices = new Set(event.detail.indices);
@@ -1372,8 +1390,9 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
               option.selected = indices.has(option.index);
             }
             storage.setValue(id, {
-              value: getValue(event, true)
+              value: getValue(true)
             });
+            selectedValues = getValue(false);
           },
           editable(event) {
             event.target.disabled = !event.detail.editable;
@@ -1382,19 +1401,19 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
         this._dispatchEventFromSandbox(actions, jsEvent);
       });
       selectElement.addEventListener("input", event => {
-        const exportValue = getValue(event, true);
-        const value = getValue(event, false);
+        const exportValue = getValue(true);
         storage.setValue(id, {
           value: exportValue
         });
+        event.preventDefault();
         this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
           source: this,
           detail: {
             id,
             name: "Keystroke",
-            value,
+            value: selectedValues,
             changeEx: exportValue,
-            willCommit: true,
+            willCommit: false,
             commitKey: 1,
             keyDown: false
           }
@@ -1404,7 +1423,7 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
     } else {
       selectElement.addEventListener("input", function (event) {
         storage.setValue(id, {
-          value: getValue(event, true)
+          value: getValue(true)
         });
       });
     }
@@ -1447,11 +1466,14 @@ class PopupAnnotationElement extends AnnotationElement {
     const rect = _util.Util.normalizeRect([this.data.parentRect[0], page.view[3] - this.data.parentRect[1] + page.view[1], this.data.parentRect[2], page.view[3] - this.data.parentRect[3] + page.view[1]]);
     const popupLeft = rect[0] + this.data.parentRect[2] - this.data.parentRect[0];
     const popupTop = rect[1];
-    const [pageLLx, pageLLy, pageURx, pageURy] = this.viewport.viewBox;
-    const pageWidth = pageURx - pageLLx;
-    const pageHeight = pageURy - pageLLy;
-    this.container.style.left = `${100 * (popupLeft - pageLLx) / pageWidth}%`;
-    this.container.style.top = `${100 * (popupTop - pageLLy) / pageHeight}%`;
+    const {
+      pageWidth,
+      pageHeight,
+      pageX,
+      pageY
+    } = this.viewport.rawDims;
+    this.container.style.left = `${100 * (popupLeft - pageX) / pageWidth}%`;
+    this.container.style.top = `${100 * (popupTop - pageY) / pageHeight}%`;
     this.container.append(popup.render());
     return this.container;
   }
@@ -1897,7 +1919,13 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
   }
   render() {
     this.container.className = "fileAttachmentAnnotation";
-    const trigger = document.createElement("div");
+    let trigger;
+    if (this.data.hasAppearance) {
+      trigger = document.createElement("div");
+    } else {
+      trigger = document.createElement("img");
+      trigger.src = `${this.imageResourcesPath}annotation-${/paperclip/i.test(this.data.name) ? "paperclip" : "pushpin"}.svg`;
+    }
     trigger.className = "popupTriggerArea";
     trigger.addEventListener("dblclick", this._download.bind(this));
     if (!this.data.hasPopup && (this.data.titleObj?.str || this.data.contentsObj?.str || this.data.richText)) {
@@ -1917,14 +1945,29 @@ class AnnotationLayer {
     div.append(element);
     accessibilityManager?.moveElementInDOM(div, element, contentElement, false);
   }
-  static render(parameters) {
+  static render(params) {
     const {
       annotations,
       div,
       viewport,
       accessibilityManager
-    } = parameters;
-    this.#setDimensions(div, viewport);
+    } = params;
+    (0, _display_utils.setLayerDimensions)(div, viewport);
+    const elementParams = {
+      data: null,
+      layer: div,
+      page: params.page,
+      viewport,
+      linkService: params.linkService,
+      downloadManager: params.downloadManager,
+      imageResourcesPath: params.imageResourcesPath || "",
+      renderForms: params.renderForms !== false,
+      svgFactory: new _display_utils.DOMSVGFactory(),
+      annotationStorage: params.annotationStorage || new _annotation_storage.AnnotationStorage(),
+      enableScripting: params.enableScripting === true,
+      hasJSActions: params.hasJSActions,
+      fieldObjects: params.fieldObjects
+    };
     let zIndex = 0;
     for (const data of annotations) {
       if (data.annotationType !== _util.AnnotationType.POPUP) {
@@ -1936,71 +1979,43 @@ class AnnotationLayer {
           continue;
         }
       }
-      const element = AnnotationElementFactory.create({
-        data,
-        layer: div,
-        page: parameters.page,
-        viewport,
-        linkService: parameters.linkService,
-        downloadManager: parameters.downloadManager,
-        imageResourcesPath: parameters.imageResourcesPath || "",
-        renderForms: parameters.renderForms !== false,
-        svgFactory: new _display_utils.DOMSVGFactory(),
-        annotationStorage: parameters.annotationStorage || new _annotation_storage.AnnotationStorage(),
-        enableScripting: parameters.enableScripting,
-        hasJSActions: parameters.hasJSActions,
-        fieldObjects: parameters.fieldObjects,
-        mouseState: parameters.mouseState || {
-          isDown: false
-        }
-      });
-      if (element.isRenderable) {
-        const rendered = element.render();
-        if (data.hidden) {
-          rendered.style.visibility = "hidden";
+      elementParams.data = data;
+      const element = AnnotationElementFactory.create(elementParams);
+      if (!element.isRenderable) {
+        continue;
+      }
+      const rendered = element.render();
+      if (data.hidden) {
+        rendered.style.visibility = "hidden";
+      }
+      if (Array.isArray(rendered)) {
+        for (const renderedElement of rendered) {
+          renderedElement.style.zIndex = zIndex++;
+          AnnotationLayer.#appendElement(renderedElement, data.id, div, accessibilityManager);
         }
-        if (Array.isArray(rendered)) {
-          for (const renderedElement of rendered) {
-            renderedElement.style.zIndex = zIndex++;
-            AnnotationLayer.#appendElement(renderedElement, data.id, div, accessibilityManager);
-          }
+      } else {
+        rendered.style.zIndex = zIndex++;
+        if (element instanceof PopupAnnotationElement) {
+          div.prepend(rendered);
         } else {
-          rendered.style.zIndex = zIndex++;
-          if (element instanceof PopupAnnotationElement) {
-            div.prepend(rendered);
-          } else {
-            AnnotationLayer.#appendElement(rendered, data.id, div, accessibilityManager);
-          }
+          AnnotationLayer.#appendElement(rendered, data.id, div, accessibilityManager);
         }
       }
     }
-    this.#setAnnotationCanvasMap(div, parameters.annotationCanvasMap);
+    this.#setAnnotationCanvasMap(div, params.annotationCanvasMap);
   }
-  static update(parameters) {
+  static update(params) {
     const {
       annotationCanvasMap,
       div,
       viewport
-    } = parameters;
-    this.#setDimensions(div, viewport);
+    } = params;
+    (0, _display_utils.setLayerDimensions)(div, {
+      rotation: viewport.rotation
+    });
     this.#setAnnotationCanvasMap(div, annotationCanvasMap);
     div.hidden = false;
   }
-  static #setDimensions(div, {
-    width,
-    height,
-    rotation
-  }) {
-    const {
-      style
-    } = div;
-    const flipOrientation = rotation % 180 !== 0,
-      widthStr = Math.floor(width) + "px",
-      heightStr = Math.floor(height) + "px";
-    style.width = flipOrientation ? heightStr : widthStr;
-    style.height = flipOrientation ? widthStr : heightStr;
-    div.setAttribute("data-main-rotation", rotation);
-  }
   static #setAnnotationCanvasMap(div, annotationCanvasMap) {
     if (!annotationCanvasMap) {
       return;

+ 33 - 26
lib/display/api.js

@@ -240,7 +240,7 @@ async function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
   }
   const workerId = await worker.messageHandler.sendWithPromise("GetDocRequest", {
     docId,
-    apiVersion: '3.1.81',
+    apiVersion: '3.2.146',
     data: source.data,
     password: source.password,
     disableAutoFetch: source.disableAutoFetch,
@@ -270,6 +270,7 @@ async function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
 }
 class PDFDocumentLoadingTask {
   static #docId = 0;
+  #onUnsupportedFeature = null;
   constructor() {
     this._capability = (0, _util.createPromiseCapability)();
     this._transport = null;
@@ -278,7 +279,13 @@ class PDFDocumentLoadingTask {
     this.destroyed = false;
     this.onPassword = null;
     this.onProgress = null;
-    this.onUnsupportedFeature = null;
+  }
+  get onUnsupportedFeature() {
+    return this.#onUnsupportedFeature;
+  }
+  set onUnsupportedFeature(callback) {
+    (0, _display_utils.deprecated)("The PDFDocumentLoadingTask onUnsupportedFeature property will be removed in the future.");
+    this.#onUnsupportedFeature = callback;
   }
   get promise() {
     return this._capability.promise;
@@ -368,10 +375,11 @@ class PDFDocumentProxy {
     return this._pdfInfo.fingerprints;
   }
   get stats() {
+    (0, _display_utils.deprecated)("The PDFDocumentProxy stats property will be removed in the future.");
     return this._transport.stats;
   }
   get isPureXfa() {
-    return !!this._transport._htmlForXfa;
+    return (0, _util.shadow)(this, "isPureXfa", !!this._transport._htmlForXfa);
   }
   get allXfaHtml() {
     return this._transport._htmlForXfa;
@@ -473,7 +481,6 @@ class PDFPageProxy {
     this.cleanupAfterRender = false;
     this.pendingCleanup = false;
     this._intentStates = new Map();
-    this._annotationPromises = new Map();
     this.destroyed = false;
   }
   get pageNumber() {
@@ -511,15 +518,13 @@ class PDFPageProxy {
     intent = "display"
   } = {}) {
     const intentArgs = this._transport.getRenderingIntent(intent);
-    let promise = this._annotationPromises.get(intentArgs.cacheKey);
-    if (!promise) {
-      promise = this._transport.getAnnotations(this._pageIndex, intentArgs.renderingIntent);
-      this._annotationPromises.set(intentArgs.cacheKey, promise);
-    }
-    return promise;
+    return this._transport.getAnnotations(this._pageIndex, intentArgs.renderingIntent);
   }
   getJSActions() {
-    return this._jsActionsPromise ||= this._transport.getPageJSActions(this._pageIndex);
+    return this._transport.getPageJSActions(this._pageIndex);
+  }
+  get isPureXfa() {
+    return (0, _util.shadow)(this, "isPureXfa", !!this._transport._htmlForXfa);
   }
   async getXfa() {
     return this._transport._htmlForXfa?.children[this._pageIndex] || null;
@@ -700,7 +705,7 @@ class PDFPageProxy {
     });
   }
   getStructTree() {
-    return this._structTreePromise ||= this._transport.getStructTree(this._pageIndex);
+    return this._transport.getStructTree(this._pageIndex);
   }
   _destroy() {
     this.destroyed = true;
@@ -724,9 +729,6 @@ class PDFPageProxy {
       bitmap.close();
     }
     this._bitmaps.clear();
-    this._annotationPromises.clear();
-    this._jsActionsPromise = null;
-    this._structTreePromise = null;
     this.pendingCleanup = false;
     return Promise.all(waitOn);
   }
@@ -748,9 +750,6 @@ class PDFPageProxy {
     }
     this._intentStates.clear();
     this.objs.clear();
-    this._annotationPromises.clear();
-    this._jsActionsPromise = null;
-    this._structTreePromise = null;
     if (resetStats && this._stats) {
       this._stats = new _display_utils.StatTimer();
     }
@@ -842,19 +841,27 @@ class PDFPageProxy {
     if (!intentState.streamReader) {
       return;
     }
+    if (intentState.streamReaderCancelTimeout) {
+      clearTimeout(intentState.streamReaderCancelTimeout);
+      intentState.streamReaderCancelTimeout = null;
+    }
     if (!force) {
       if (intentState.renderTasks.size > 0) {
         return;
       }
       if (reason instanceof _display_utils.RenderingCancelledException) {
+        let delay = RENDERING_CANCELLED_TIMEOUT;
+        if (reason.extraDelay > 0 && reason.extraDelay < 1000) {
+          delay += reason.extraDelay;
+        }
         intentState.streamReaderCancelTimeout = setTimeout(() => {
+          intentState.streamReaderCancelTimeout = null;
           this._abortOperatorList({
             intentState,
             reason,
             force: true
           });
-          intentState.streamReaderCancelTimeout = null;
-        }, RENDERING_CANCELLED_TIMEOUT);
+        }, delay);
         return;
       }
     }
@@ -1746,8 +1753,8 @@ class RenderTask {
   get promise() {
     return this.#internalRenderTask.capability.promise;
   }
-  cancel() {
-    this.#internalRenderTask.cancel();
+  cancel(extraDelay = 0) {
+    this.#internalRenderTask.cancel(null, extraDelay);
   }
   get separateAnnots() {
     const {
@@ -1842,14 +1849,14 @@ class InternalRenderTask {
     this.graphicsReady = true;
     this.graphicsReadyCallback?.();
   }
-  cancel(error = null) {
+  cancel(error = null, extraDelay = 0) {
     this.running = false;
     this.cancelled = true;
     this.gfx?.endDrawing();
     if (this._canvas) {
       InternalRenderTask.#canvasInUse.delete(this._canvas);
     }
-    this.callback(error || new _display_utils.RenderingCancelledException(`Rendering cancelled, page ${this._pageIndex + 1}`, "canvas"));
+    this.callback(error || new _display_utils.RenderingCancelledException(`Rendering cancelled, page ${this._pageIndex + 1}`, "canvas", extraDelay));
   }
   operatorListChanged() {
     if (!this.graphicsReady) {
@@ -1901,7 +1908,7 @@ class InternalRenderTask {
     }
   }
 }
-const version = '3.1.81';
+const version = '3.2.146';
 exports.version = version;
-const build = '0766898d5';
+const build = '3fd2a3548';
 exports.build = build;

+ 2 - 4
lib/display/canvas.js

@@ -1257,8 +1257,7 @@ class CanvasGraphics {
   closePath() {
     this.ctx.closePath();
   }
-  stroke(consumePath) {
-    consumePath = typeof consumePath !== "undefined" ? consumePath : true;
+  stroke(consumePath = true) {
     const ctx = this.ctx;
     const strokeColor = this.current.strokeColor;
     ctx.globalAlpha = this.current.strokeAlpha;
@@ -1281,8 +1280,7 @@ class CanvasGraphics {
     this.closePath();
     this.stroke();
   }
-  fill(consumePath) {
-    consumePath = typeof consumePath !== "undefined" ? consumePath : true;
+  fill(consumePath = true) {
     const ctx = this.ctx;
     const fillColor = this.current.fillColor;
     const isPatternFill = this.current.patternFill;

+ 41 - 5
lib/display/display_utils.js

@@ -37,6 +37,7 @@ exports.isDataScheme = isDataScheme;
 exports.isPdfFile = isPdfFile;
 exports.isValidFetchUrl = isValidFetchUrl;
 exports.loadScript = loadScript;
+exports.setLayerDimensions = setLayerDimensions;
 var _base_factory = require("./base_factory.js");
 var _util = require("../shared/util.js");
 const SVG_NS = "http://www.w3.org/2000/svg";
@@ -179,18 +180,29 @@ class PageViewport {
     if (rotateA === 0) {
       offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
       offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
-      width = Math.abs(viewBox[3] - viewBox[1]) * scale;
-      height = Math.abs(viewBox[2] - viewBox[0]) * scale;
+      width = (viewBox[3] - viewBox[1]) * scale;
+      height = (viewBox[2] - viewBox[0]) * scale;
     } else {
       offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
       offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
-      width = Math.abs(viewBox[2] - viewBox[0]) * scale;
-      height = Math.abs(viewBox[3] - viewBox[1]) * scale;
+      width = (viewBox[2] - viewBox[0]) * scale;
+      height = (viewBox[3] - viewBox[1]) * scale;
     }
     this.transform = [rotateA * scale, rotateB * scale, rotateC * scale, rotateD * scale, offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY];
     this.width = width;
     this.height = height;
   }
+  get rawDims() {
+    const {
+      viewBox
+    } = this;
+    return (0, _util.shadow)(this, "rawDims", {
+      pageWidth: viewBox[2] - viewBox[0],
+      pageHeight: viewBox[3] - viewBox[1],
+      pageX: viewBox[0],
+      pageY: viewBox[1]
+    });
+  }
   clone({
     scale = this.scale,
     rotation = this.rotation,
@@ -221,9 +233,10 @@ class PageViewport {
 }
 exports.PageViewport = PageViewport;
 class RenderingCancelledException extends _util.BaseException {
-  constructor(msg, type) {
+  constructor(msg, type, extraDelay = 0) {
     super(msg, "RenderingCancelledException");
     this.type = type;
+    this.extraDelay = extraDelay;
   }
 }
 exports.RenderingCancelledException = RenderingCancelledException;
@@ -435,4 +448,27 @@ function getCurrentTransformInverse(ctx) {
     f
   } = ctx.getTransform().invertSelf();
   return [a, b, c, d, e, f];
+}
+function setLayerDimensions(div, viewport, mustFlip = false, mustRotate = true) {
+  if (viewport instanceof PageViewport) {
+    const {
+      pageWidth,
+      pageHeight
+    } = viewport.rawDims;
+    const {
+      style
+    } = div;
+    const widthStr = `calc(var(--scale-factor) * ${pageWidth}px)`;
+    const heightStr = `calc(var(--scale-factor) * ${pageHeight}px)`;
+    if (!mustFlip || viewport.rotation % 180 === 0) {
+      style.width = widthStr;
+      style.height = heightStr;
+    } else {
+      style.width = heightStr;
+      style.height = widthStr;
+    }
+  }
+  if (mustRotate) {
+    div.setAttribute("data-main-rotation", viewport.rotation);
+  }
 }

+ 31 - 50
lib/display/editor/annotation_editor_layer.js

@@ -25,10 +25,11 @@ Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.AnnotationEditorLayer = void 0;
-var _tools = require("./tools.js");
 var _util = require("../../shared/util.js");
+var _tools = require("./tools.js");
 var _freetext = require("./freetext.js");
 var _ink = require("./ink.js");
+var _display_utils = require("../display_utils.js");
 class AnnotationEditorLayer {
   #accessibilityManager;
   #allowClick = false;
@@ -47,7 +48,6 @@ class AnnotationEditorLayer {
     }
     options.uiManager.registerEditorTypes([_freetext.FreeTextEditor, _ink.InkEditor]);
     this.#uiManager = options.uiManager;
-    this.annotationStorage = options.annotationStorage;
     this.pageIndex = options.pageIndex;
     this.div = options.div;
     this.#accessibilityManager = options.accessibilityManager;
@@ -129,7 +129,6 @@ class AnnotationEditorLayer {
   remove(editor) {
     this.#uiManager.removeEditor(editor);
     this.detach(editor);
-    this.annotationStorage.remove(editor.id);
     editor.div.style.display = "none";
     setTimeout(() => {
       editor.div.style.display = "";
@@ -148,9 +147,8 @@ class AnnotationEditorLayer {
       return;
     }
     this.attach(editor);
-    editor.pageIndex = this.pageIndex;
     editor.parent?.detach(editor);
-    editor.parent = this;
+    editor.setParent(this);
     if (editor.div && editor.isAttachedToDOM) {
       editor.div.remove();
       this.div.append(editor.div);
@@ -167,16 +165,11 @@ class AnnotationEditorLayer {
     }
     this.moveEditorInDOM(editor);
     editor.onceAdded();
-    this.addToAnnotationStorage(editor);
+    this.#uiManager.addToAnnotationStorage(editor);
   }
   moveEditorInDOM(editor) {
     this.#accessibilityManager?.moveElementInDOM(this.div, editor.div, editor.contentDiv, true);
   }
-  addToAnnotationStorage(editor) {
-    if (!editor.isEmpty() && !this.annotationStorage.has(editor.id)) {
-      this.annotationStorage.setValue(editor.id, editor);
-    }
-  }
   addOrRebuild(editor) {
     if (editor.needsToBeRebuilt()) {
       editor.rebuild();
@@ -225,9 +218,9 @@ class AnnotationEditorLayer {
   deserialize(data) {
     switch (data.annotationType) {
       case _util.AnnotationEditorType.FREETEXT:
-        return _freetext.FreeTextEditor.deserialize(data, this);
+        return _freetext.FreeTextEditor.deserialize(data, this, this.#uiManager);
       case _util.AnnotationEditorType.INK:
-        return _ink.InkEditor.deserialize(data, this);
+        return _ink.InkEditor.deserialize(data, this, this.#uiManager);
     }
     return null;
   }
@@ -237,7 +230,8 @@ class AnnotationEditorLayer {
       parent: this,
       id,
       x: event.offsetX,
-      y: event.offsetY
+      y: event.offsetY,
+      uiManager: this.#uiManager
     });
     if (editor) {
       this.add(editor);
@@ -257,7 +251,9 @@ class AnnotationEditorLayer {
     this.#uiManager.unselect(editor);
   }
   pointerup(event) {
-    const isMac = _tools.KeyboardManager.platform.isMac;
+    const {
+      isMac
+    } = _util.FeatureTest.platform;
     if (event.button !== 0 || event.ctrlKey && isMac) {
       return;
     }
@@ -275,7 +271,9 @@ class AnnotationEditorLayer {
     this.#createAndAddNewEditor(event);
   }
   pointerdown(event) {
-    const isMac = _tools.KeyboardManager.platform.isMac;
+    const {
+      isMac
+    } = _util.FeatureTest.platform;
     if (event.button !== 0 || event.ctrlKey && isMac) {
       return;
     }
@@ -311,9 +309,9 @@ class AnnotationEditorLayer {
     }
     for (const editor of this.#editors.values()) {
       this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv);
+      editor.setParent(null);
       editor.isAttachedToDOM = false;
       editor.div.remove();
-      editor.parent = null;
     }
     this.div = null;
     this.#editors.clear();
@@ -328,50 +326,33 @@ class AnnotationEditorLayer {
     }
     this.#isCleaningUp = false;
   }
-  render(parameters) {
-    this.viewport = parameters.viewport;
+  render({
+    viewport
+  }) {
+    this.viewport = viewport;
+    (0, _display_utils.setLayerDimensions)(this.div, viewport);
     (0, _tools.bindEvents)(this, this.div, ["dragover", "drop"]);
-    this.setDimensions();
     for (const editor of this.#uiManager.getEditors(this.pageIndex)) {
       this.add(editor);
     }
     this.updateMode();
   }
-  update(parameters) {
+  update({
+    viewport
+  }) {
     this.#uiManager.commitOrRemove();
-    this.viewport = parameters.viewport;
-    this.setDimensions();
+    this.viewport = viewport;
+    (0, _display_utils.setLayerDimensions)(this.div, {
+      rotation: viewport.rotation
+    });
     this.updateMode();
   }
-  get scaleFactor() {
-    return this.viewport.scale;
-  }
   get pageDimensions() {
-    const [pageLLx, pageLLy, pageURx, pageURy] = this.viewport.viewBox;
-    const width = pageURx - pageLLx;
-    const height = pageURy - pageLLy;
-    return [width, height];
-  }
-  get viewportBaseDimensions() {
-    const {
-      width,
-      height,
-      rotation
-    } = this.viewport;
-    return rotation % 180 === 0 ? [width, height] : [height, width];
-  }
-  setDimensions() {
     const {
-      width,
-      height,
-      rotation
-    } = this.viewport;
-    const flipOrientation = rotation % 180 !== 0,
-      widthStr = Math.floor(width) + "px",
-      heightStr = Math.floor(height) + "px";
-    this.div.style.width = flipOrientation ? heightStr : widthStr;
-    this.div.style.height = flipOrientation ? widthStr : heightStr;
-    this.div.setAttribute("data-main-rotation", rotation);
+      pageWidth,
+      pageHeight
+    } = this.viewport.rawDims;
+    return [pageWidth, pageHeight];
   }
 }
 exports.AnnotationEditorLayer = AnnotationEditorLayer;

+ 67 - 24
lib/display/editor/editor.js

@@ -33,6 +33,7 @@ class AnnotationEditor {
   #hasBeenSelected = false;
   #isEditing = false;
   #isInEditMode = false;
+  _uiManager = null;
   #zIndex = AnnotationEditor._zIndex++;
   static _colorManager = new _tools.ColorManager();
   static _zIndex = 1;
@@ -46,21 +47,46 @@ class AnnotationEditor {
     this.pageIndex = parameters.parent.pageIndex;
     this.name = parameters.name;
     this.div = null;
-    const [width, height] = this.parent.viewportBaseDimensions;
+    this._uiManager = parameters.uiManager;
+    const {
+      rotation,
+      rawDims: {
+        pageWidth,
+        pageHeight,
+        pageX,
+        pageY
+      }
+    } = this.parent.viewport;
+    this.rotation = rotation;
+    this.pageDimensions = [pageWidth, pageHeight];
+    this.pageTranslation = [pageX, pageY];
+    const [width, height] = this.parentDimensions;
     this.x = parameters.x / width;
     this.y = parameters.y / height;
-    this.rotation = this.parent.viewport.rotation;
     this.isAttachedToDOM = false;
   }
   static get _defaultLineColor() {
     return (0, _util.shadow)(this, "_defaultLineColor", this._colorManager.getHexCode("CanvasText"));
   }
+  addCommands(params) {
+    this._uiManager.addCommands(params);
+  }
+  get currentLayer() {
+    return this._uiManager.currentLayer;
+  }
   setInBackground() {
     this.div.style.zIndex = 0;
   }
   setInForeground() {
     this.div.style.zIndex = this.#zIndex;
   }
+  setParent(parent) {
+    if (parent !== null) {
+      this.pageIndex = parent.pageIndex;
+      this.pageDimensions = parent.pageDimensions;
+    }
+    this.parent = parent;
+  }
   focusin(event) {
     if (!this.#hasBeenSelected) {
       this.parent.setSelected(this);
@@ -77,7 +103,7 @@ class AnnotationEditor {
       return;
     }
     event.preventDefault();
-    if (!this.parent.isMultipleSelection) {
+    if (!this.parent?.isMultipleSelection) {
       this.commitOrRemove();
     }
   }
@@ -89,7 +115,10 @@ class AnnotationEditor {
     }
   }
   commit() {
-    this.parent.addToAnnotationStorage(this);
+    this.addToAnnotationStorage();
+  }
+  addToAnnotationStorage() {
+    this._uiManager.addToAnnotationStorage(this);
   }
   dragstart(event) {
     const rect = this.parent.div.getBoundingClientRect();
@@ -99,7 +128,7 @@ class AnnotationEditor {
     event.dataTransfer.effectAllowed = "move";
   }
   setAt(x, y, tx, ty) {
-    const [width, height] = this.parent.viewportBaseDimensions;
+    const [width, height] = this.parentDimensions;
     [tx, ty] = this.screenToPageTranslation(tx, ty);
     this.x = (x + tx) / width;
     this.y = (y + ty) / height;
@@ -107,7 +136,7 @@ class AnnotationEditor {
     this.div.style.top = `${100 * this.y}%`;
   }
   translate(x, y) {
-    const [width, height] = this.parent.viewportBaseDimensions;
+    const [width, height] = this.parentDimensions;
     [x, y] = this.screenToPageTranslation(x, y);
     this.x += x / width;
     this.y += y / height;
@@ -115,10 +144,7 @@ class AnnotationEditor {
     this.div.style.top = `${100 * this.y}%`;
   }
   screenToPageTranslation(x, y) {
-    const {
-      rotation
-    } = this.parent.viewport;
-    switch (rotation) {
+    switch (this.parentRotation) {
       case 90:
         return [y, -x];
       case 180:
@@ -129,8 +155,21 @@ class AnnotationEditor {
         return [x, y];
     }
   }
+  get parentScale() {
+    return this._uiManager.viewParameters.realScale;
+  }
+  get parentRotation() {
+    return this._uiManager.viewParameters.rotation;
+  }
+  get parentDimensions() {
+    const {
+      realScale
+    } = this._uiManager.viewParameters;
+    const [pageWidth, pageHeight] = this.pageDimensions;
+    return [pageWidth * realScale, pageHeight * realScale];
+  }
   setDims(width, height) {
-    const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions;
+    const [parentWidth, parentHeight] = this.parentDimensions;
     this.div.style.width = `${100 * width / parentWidth}%`;
     this.div.style.height = `${100 * height / parentHeight}%`;
   }
@@ -147,7 +186,7 @@ class AnnotationEditor {
     if (widthPercent && heightPercent) {
       return;
     }
-    const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions;
+    const [parentWidth, parentHeight] = this.parentDimensions;
     if (!widthPercent) {
       style.width = `${100 * parseFloat(width) / parentWidth}%`;
     }
@@ -173,7 +212,9 @@ class AnnotationEditor {
     return this.div;
   }
   pointerdown(event) {
-    const isMac = _tools.KeyboardManager.platform.isMac;
+    const {
+      isMac
+    } = _util.FeatureTest.platform;
     if (event.button !== 0 || event.ctrlKey && isMac) {
       event.preventDefault();
       return;
@@ -186,23 +227,24 @@ class AnnotationEditor {
     this.#hasBeenSelected = true;
   }
   getRect(tx, ty) {
-    const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions;
-    const [pageWidth, pageHeight] = this.parent.pageDimensions;
-    const shiftX = pageWidth * tx / parentWidth;
-    const shiftY = pageHeight * ty / parentHeight;
+    const scale = this.parentScale;
+    const [pageWidth, pageHeight] = this.pageDimensions;
+    const [pageX, pageY] = this.pageTranslation;
+    const shiftX = tx / scale;
+    const shiftY = ty / scale;
     const x = this.x * pageWidth;
     const y = this.y * pageHeight;
     const width = this.width * pageWidth;
     const height = this.height * pageHeight;
     switch (this.rotation) {
       case 0:
-        return [x + shiftX, pageHeight - y - shiftY - height, x + shiftX + width, pageHeight - y - shiftY];
+        return [x + shiftX + pageX, pageHeight - y - shiftY - height + pageY, x + shiftX + width + pageX, pageHeight - y - shiftY + pageY];
       case 90:
-        return [x + shiftY, pageHeight - y + shiftX, x + shiftY + height, pageHeight - y + shiftX + width];
+        return [x + shiftY + pageX, pageHeight - y + shiftX + pageY, x + shiftY + height + pageX, pageHeight - y + shiftX + width + pageY];
       case 180:
-        return [x - shiftX - width, pageHeight - y + shiftY, x - shiftX, pageHeight - y + shiftY + height];
+        return [x - shiftX - width + pageX, pageHeight - y + shiftY + pageY, x - shiftX + pageX, pageHeight - y + shiftY + height + pageY];
       case 270:
-        return [x - shiftY - height, pageHeight - y - shiftX - width, x - shiftY, pageHeight - y - shiftX];
+        return [x - shiftY - height + pageX, pageHeight - y - shiftX - width + pageY, x - shiftY + pageX, pageHeight - y - shiftX + pageY];
       default:
         throw new Error("Invalid rotation");
     }
@@ -249,13 +291,14 @@ class AnnotationEditor {
   serialize() {
     (0, _util.unreachable)("An editor must be serializable");
   }
-  static deserialize(data, parent) {
+  static deserialize(data, parent, uiManager) {
     const editor = new this.prototype.constructor({
       parent,
-      id: parent.getNextId()
+      id: parent.getNextId(),
+      uiManager
     });
     editor.rotation = data.rotation;
-    const [pageWidth, pageHeight] = parent.pageDimensions;
+    const [pageWidth, pageHeight] = editor.pageDimensions;
     const [x, y, width, height] = editor.getRectInCurrentCoords(data.rect, pageHeight);
     editor.x = x / pageWidth;
     editor.y = y / pageHeight;

+ 35 - 17
lib/display/editor/freetext.js

@@ -87,12 +87,12 @@ class FreeTextEditor extends _editor.AnnotationEditor {
   #updateFontSize(fontSize) {
     const setFontsize = size => {
       this.editorDiv.style.fontSize = `calc(${size}px * var(--scale-factor))`;
-      this.translate(0, -(size - this.#fontSize) * this.parent.scaleFactor);
+      this.translate(0, -(size - this.#fontSize) * this.parentScale);
       this.#fontSize = size;
       this.#setEditorDimensions();
     };
     const savedFontsize = this.#fontSize;
-    this.parent.addCommands({
+    this.addCommands({
       cmd: () => {
         setFontsize(fontSize);
       },
@@ -107,14 +107,12 @@ class FreeTextEditor extends _editor.AnnotationEditor {
   }
   #updateColor(color) {
     const savedColor = this.#color;
-    this.parent.addCommands({
+    this.addCommands({
       cmd: () => {
-        this.#color = color;
-        this.editorDiv.style.color = color;
+        this.#color = this.editorDiv.style.color = color;
       },
       undo: () => {
-        this.#color = savedColor;
-        this.editorDiv.style.color = savedColor;
+        this.#color = this.editorDiv.style.color = savedColor;
       },
       mustExec: true,
       type: _util.AnnotationEditorParamsType.FREETEXT_COLOR,
@@ -123,7 +121,8 @@ class FreeTextEditor extends _editor.AnnotationEditor {
     });
   }
   getInitialTranslation() {
-    return [-FreeTextEditor._internalPadding * this.parent.scaleFactor, -(FreeTextEditor._internalPadding + this.#fontSize) * this.parent.scaleFactor];
+    const scale = this.parentScale;
+    return [-FreeTextEditor._internalPadding * scale, -(FreeTextEditor._internalPadding + this.#fontSize) * scale];
   }
   rebuild() {
     super.rebuild();
@@ -164,7 +163,9 @@ class FreeTextEditor extends _editor.AnnotationEditor {
     this.editorDiv.removeEventListener("focus", this.#boundEditorDivFocus);
     this.editorDiv.removeEventListener("blur", this.#boundEditorDivBlur);
     this.editorDiv.removeEventListener("input", this.#boundEditorDivInput);
-    this.div.focus();
+    this.div.focus({
+      preventScroll: true
+    });
     this.isEditing = false;
     this.parent.div.classList.add("freeTextEditing");
   }
@@ -202,12 +203,29 @@ class FreeTextEditor extends _editor.AnnotationEditor {
     return buffer.join("\n");
   }
   #setEditorDimensions() {
-    const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions;
-    const rect = this.div.getBoundingClientRect();
+    const [parentWidth, parentHeight] = this.parentDimensions;
+    let rect;
+    if (this.isAttachedToDOM) {
+      rect = this.div.getBoundingClientRect();
+    } else {
+      const {
+        currentLayer,
+        div
+      } = this;
+      const savedDisplay = div.style.display;
+      div.style.display = "hidden";
+      currentLayer.div.append(this.div);
+      rect = div.getBoundingClientRect();
+      div.remove();
+      div.style.display = savedDisplay;
+    }
     this.width = rect.width / parentWidth;
     this.height = rect.height / parentHeight;
   }
   commit() {
+    if (!this.isInEditMode()) {
+      return;
+    }
     super.commit();
     if (!this.#hasAlreadyBeenCommitted) {
       this.#hasAlreadyBeenCommitted = true;
@@ -278,7 +296,7 @@ class FreeTextEditor extends _editor.AnnotationEditor {
     this.div.append(this.overlayDiv);
     (0, _tools.bindEvents)(this, this.div, ["dblclick", "keydown"]);
     if (this.width) {
-      const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions;
+      const [parentWidth, parentHeight] = this.parentDimensions;
       this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight);
       for (const line of this.#content.split("\n")) {
         const div = document.createElement("div");
@@ -296,8 +314,8 @@ class FreeTextEditor extends _editor.AnnotationEditor {
   get contentDiv() {
     return this.editorDiv;
   }
-  static deserialize(data, parent) {
-    const editor = super.deserialize(data, parent);
+  static deserialize(data, parent, uiManager) {
+    const editor = super.deserialize(data, parent, uiManager);
     editor.#fontSize = data.fontSize;
     editor.#color = _util.Util.makeHexColor(...data.color);
     editor.#content = data.value;
@@ -307,15 +325,15 @@ class FreeTextEditor extends _editor.AnnotationEditor {
     if (this.isEmpty()) {
       return null;
     }
-    const padding = FreeTextEditor._internalPadding * this.parent.scaleFactor;
+    const padding = FreeTextEditor._internalPadding * this.parentScale;
     const rect = this.getRect(padding, padding);
-    const color = _editor.AnnotationEditor._colorManager.convert(getComputedStyle(this.editorDiv).color);
+    const color = _editor.AnnotationEditor._colorManager.convert(this.isAttachedToDOM ? getComputedStyle(this.editorDiv).color : this.#color);
     return {
       annotationType: _util.AnnotationEditorType.FREETEXT,
       color,
       fontSize: this.#fontSize,
       value: this.#content,
-      pageIndex: this.parent.pageIndex,
+      pageIndex: this.pageIndex,
       rect,
       rotation: this.rotation
     };

+ 52 - 29
lib/display/editor/ink.js

@@ -110,7 +110,7 @@ class InkEditor extends _editor.AnnotationEditor {
   }
   #updateThickness(thickness) {
     const savedThickness = this.thickness;
-    this.parent.addCommands({
+    this.addCommands({
       cmd: () => {
         this.thickness = thickness;
         this.#fitToContent();
@@ -127,7 +127,7 @@ class InkEditor extends _editor.AnnotationEditor {
   }
   #updateColor(color) {
     const savedColor = this.color;
-    this.parent.addCommands({
+    this.addCommands({
       cmd: () => {
         this.color = color;
         this.#redraw();
@@ -145,7 +145,7 @@ class InkEditor extends _editor.AnnotationEditor {
   #updateOpacity(opacity) {
     opacity /= 100;
     const savedOpacity = this.opacity;
-    this.parent.addCommands({
+    this.addCommands({
       cmd: () => {
         this.opacity = opacity;
         this.#redraw();
@@ -189,6 +189,20 @@ class InkEditor extends _editor.AnnotationEditor {
     this.#observer = null;
     super.remove();
   }
+  setParent(parent) {
+    if (!this.parent && parent) {
+      this._uiManager.removeShouldRescale(this);
+    } else if (this.parent && parent === null) {
+      this._uiManager.addShouldRescale(this);
+    }
+    super.setParent(parent);
+  }
+  onScaleChanging() {
+    const [parentWidth, parentHeight] = this.parentDimensions;
+    const width = this.width * parentWidth;
+    const height = this.height * parentHeight;
+    this.setDimensions(width, height);
+  }
   enableEditMode() {
     if (this.#disableEditing || this.canvas === null) {
       return;
@@ -216,27 +230,34 @@ class InkEditor extends _editor.AnnotationEditor {
   }
   #getInitialBBox() {
     const {
-      width,
-      height,
-      rotation
-    } = this.parent.viewport;
-    switch (rotation) {
+      parentRotation,
+      parentDimensions: [width, height]
+    } = this;
+    switch (parentRotation) {
       case 90:
-        return [0, width, width, height];
+        return [0, height, height, width];
       case 180:
         return [width, height, width, height];
       case 270:
-        return [height, 0, width, height];
+        return [width, 0, height, width];
       default:
         return [0, 0, width, height];
     }
   }
   #setStroke() {
-    this.ctx.lineWidth = this.thickness * this.parent.scaleFactor / this.scaleFactor;
-    this.ctx.lineCap = "round";
-    this.ctx.lineJoin = "round";
-    this.ctx.miterLimit = 10;
-    this.ctx.strokeStyle = `${this.color}${(0, _tools.opacityToHex)(this.opacity)}`;
+    const {
+      ctx,
+      color,
+      opacity,
+      thickness,
+      parentScale,
+      scaleFactor
+    } = this;
+    ctx.lineWidth = thickness * parentScale / scaleFactor;
+    ctx.lineCap = "round";
+    ctx.lineJoin = "round";
+    ctx.miterLimit = 10;
+    ctx.strokeStyle = `${color}${(0, _tools.opacityToHex)(opacity)}`;
   }
   #startDrawing(x, y) {
     this.isEditing = true;
@@ -315,7 +336,7 @@ class InkEditor extends _editor.AnnotationEditor {
         this.#fitToContent();
       }
     };
-    this.parent.addCommands({
+    this.addCommands({
       cmd,
       undo,
       mustExec: true
@@ -351,7 +372,9 @@ class InkEditor extends _editor.AnnotationEditor {
     this.#fitToContent(true);
     this.parent.addInkEditorIfNeeded(true);
     this.parent.moveEditorInDOM(this);
-    this.div.focus();
+    this.div.focus({
+      preventScroll: true
+    });
   }
   focusin(event) {
     super.focusin(event);
@@ -392,7 +415,7 @@ class InkEditor extends _editor.AnnotationEditor {
     this.#stopDrawing(event.offsetX, event.offsetY);
     this.canvas.removeEventListener("pointerleave", this.#boundCanvasPointerleave);
     this.canvas.removeEventListener("pointermove", this.#boundCanvasPointermove);
-    this.parent.addToAnnotationStorage(this);
+    this.addToAnnotationStorage();
   }
   #createCanvas() {
     this.canvas = document.createElement("canvas");
@@ -435,7 +458,7 @@ class InkEditor extends _editor.AnnotationEditor {
     this.setDims(w, h);
     this.#createCanvas();
     if (this.width) {
-      const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions;
+      const [parentWidth, parentHeight] = this.parentDimensions;
       this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight);
       this.#isCanvasInitialized = true;
       this.#setCanvasDims();
@@ -454,7 +477,7 @@ class InkEditor extends _editor.AnnotationEditor {
     if (!this.#isCanvasInitialized) {
       return;
     }
-    const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions;
+    const [parentWidth, parentHeight] = this.parentDimensions;
     this.canvas.width = Math.ceil(this.width * parentWidth);
     this.canvas.height = Math.ceil(this.height * parentHeight);
     this.#updateTransform();
@@ -472,7 +495,7 @@ class InkEditor extends _editor.AnnotationEditor {
       height = Math.ceil(width / this.#aspectRatio);
       this.setDims(width, height);
     }
-    const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions;
+    const [parentWidth, parentHeight] = this.parentDimensions;
     this.width = width / parentWidth;
     this.height = height / parentHeight;
     if (this.#disableEditing) {
@@ -584,7 +607,7 @@ class InkEditor extends _editor.AnnotationEditor {
     return [xMin, yMin, xMax, yMax];
   }
   #getPadding() {
-    return this.#disableEditing ? Math.ceil(this.thickness * this.parent.scaleFactor) : 0;
+    return this.#disableEditing ? Math.ceil(this.thickness * this.parentScale) : 0;
   }
   #fitToContent(firstTime = false) {
     if (this.isEmpty()) {
@@ -600,7 +623,7 @@ class InkEditor extends _editor.AnnotationEditor {
     this.#baseHeight = Math.max(RESIZER_SIZE, bbox[3] - bbox[1]);
     const width = Math.ceil(padding + this.#baseWidth * this.scaleFactor);
     const height = Math.ceil(padding + this.#baseHeight * this.scaleFactor);
-    const [parentWidth, parentHeight] = this.parent.viewportBaseDimensions;
+    const [parentWidth, parentHeight] = this.parentDimensions;
     this.width = width / parentWidth;
     this.height = height / parentHeight;
     this.#aspectRatio = width / height;
@@ -629,15 +652,15 @@ class InkEditor extends _editor.AnnotationEditor {
       style.minHeight = `${Math.round(RESIZER_SIZE / this.#aspectRatio)}px`;
     }
   }
-  static deserialize(data, parent) {
-    const editor = super.deserialize(data, parent);
+  static deserialize(data, parent, uiManager) {
+    const editor = super.deserialize(data, parent, uiManager);
     editor.thickness = data.thickness;
     editor.color = _util.Util.makeHexColor(...data.color);
     editor.opacity = data.opacity;
-    const [pageWidth, pageHeight] = parent.pageDimensions;
+    const [pageWidth, pageHeight] = editor.pageDimensions;
     const width = editor.width * pageWidth;
     const height = editor.height * pageHeight;
-    const scaleFactor = parent.scaleFactor;
+    const scaleFactor = editor.parentScale;
     const padding = data.thickness / 2;
     editor.#aspectRatio = width / height;
     editor.#disableEditing = true;
@@ -682,8 +705,8 @@ class InkEditor extends _editor.AnnotationEditor {
       color,
       thickness: this.thickness,
       opacity: this.opacity,
-      paths: this.#serializePaths(this.scaleFactor / this.parent.scaleFactor, this.translationX, this.translationY, height),
-      pageIndex: this.parent.pageIndex,
+      paths: this.#serializePaths(this.scaleFactor / this.parentScale, this.translationX, this.translationY, height),
+      pageIndex: this.pageIndex,
       rect,
       rotation: this.rotation
     };

+ 51 - 9
lib/display/editor/tools.js

@@ -129,7 +129,9 @@ class KeyboardManager {
     this.buffer = [];
     this.callbacks = new Map();
     this.allKeys = new Set();
-    const isMac = KeyboardManager.platform.isMac;
+    const {
+      isMac
+    } = _util.FeatureTest.platform;
     for (const [keys, callback] of callbacks) {
       for (const key of keys) {
         const isMacKey = key.startsWith("mac+");
@@ -143,13 +145,6 @@ class KeyboardManager {
       }
     }
   }
-  static get platform() {
-    const platform = typeof navigator !== "undefined" ? navigator.platform : "";
-    return (0, _util.shadow)(this, "platform", {
-      isWin: platform.includes("Win"),
-      isMac: platform.includes("Mac")
-    });
-  }
   #serialize(event) {
     if (event.altKey) {
       this.buffer.push("alt");
@@ -217,9 +212,11 @@ class AnnotationEditorUIManager {
   #activeEditor = null;
   #allEditors = new Map();
   #allLayers = new Map();
+  #annotationStorage = null;
   #commandManager = new CommandManager();
   #currentPageIndex = 0;
   #editorTypes = null;
+  #editorsToRescale = new Set();
   #eventBus = null;
   #idManager = new IdManager();
   #isEnabled = false;
@@ -231,6 +228,8 @@ class AnnotationEditorUIManager {
   #boundKeydown = this.keydown.bind(this);
   #boundOnEditingAction = this.onEditingAction.bind(this);
   #boundOnPageChanging = this.onPageChanging.bind(this);
+  #boundOnScaleChanging = this.onScaleChanging.bind(this);
+  #boundOnRotationChanging = this.onRotationChanging.bind(this);
   #previousStates = {
     isEditing: false,
     isEmpty: true,
@@ -240,21 +239,31 @@ class AnnotationEditorUIManager {
   };
   #container = null;
   static _keyboardManager = new KeyboardManager([[["ctrl+a", "mac+meta+a"], AnnotationEditorUIManager.prototype.selectAll], [["ctrl+z", "mac+meta+z"], AnnotationEditorUIManager.prototype.undo], [["ctrl+y", "ctrl+shift+Z", "mac+meta+shift+Z"], AnnotationEditorUIManager.prototype.redo], [["Backspace", "alt+Backspace", "ctrl+Backspace", "shift+Backspace", "mac+Backspace", "mac+alt+Backspace", "mac+ctrl+Backspace", "Delete", "ctrl+Delete", "shift+Delete"], AnnotationEditorUIManager.prototype.delete], [["Escape", "mac+Escape"], AnnotationEditorUIManager.prototype.unselectAll]]);
-  constructor(container, eventBus) {
+  constructor(container, eventBus, annotationStorage) {
     this.#container = container;
     this.#eventBus = eventBus;
     this.#eventBus._on("editingaction", this.#boundOnEditingAction);
     this.#eventBus._on("pagechanging", this.#boundOnPageChanging);
+    this.#eventBus._on("scalechanging", this.#boundOnScaleChanging);
+    this.#eventBus._on("rotationchanging", this.#boundOnRotationChanging);
+    this.#annotationStorage = annotationStorage;
+    this.viewParameters = {
+      realScale: _display_utils.PixelsPerInch.PDF_TO_CSS_UNITS,
+      rotation: 0
+    };
   }
   destroy() {
     this.#removeKeyboardManager();
     this.#eventBus._off("editingaction", this.#boundOnEditingAction);
     this.#eventBus._off("pagechanging", this.#boundOnPageChanging);
+    this.#eventBus._off("scalechanging", this.#boundOnScaleChanging);
+    this.#eventBus._off("rotationchanging", this.#boundOnRotationChanging);
     for (const layer of this.#allLayers.values()) {
       layer.destroy();
     }
     this.#allLayers.clear();
     this.#allEditors.clear();
+    this.#editorsToRescale.clear();
     this.#activeEditor = null;
     this.#selectedEditors.clear();
     this.#commandManager.destroy();
@@ -267,6 +276,32 @@ class AnnotationEditorUIManager {
   focusMainContainer() {
     this.#container.focus();
   }
+  addShouldRescale(editor) {
+    this.#editorsToRescale.add(editor);
+  }
+  removeShouldRescale(editor) {
+    this.#editorsToRescale.delete(editor);
+  }
+  onScaleChanging({
+    scale
+  }) {
+    this.commitOrRemove();
+    this.viewParameters.realScale = scale * _display_utils.PixelsPerInch.PDF_TO_CSS_UNITS;
+    for (const editor of this.#editorsToRescale) {
+      editor.onScaleChanging();
+    }
+  }
+  onRotationChanging({
+    pagesRotation
+  }) {
+    this.commitOrRemove();
+    this.viewParameters.rotation = pagesRotation;
+  }
+  addToAnnotationStorage(editor) {
+    if (!editor.isEmpty() && this.#annotationStorage && !this.#annotationStorage.has(editor.id)) {
+      this.#annotationStorage.setValue(editor.id, editor);
+    }
+  }
   #addKeyboardManager() {
     this.#container.addEventListener("keydown", this.#boundKeydown);
   }
@@ -408,6 +443,12 @@ class AnnotationEditorUIManager {
   getId() {
     return this.#idManager.getId();
   }
+  get currentLayer() {
+    return this.#allLayers.get(this.#currentPageIndex);
+  }
+  get currentPageIndex() {
+    return this.#currentPageIndex;
+  }
   addLayer(layer) {
     this.#allLayers.set(layer.pageIndex, layer);
     if (this.#isEnabled) {
@@ -487,6 +528,7 @@ class AnnotationEditorUIManager {
   removeEditor(editor) {
     this.#allEditors.delete(editor.id);
     this.unselect(editor);
+    this.#annotationStorage?.remove(editor.id);
   }
   #addEditorToLayer(editor) {
     const layer = this.#allLayers.get(editor.pageIndex);

+ 1 - 1
lib/display/fetch_stream.js

@@ -42,7 +42,7 @@ function createHeaders(httpHeaders) {
   const headers = new Headers();
   for (const property in httpHeaders) {
     const value = httpHeaders[property];
-    if (typeof value === "undefined") {
+    if (value === undefined) {
       continue;
     }
     headers.append(property, value);

+ 4 - 6
lib/display/font_loader.js

@@ -26,6 +26,7 @@ Object.defineProperty(exports, "__esModule", {
 });
 exports.FontLoader = exports.FontFaceObject = void 0;
 var _util = require("../shared/util.js");
+var _is_node = require("../shared/is_node.js");
 class FontLoader {
   constructor({
     onUnsupportedFeature,
@@ -101,13 +102,10 @@ class FontLoader {
   }
   get isSyncFontLoadingSupported() {
     let supported = false;
-    if (typeof navigator === "undefined") {
+    if (_is_node.isNodeJS) {
+      supported = true;
+    } else if (typeof navigator !== "undefined" && /Mozilla\/5.0.*?rv:\d+.*? Gecko/.test(navigator.userAgent)) {
       supported = true;
-    } else {
-      const m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);
-      if (m?.[1] >= 14) {
-        supported = true;
-      }
     }
     return (0, _util.shadow)(this, "isSyncFontLoadingSupported", supported);
   }

+ 1 - 1
lib/display/network.js

@@ -73,7 +73,7 @@ class NetworkManager {
     xhr.withCredentials = this.withCredentials;
     for (const property in this.httpHeaders) {
       const value = this.httpHeaders[property];
-      if (typeof value === "undefined") {
+      if (value === undefined) {
         continue;
       }
       xhr.setRequestHeader(property, value);

+ 1 - 1
lib/display/node_stream.js

@@ -303,7 +303,7 @@ class PDFNodeStreamRangeReader extends BaseRangeReader {
     this._httpHeaders = {};
     for (const property in stream.httpHeaders) {
       const value = stream.httpHeaders[property];
-      if (typeof value === "undefined") {
+      if (value === undefined) {
         continue;
       }
       this._httpHeaders[property] = value;

+ 160 - 107
lib/display/text_layer.js

@@ -26,26 +26,42 @@ Object.defineProperty(exports, "__esModule", {
 });
 exports.TextLayerRenderTask = void 0;
 exports.renderTextLayer = renderTextLayer;
+exports.updateTextLayer = updateTextLayer;
 var _util = require("../shared/util.js");
 var _display_utils = require("./display_utils.js");
 const MAX_TEXT_DIVS_TO_RENDER = 100000;
 const DEFAULT_FONT_SIZE = 30;
 const DEFAULT_FONT_ASCENT = 0.8;
 const ascentCache = new Map();
-function getAscent(fontFamily, ctx) {
+function getCtx(size, isOffscreenCanvasSupported) {
+  let ctx;
+  if (isOffscreenCanvasSupported && _util.FeatureTest.isOffscreenCanvasSupported) {
+    ctx = new OffscreenCanvas(size, size).getContext("2d", {
+      alpha: false
+    });
+  } else {
+    const canvas = document.createElement("canvas");
+    canvas.width = canvas.height = size;
+    ctx = canvas.getContext("2d", {
+      alpha: false
+    });
+  }
+  return ctx;
+}
+function getAscent(fontFamily, isOffscreenCanvasSupported) {
   const cachedAscent = ascentCache.get(fontFamily);
   if (cachedAscent) {
     return cachedAscent;
   }
-  ctx.save();
+  const ctx = getCtx(DEFAULT_FONT_SIZE, isOffscreenCanvasSupported);
   ctx.font = `${DEFAULT_FONT_SIZE}px ${fontFamily}`;
   const metrics = ctx.measureText("");
   let ascent = metrics.fontBoundingBoxAscent;
   let descent = Math.abs(metrics.fontBoundingBoxDescent);
   if (ascent) {
-    ctx.restore();
     const ratio = ascent / (ascent + descent);
     ascentCache.set(fontFamily, ratio);
+    ctx.canvas.width = ctx.canvas.height = 0;
     return ratio;
   }
   ctx.strokeStyle = "red";
@@ -69,7 +85,7 @@ function getAscent(fontFamily, ctx) {
       break;
     }
   }
-  ctx.restore();
+  ctx.canvas.width = ctx.canvas.height = 0;
   if (ascent) {
     const ratio = ascent / (ascent + descent);
     ascentCache.set(fontFamily, ratio);
@@ -78,7 +94,7 @@ function getAscent(fontFamily, ctx) {
   ascentCache.set(fontFamily, DEFAULT_FONT_ASCENT);
   return DEFAULT_FONT_ASCENT;
 }
-function appendText(task, geom, styles, ctx) {
+function appendText(task, geom, styles) {
   const textDiv = document.createElement("span");
   const textDivProperties = {
     angle: 0,
@@ -88,14 +104,14 @@ function appendText(task, geom, styles, ctx) {
     fontSize: 0
   };
   task._textDivs.push(textDiv);
-  const tx = _util.Util.transform(task._viewport.transform, geom.transform);
+  const tx = _util.Util.transform(task._transform, geom.transform);
   let angle = Math.atan2(tx[1], tx[0]);
   const style = styles[geom.fontName];
   if (style.vertical) {
     angle += Math.PI / 2;
   }
   const fontHeight = Math.hypot(tx[2], tx[3]);
-  const fontAscent = fontHeight * getAscent(style.fontFamily, ctx);
+  const fontAscent = fontHeight * getAscent(style.fontFamily, task._isOffscreenCanvasSupported);
   let left, top;
   if (angle === 0) {
     left = tx[4];
@@ -104,10 +120,17 @@ function appendText(task, geom, styles, ctx) {
     left = tx[4] + fontAscent * Math.sin(angle);
     top = tx[5] - fontAscent * Math.cos(angle);
   }
-  textDiv.style.left = `${left}px`;
-  textDiv.style.top = `${top}px`;
-  textDiv.style.fontSize = `${fontHeight}px`;
-  textDiv.style.fontFamily = style.fontFamily;
+  const scaleFactorStr = "calc(var(--scale-factor)*";
+  const divStyle = textDiv.style;
+  if (task._container === task._rootContainer) {
+    divStyle.left = `${(100 * left / task._pageWidth).toFixed(2)}%`;
+    divStyle.top = `${(100 * top / task._pageHeight).toFixed(2)}%`;
+  } else {
+    divStyle.left = `${scaleFactorStr}${left.toFixed(2)}px)`;
+    divStyle.top = `${scaleFactorStr}${top.toFixed(2)}px)`;
+  }
+  divStyle.fontSize = `${scaleFactorStr}${fontHeight.toFixed(2)}px)`;
+  divStyle.fontFamily = style.fontFamily;
   textDivProperties.fontSize = fontHeight;
   textDiv.setAttribute("role", "presentation");
   textDiv.textContent = geom.str;
@@ -129,17 +152,53 @@ function appendText(task, geom, styles, ctx) {
     }
   }
   if (shouldScaleText) {
-    if (style.vertical) {
-      textDivProperties.canvasWidth = geom.height * task._viewport.scale;
-    } else {
-      textDivProperties.canvasWidth = geom.width * task._viewport.scale;
-    }
+    textDivProperties.canvasWidth = style.vertical ? geom.height : geom.width;
   }
   task._textDivProperties.set(textDiv, textDivProperties);
-  if (task._textContentStream) {
+  if (task._isReadableStream) {
     task._layoutText(textDiv);
   }
 }
+function layout(params) {
+  const {
+    div,
+    scale,
+    properties,
+    ctx,
+    prevFontSize,
+    prevFontFamily
+  } = params;
+  const {
+    style
+  } = div;
+  let transform = "";
+  if (properties.canvasWidth !== 0 && properties.hasText) {
+    const {
+      fontFamily
+    } = style;
+    const {
+      canvasWidth,
+      fontSize
+    } = properties;
+    if (prevFontSize !== fontSize || prevFontFamily !== fontFamily) {
+      ctx.font = `${fontSize * scale}px ${fontFamily}`;
+      params.prevFontSize = fontSize;
+      params.prevFontFamily = fontFamily;
+    }
+    const {
+      width
+    } = ctx.measureText(div.textContent);
+    if (width > 0) {
+      transform = `scaleX(${canvasWidth * scale / width})`;
+    }
+  }
+  if (properties.angle !== 0) {
+    transform = `rotate(${properties.angle}deg) ${transform}`;
+  }
+  if (transform.length > 0) {
+    style.transform = transform;
+  }
+}
 function render(task) {
   if (task._canceled) {
     return;
@@ -148,52 +207,56 @@ function render(task) {
   const capability = task._capability;
   const textDivsLength = textDivs.length;
   if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {
-    task._renderingDone = true;
     capability.resolve();
     return;
   }
-  if (!task._textContentStream) {
+  if (!task._isReadableStream) {
     for (const textDiv of textDivs) {
       task._layoutText(textDiv);
     }
   }
-  task._renderingDone = true;
   capability.resolve();
 }
 class TextLayerRenderTask {
   constructor({
-    textContent,
-    textContentStream,
+    textContentSource,
     container,
     viewport,
     textDivs,
-    textContentItemsStr
+    textDivProperties,
+    textContentItemsStr,
+    isOffscreenCanvasSupported
   }) {
-    this._textContent = textContent;
-    this._textContentStream = textContentStream;
-    this._container = container;
-    this._document = container.ownerDocument;
-    this._viewport = viewport;
+    this._textContentSource = textContentSource;
+    this._isReadableStream = textContentSource instanceof ReadableStream;
+    this._container = this._rootContainer = container;
     this._textDivs = textDivs || [];
     this._textContentItemsStr = textContentItemsStr || [];
     this._fontInspectorEnabled = !!globalThis.FontInspector?.enabled;
     this._reader = null;
-    this._layoutTextLastFontSize = null;
-    this._layoutTextLastFontFamily = null;
-    this._layoutTextCtx = null;
-    this._textDivProperties = new WeakMap();
-    this._renderingDone = false;
+    this._textDivProperties = textDivProperties || new WeakMap();
     this._canceled = false;
     this._capability = (0, _util.createPromiseCapability)();
-    this._renderTimer = null;
-    this._devicePixelRatio = globalThis.devicePixelRatio || 1;
+    this._layoutTextParams = {
+      prevFontSize: null,
+      prevFontFamily: null,
+      div: null,
+      scale: viewport.scale * (globalThis.devicePixelRatio || 1),
+      properties: null,
+      ctx: getCtx(0, isOffscreenCanvasSupported)
+    };
+    const {
+      pageWidth,
+      pageHeight,
+      pageX,
+      pageY
+    } = viewport.rawDims;
+    this._transform = [1, 0, 0, -1, -pageX, pageY + pageHeight];
+    this._pageWidth = pageWidth;
+    this._pageHeight = pageHeight;
+    (0, _display_utils.setLayerDimensions)(container, viewport);
     this._capability.promise.finally(() => {
-      this._textDivProperties = null;
-      if (this._layoutTextCtx) {
-        this._layoutTextCtx.canvas.width = 0;
-        this._layoutTextCtx.canvas.height = 0;
-        this._layoutTextCtx = null;
-      }
+      this._layoutTextParams = null;
     }).catch(() => {});
   }
   get promise() {
@@ -205,11 +268,7 @@ class TextLayerRenderTask {
       this._reader.cancel(new _util.AbortException("TextLayer task cancelled.")).catch(() => {});
       this._reader = null;
     }
-    if (this._renderTimer !== null) {
-      clearTimeout(this._renderTimer);
-      this._renderTimer = null;
-    }
-    this._capability.reject(new Error("TextLayer task cancelled."));
+    this._capability.reject(new _util.AbortException("TextLayer task cancelled."));
   }
   _processItems(items, styleCache) {
     for (const item of items) {
@@ -228,37 +287,13 @@ class TextLayerRenderTask {
         continue;
       }
       this._textContentItemsStr.push(item.str);
-      appendText(this, item, styleCache, this._layoutTextCtx);
+      appendText(this, item, styleCache);
     }
   }
   _layoutText(textDiv) {
-    const textDivProperties = this._textDivProperties.get(textDiv);
-    let transform = "";
-    if (textDivProperties.canvasWidth !== 0 && textDivProperties.hasText) {
-      const {
-        fontFamily
-      } = textDiv.style;
-      const {
-        fontSize
-      } = textDivProperties;
-      if (fontSize !== this._layoutTextLastFontSize || fontFamily !== this._layoutTextLastFontFamily) {
-        this._layoutTextCtx.font = `${fontSize * this._devicePixelRatio}px ${fontFamily}`;
-        this._layoutTextLastFontSize = fontSize;
-        this._layoutTextLastFontFamily = fontFamily;
-      }
-      const {
-        width
-      } = this._layoutTextCtx.measureText(textDiv.textContent);
-      if (width > 0) {
-        transform = `scaleX(${this._devicePixelRatio * textDivProperties.canvasWidth / width})`;
-      }
-    }
-    if (textDivProperties.angle !== 0) {
-      transform = `rotate(${textDivProperties.angle}deg) ${transform}`;
-    }
-    if (transform.length > 0) {
-      textDiv.style.transform = transform;
-    }
+    const textDivProperties = this._layoutTextParams.properties = this._textDivProperties.get(textDiv);
+    this._layoutTextParams.div = textDiv;
+    layout(this._layoutTextParams);
     if (textDivProperties.hasText) {
       this._container.append(textDiv);
     }
@@ -268,20 +303,10 @@ class TextLayerRenderTask {
       this._container.append(br);
     }
   }
-  _render(timeout = 0) {
+  _render() {
     const capability = (0, _util.createPromiseCapability)();
     let styleCache = Object.create(null);
-    const canvas = this._document.createElement("canvas");
-    canvas.height = canvas.width = DEFAULT_FONT_SIZE;
-    this._layoutTextCtx = canvas.getContext("2d", {
-      alpha: false
-    });
-    if (this._textContent) {
-      const textItems = this._textContent.items;
-      const textStyles = this._textContent.styles;
-      this._processItems(textItems, textStyles);
-      capability.resolve();
-    } else if (this._textContentStream) {
+    if (this._isReadableStream) {
       const pump = () => {
         this._reader.read().then(({
           value,
@@ -296,35 +321,63 @@ class TextLayerRenderTask {
           pump();
         }, capability.reject);
       };
-      this._reader = this._textContentStream.getReader();
+      this._reader = this._textContentSource.getReader();
       pump();
+    } else if (this._textContentSource) {
+      const {
+        items,
+        styles
+      } = this._textContentSource;
+      this._processItems(items, styles);
+      capability.resolve();
     } else {
-      throw new Error('Neither "textContent" nor "textContentStream" parameters specified.');
+      throw new Error('No "textContentSource" parameter specified.');
     }
     capability.promise.then(() => {
       styleCache = null;
-      if (!timeout) {
-        render(this);
-      } else {
-        (0, _display_utils.deprecated)("The TextLayerRender `timeout` parameter will be removed in the " + "future, since streaming of textContent has made it obsolete.");
-        this._renderTimer = setTimeout(() => {
-          render(this);
-          this._renderTimer = null;
-        }, timeout);
-      }
+      render(this);
     }, this._capability.reject);
   }
 }
 exports.TextLayerRenderTask = TextLayerRenderTask;
-function renderTextLayer(renderParameters) {
-  const task = new TextLayerRenderTask({
-    textContent: renderParameters.textContent,
-    textContentStream: renderParameters.textContentStream,
-    container: renderParameters.container,
-    viewport: renderParameters.viewport,
-    textDivs: renderParameters.textDivs,
-    textContentItemsStr: renderParameters.textContentItemsStr
-  });
-  task._render(renderParameters.timeout);
+function renderTextLayer(params) {
+  if (!params.textContentSource && (params.textContent || params.textContentStream)) {
+    (0, _display_utils.deprecated)("The TextLayerRender `textContent`/`textContentStream` parameters " + "will be removed in the future, please use `textContentSource` instead.");
+    params.textContentSource = params.textContent || params.textContentStream;
+  }
+  const task = new TextLayerRenderTask(params);
+  task._render();
   return task;
+}
+function updateTextLayer({
+  container,
+  viewport,
+  textDivs,
+  textDivProperties,
+  isOffscreenCanvasSupported,
+  mustRotate = true,
+  mustRescale = true
+}) {
+  if (mustRotate) {
+    (0, _display_utils.setLayerDimensions)(container, {
+      rotation: viewport.rotation
+    });
+  }
+  if (mustRescale) {
+    const ctx = getCtx(0, isOffscreenCanvasSupported);
+    const scale = viewport.scale * (globalThis.devicePixelRatio || 1);
+    const params = {
+      prevFontSize: null,
+      prevFontFamily: null,
+      div: null,
+      scale,
+      properties: null,
+      ctx
+    };
+    for (const div of textDivs) {
+      params.properties = textDivProperties.get(div);
+      params.div = div;
+      layout(params);
+    }
+  }
 }

+ 27 - 3
lib/pdf.js

@@ -24,6 +24,12 @@
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
+Object.defineProperty(exports, "AbortException", {
+  enumerable: true,
+  get: function () {
+    return _util.AbortException;
+  }
+});
 Object.defineProperty(exports, "AnnotationEditorLayer", {
   enumerable: true,
   get: function () {
@@ -210,6 +216,12 @@ Object.defineProperty(exports, "getXfaPageViewport", {
     return _display_utils.getXfaPageViewport;
   }
 });
+Object.defineProperty(exports, "isDataScheme", {
+  enumerable: true,
+  get: function () {
+    return _display_utils.isDataScheme;
+  }
+});
 Object.defineProperty(exports, "isPdfFile", {
   enumerable: true,
   get: function () {
@@ -228,12 +240,24 @@ Object.defineProperty(exports, "renderTextLayer", {
     return _text_layer.renderTextLayer;
   }
 });
+Object.defineProperty(exports, "setLayerDimensions", {
+  enumerable: true,
+  get: function () {
+    return _display_utils.setLayerDimensions;
+  }
+});
 Object.defineProperty(exports, "shadow", {
   enumerable: true,
   get: function () {
     return _util.shadow;
   }
 });
+Object.defineProperty(exports, "updateTextLayer", {
+  enumerable: true,
+  get: function () {
+    return _text_layer.updateTextLayer;
+  }
+});
 Object.defineProperty(exports, "version", {
   enumerable: true,
   get: function () {
@@ -243,16 +267,16 @@ Object.defineProperty(exports, "version", {
 var _util = require("./shared/util.js");
 var _api = require("./display/api.js");
 var _display_utils = require("./display/display_utils.js");
+var _text_layer = require("./display/text_layer.js");
 var _annotation_editor_layer = require("./display/editor/annotation_editor_layer.js");
 var _tools = require("./display/editor/tools.js");
 var _annotation_layer = require("./display/annotation_layer.js");
 var _worker_options = require("./display/worker_options.js");
 var _is_node = require("./shared/is_node.js");
-var _text_layer = require("./display/text_layer.js");
 var _svg = require("./display/svg.js");
 var _xfa_layer = require("./display/xfa_layer.js");
-const pdfjsVersion = '3.1.81';
-const pdfjsBuild = '0766898d5';
+const pdfjsVersion = '3.2.146';
+const pdfjsBuild = '3fd2a3548';
 {
   if (_is_node.isNodeJS) {
     const {

Файловите разлики са ограничени, защото са твърде много
+ 2 - 2
lib/pdf.sandbox.js


+ 2 - 2
lib/pdf.worker.js

@@ -31,5 +31,5 @@ Object.defineProperty(exports, "WorkerMessageHandler", {
   }
 });
 var _worker = require("./core/worker.js");
-const pdfjsVersion = '3.1.81';
-const pdfjsBuild = '0766898d5';
+const pdfjsVersion = '3.2.146';
+const pdfjsBuild = '3fd2a3548';

+ 12 - 0
lib/shared/util.js

@@ -641,6 +641,18 @@ class FeatureTest {
   static get isOffscreenCanvasSupported() {
     return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined");
   }
+  static get platform() {
+    if (typeof navigator === "undefined") {
+      return shadow(this, "platform", {
+        isWin: false,
+        isMac: false
+      });
+    }
+    return shadow(this, "platform", {
+      isWin: navigator.platform.includes("Win"),
+      isMac: navigator.platform.includes("Mac")
+    });
+  }
 }
 exports.FeatureTest = FeatureTest;
 const hexNumbers = [...Array(256).keys()].map(n => n.toString(16).padStart(2, "0"));

+ 1 - 0
lib/test/unit/api_spec.js

@@ -2073,6 +2073,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)).toEqual(true);
         expect(reason instanceof _display_utils.RenderingCancelledException).toEqual(true);
         expect(reason.message).toEqual("Rendering cancelled, page 1");
         expect(reason.type).toEqual("canvas");
+        expect(reason.extraDelay).toEqual(0);
       }
       CanvasFactory.destroy(canvasAndCtx);
     });

+ 20 - 0
lib/test/unit/pdf_find_controller_spec.js

@@ -576,4 +576,24 @@ describe("pdf_find_controller", function () {
       pageMatchesLength: [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
     });
   });
+  it("performs a search in a text with some Katakana at the end of a line", async function () {
+    const {
+      eventBus,
+      pdfFindController
+    } = await initPdfFindController("issue15759.pdf");
+    await testSearch({
+      eventBus,
+      pdfFindController,
+      state: {
+        query: "ソレノイド"
+      },
+      matchesPerPage: [1],
+      selectedMatch: {
+        pageIndex: 0,
+        matchIndex: 0
+      },
+      pageMatches: [[6]],
+      pageMatchesLength: [[5]]
+    });
+  });
 });

+ 11 - 3
lib/test/unit/scripting_spec.js

@@ -247,6 +247,14 @@ describe("Scripting", function () {
         expect(value).toEqual("Decimal number: +  1.235");
         value = await myeval(`util.printf("Decimal number: %,0.2f", -12.34567)`);
         expect(value).toEqual("Decimal number: -12.35");
+        value = await myeval(`util.printf("Decimal number: %,0.0f", 4.95)`);
+        expect(value).toEqual("Decimal number: 5");
+        value = await myeval(`util.printf("Decimal number: %,0.0f", 4.49)`);
+        expect(value).toEqual("Decimal number: 4");
+        value = await myeval(`util.printf("Decimal number: %,0.0f", -4.95)`);
+        expect(value).toEqual("Decimal number: -5");
+        value = await myeval(`util.printf("Decimal number: %,0.0f", -4.49)`);
+        expect(value).toEqual("Decimal number: -4");
       });
       it("should print a string with no argument", async () => {
         const value = await myeval(`util.printf("hello world")`);
@@ -294,7 +302,7 @@ describe("Scripting", function () {
       expect(send_queue.has(refId)).toEqual(true);
       expect(send_queue.get(refId)).toEqual({
         id: refId,
-        value: "123"
+        value: 123
       });
     });
     it("should trigger a Keystroke event and invalidate it", async () => {
@@ -697,7 +705,7 @@ describe("Scripting", function () {
         expect(send_queue.get(refId)).toEqual({
           id: refId,
           siblings: null,
-          value: "123456.789",
+          value: 123456.789,
           formattedValue: null
         });
       });
@@ -860,7 +868,7 @@ describe("Scripting", function () {
         expect(send_queue.get(refId)).toEqual({
           id: refId,
           siblings: null,
-          value: "321",
+          value: 321,
           formattedValue: null
         });
       });

+ 1 - 1
lib/test/unit/testreporter.js

@@ -57,7 +57,7 @@ const TestReporter = function (browser) {
       status,
       description
     };
-    if (typeof error !== "undefined") {
+    if (error !== undefined) {
       message.error = error;
     }
     send("/submit_task_results", message);

+ 3 - 3
lib/test/unit/text_layer_spec.js

@@ -28,15 +28,15 @@ var _is_node = require("../../shared/is_node.js");
 describe("textLayer", function () {
   it("creates textLayer from ReadableStream", async function () {
     if (_is_node.isNodeJS) {
-      pending("document.createDocumentFragment is not supported in Node.js.");
+      pending("document.createElement is not supported in Node.js.");
     }
     const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("basicapi.pdf"));
     const pdfDocument = await loadingTask.promise;
     const page = await pdfDocument.getPage(1);
     const textContentItemsStr = [];
     const textLayerRenderTask = (0, _text_layer.renderTextLayer)({
-      textContentStream: page.streamTextContent(),
-      container: document.createDocumentFragment(),
+      textContentSource: page.streamTextContent(),
+      container: document.createElement("div"),
       viewport: page.getViewport(),
       textContentItemsStr
     });

+ 13 - 18
lib/web/annotation_editor_layer_builder.js

@@ -32,7 +32,6 @@ class AnnotationEditorLayerBuilder {
   constructor(options) {
     this.pageDiv = options.pageDiv;
     this.pdfPage = options.pdfPage;
-    this.annotationStorage = options.annotationStorage || null;
     this.accessibilityManager = options.accessibilityManager;
     this.l10n = options.l10n || _l10n_utils.NullL10n;
     this.annotationEditorLayer = null;
@@ -57,22 +56,21 @@ class AnnotationEditorLayerBuilder {
       this.show();
       return;
     }
-    this.div = document.createElement("div");
-    this.div.className = "annotationEditorLayer";
-    this.div.tabIndex = 0;
-    this.pageDiv.append(this.div);
+    const div = this.div = document.createElement("div");
+    div.className = "annotationEditorLayer";
+    div.tabIndex = 0;
+    this.pageDiv.append(div);
     this.annotationEditorLayer = new _pdf.AnnotationEditorLayer({
       uiManager: this.#uiManager,
-      div: this.div,
-      annotationStorage: this.annotationStorage,
+      div,
       accessibilityManager: this.accessibilityManager,
-      pageIndex: this.pdfPage._pageIndex,
+      pageIndex: this.pdfPage.pageNumber - 1,
       l10n: this.l10n,
       viewport: clonedViewport
     });
     const parameters = {
       viewport: clonedViewport,
-      div: this.div,
+      div,
       annotations: null,
       intent
     };
@@ -80,7 +78,12 @@ class AnnotationEditorLayerBuilder {
   }
   cancel() {
     this._cancelled = true;
-    this.destroy();
+    if (!this.div) {
+      return;
+    }
+    this.pageDiv = null;
+    this.annotationEditorLayer.destroy();
+    this.div.remove();
   }
   hide() {
     if (!this.div) {
@@ -94,13 +97,5 @@ class AnnotationEditorLayerBuilder {
     }
     this.div.hidden = false;
   }
-  destroy() {
-    if (!this.div) {
-      return;
-    }
-    this.pageDiv = null;
-    this.annotationEditorLayer.destroy();
-    this.div.remove();
-  }
 }
 exports.AnnotationEditorLayerBuilder = AnnotationEditorLayerBuilder;

+ 37 - 27
lib/web/annotation_layer_builder.js

@@ -29,6 +29,7 @@ var _pdf = require("../pdf");
 var _l10n_utils = require("./l10n_utils.js");
 var _ui_utils = require("./ui_utils.js");
 class AnnotationLayerBuilder {
+  #numAnnotations = 0;
   #onPresentationModeChanged = null;
   constructor({
     pageDiv,
@@ -42,7 +43,6 @@ class AnnotationLayerBuilder {
     enableScripting = false,
     hasJSActionsPromise = null,
     fieldObjectsPromise = null,
-    mouseState = null,
     annotationCanvasMap = null,
     accessibilityManager = null
   }) {
@@ -55,9 +55,8 @@ class AnnotationLayerBuilder {
     this.l10n = l10n;
     this.annotationStorage = annotationStorage;
     this.enableScripting = enableScripting;
-    this._hasJSActionsPromise = hasJSActionsPromise;
-    this._fieldObjectsPromise = fieldObjectsPromise;
-    this._mouseState = mouseState;
+    this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false);
+    this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);
     this._annotationCanvasMap = annotationCanvasMap;
     this._accessibilityManager = accessibilityManager;
     this.div = null;
@@ -65,13 +64,34 @@ class AnnotationLayerBuilder {
     this._eventBus = linkService.eventBus;
   }
   async render(viewport, intent = "display") {
-    const [annotations, hasJSActions = false, fieldObjects = null] = await Promise.all([this.pdfPage.getAnnotations({
+    if (this.div) {
+      if (this._cancelled || this.#numAnnotations === 0) {
+        return;
+      }
+      _pdf.AnnotationLayer.update({
+        viewport: viewport.clone({
+          dontFlip: true
+        }),
+        div: this.div,
+        annotationCanvasMap: this._annotationCanvasMap
+      });
+      return;
+    }
+    const [annotations, hasJSActions, fieldObjects] = await Promise.all([this.pdfPage.getAnnotations({
       intent
     }), this._hasJSActionsPromise, this._fieldObjectsPromise]);
-    if (this._cancelled || annotations.length === 0) {
+    if (this._cancelled) {
       return;
     }
-    const parameters = {
+    this.#numAnnotations = annotations.length;
+    this.div = document.createElement("div");
+    this.div.className = "annotationLayer";
+    this.pageDiv.append(this.div);
+    if (this.#numAnnotations === 0) {
+      this.hide();
+      return;
+    }
+    _pdf.AnnotationLayer.render({
       viewport: viewport.clone({
         dontFlip: true
       }),
@@ -86,28 +106,18 @@ class AnnotationLayerBuilder {
       enableScripting: this.enableScripting,
       hasJSActions,
       fieldObjects,
-      mouseState: this._mouseState,
       annotationCanvasMap: this._annotationCanvasMap,
       accessibilityManager: this._accessibilityManager
-    };
-    if (this.div) {
-      _pdf.AnnotationLayer.update(parameters);
-    } else {
-      this.div = document.createElement("div");
-      this.div.className = "annotationLayer";
-      this.pageDiv.append(this.div);
-      parameters.div = this.div;
-      _pdf.AnnotationLayer.render(parameters);
-      this.l10n.translate(this.div);
-      if (this.linkService.isInPresentationMode) {
-        this.#updatePresentationModeState(_ui_utils.PresentationModeState.FULLSCREEN);
-      }
-      if (!this.#onPresentationModeChanged) {
-        this.#onPresentationModeChanged = evt => {
-          this.#updatePresentationModeState(evt.state);
-        };
-        this._eventBus?._on("presentationmodechanged", this.#onPresentationModeChanged);
-      }
+    });
+    this.l10n.translate(this.div);
+    if (this.linkService.isInPresentationMode) {
+      this.#updatePresentationModeState(_ui_utils.PresentationModeState.FULLSCREEN);
+    }
+    if (!this.#onPresentationModeChanged) {
+      this.#onPresentationModeChanged = evt => {
+        this.#updatePresentationModeState(evt.state);
+      };
+      this._eventBus?._on("presentationmodechanged", this.#onPresentationModeChanged);
     }
   }
   cancel() {

+ 167 - 176
lib/web/app.js

@@ -64,8 +64,6 @@ const ViewerCssTheme = {
   LIGHT: 1,
   DARK: 2
 };
-const KNOWN_VERSIONS = ["1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "2.0", "2.1", "2.2", "2.3"];
-const KNOWN_GENERATORS = ["acrobat distiller", "acrobat pdfwriter", "adobe livecycle", "adobe pdf library", "adobe photoshop", "ghostscript", "tcpdf", "cairo", "dvipdfm", "dvips", "pdftex", "pdfkit", "itext", "prince", "quarkxpress", "mac os x", "microsoft", "openoffice", "oracle", "luradocument", "pdf-xchange", "antenna house", "aspose.cells", "fpdf"];
 class DefaultExternalServices {
   constructor() {
     throw new Error("Cannot initialize DefaultExternalServices.");
@@ -74,7 +72,7 @@ class DefaultExternalServices {
   static updateFindMatchesCount(data) {}
   static initPassiveLoading(callbacks) {}
   static reportTelemetry(data) {}
-  static createDownloadManager(options) {
+  static createDownloadManager() {
     throw new Error("Not implemented: createDownloadManager");
   }
   static createPreferences() {
@@ -149,7 +147,6 @@ const PDFViewerApplication = {
   _contentDispositionFilename: null,
   _contentLength: null,
   _saveInProgress: false,
-  _docStats: null,
   _wheelUnusedTicks: 0,
   _PDFBug: null,
   _hasAnnotationEditors: false,
@@ -352,6 +349,7 @@ const PDFViewerApplication = {
       imageResourcesPath: _app_options.AppOptions.get("imageResourcesPath"),
       enablePrintAutoRotate: _app_options.AppOptions.get("enablePrintAutoRotate"),
       useOnlyCssZoom: _app_options.AppOptions.get("useOnlyCssZoom"),
+      isOffscreenCanvasSupported: _app_options.AppOptions.get("isOffscreenCanvasSupported"),
       maxCanvasPixels: _app_options.AppOptions.get("maxCanvasPixels"),
       enablePermissions: _app_options.AppOptions.get("enablePermissions"),
       pageColors
@@ -359,15 +357,17 @@ const PDFViewerApplication = {
     pdfRenderingQueue.setViewer(this.pdfViewer);
     pdfLinkService.setViewer(this.pdfViewer);
     pdfScriptingManager.setViewer(this.pdfViewer);
-    this.pdfThumbnailViewer = new _pdf_thumbnail_viewer.PDFThumbnailViewer({
-      container: appConfig.sidebar.thumbnailView,
-      eventBus,
-      renderingQueue: pdfRenderingQueue,
-      linkService: pdfLinkService,
-      l10n: this.l10n,
-      pageColors
-    });
-    pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
+    if (appConfig.sidebar?.thumbnailView) {
+      this.pdfThumbnailViewer = new _pdf_thumbnail_viewer.PDFThumbnailViewer({
+        container: appConfig.sidebar.thumbnailView,
+        eventBus,
+        renderingQueue: pdfRenderingQueue,
+        linkService: pdfLinkService,
+        l10n: this.l10n,
+        pageColors
+      });
+      pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
+    }
     if (!this.isViewerEmbedded && !_app_options.AppOptions.get("disableHistory")) {
       this.pdfHistory = new _pdf_history.PDFHistory({
         linkService: pdfLinkService,
@@ -375,26 +375,34 @@ const PDFViewerApplication = {
       });
       pdfLinkService.setHistory(this.pdfHistory);
     }
-    if (!this.supportsIntegratedFind) {
+    if (!this.supportsIntegratedFind && appConfig.findBar) {
       this.findBar = new _pdf_find_bar.PDFFindBar(appConfig.findBar, eventBus, this.l10n);
     }
-    if (annotationEditorMode !== _pdf.AnnotationEditorType.DISABLE) {
-      this.annotationEditorParams = new _annotation_editor_params.AnnotationEditorParams(appConfig.annotationEditorParams, eventBus);
-    } else {
-      for (const element of [document.getElementById("editorModeButtons"), document.getElementById("editorModeSeparator")]) {
-        element.hidden = true;
+    if (appConfig.annotationEditorParams) {
+      if (annotationEditorMode !== _pdf.AnnotationEditorType.DISABLE) {
+        this.annotationEditorParams = new _annotation_editor_params.AnnotationEditorParams(appConfig.annotationEditorParams, eventBus);
+      } else {
+        for (const id of ["editorModeButtons", "editorModeSeparator"]) {
+          document.getElementById(id)?.classList.add("hidden");
+        }
       }
     }
-    this.pdfDocumentProperties = new _pdf_document_properties.PDFDocumentProperties(appConfig.documentProperties, this.overlayManager, eventBus, this.l10n, () => {
-      return this._docFilename;
-    });
+    if (appConfig.documentProperties) {
+      this.pdfDocumentProperties = new _pdf_document_properties.PDFDocumentProperties(appConfig.documentProperties, this.overlayManager, eventBus, this.l10n, () => {
+        return this._docFilename;
+      });
+    }
     this.pdfCursorTools = new _pdf_cursor_tools.PDFCursorTools({
       container,
       eventBus,
       cursorToolOnLoad: _app_options.AppOptions.get("cursorToolOnLoad")
     });
-    this.toolbar = new _toolbar.Toolbar(appConfig.toolbar, eventBus, this.l10n);
-    this.secondaryToolbar = new _secondary_toolbar.SecondaryToolbar(appConfig.secondaryToolbar, eventBus, this.externalServices);
+    if (appConfig.toolbar) {
+      this.toolbar = new _toolbar.Toolbar(appConfig.toolbar, eventBus, this.l10n);
+    }
+    if (appConfig.secondaryToolbar) {
+      this.secondaryToolbar = new _secondary_toolbar.SecondaryToolbar(appConfig.secondaryToolbar, eventBus, this.externalServices);
+    }
     if (this.supportsFullscreen) {
       this.pdfPresentationMode = new _pdf_presentation_mode.PDFPresentationMode({
         container,
@@ -402,32 +410,42 @@ const PDFViewerApplication = {
         eventBus
       });
     }
-    this.passwordPrompt = new _password_prompt.PasswordPrompt(appConfig.passwordOverlay, this.overlayManager, this.l10n, this.isViewerEmbedded);
-    this.pdfOutlineViewer = new _pdf_outline_viewer.PDFOutlineViewer({
-      container: appConfig.sidebar.outlineView,
-      eventBus,
-      linkService: pdfLinkService,
-      downloadManager
-    });
-    this.pdfAttachmentViewer = new _pdf_attachment_viewer.PDFAttachmentViewer({
-      container: appConfig.sidebar.attachmentsView,
-      eventBus,
-      downloadManager
-    });
-    this.pdfLayerViewer = new _pdf_layer_viewer.PDFLayerViewer({
-      container: appConfig.sidebar.layersView,
-      eventBus,
-      l10n: this.l10n
-    });
-    this.pdfSidebar = new _pdf_sidebar.PDFSidebar({
-      elements: appConfig.sidebar,
-      pdfViewer: this.pdfViewer,
-      pdfThumbnailViewer: this.pdfThumbnailViewer,
-      eventBus,
-      l10n: this.l10n
-    });
-    this.pdfSidebar.onToggled = this.forceRendering.bind(this);
-    this.pdfSidebarResizer = new _pdf_sidebar_resizer.PDFSidebarResizer(appConfig.sidebarResizer, eventBus, this.l10n);
+    if (appConfig.passwordOverlay) {
+      this.passwordPrompt = new _password_prompt.PasswordPrompt(appConfig.passwordOverlay, this.overlayManager, this.l10n, this.isViewerEmbedded);
+    }
+    if (appConfig.sidebar?.outlineView) {
+      this.pdfOutlineViewer = new _pdf_outline_viewer.PDFOutlineViewer({
+        container: appConfig.sidebar.outlineView,
+        eventBus,
+        linkService: pdfLinkService,
+        downloadManager
+      });
+    }
+    if (appConfig.sidebar?.attachmentsView) {
+      this.pdfAttachmentViewer = new _pdf_attachment_viewer.PDFAttachmentViewer({
+        container: appConfig.sidebar.attachmentsView,
+        eventBus,
+        downloadManager
+      });
+    }
+    if (appConfig.sidebar?.layersView) {
+      this.pdfLayerViewer = new _pdf_layer_viewer.PDFLayerViewer({
+        container: appConfig.sidebar.layersView,
+        eventBus,
+        l10n: this.l10n
+      });
+    }
+    if (appConfig.sidebar) {
+      this.pdfSidebar = new _pdf_sidebar.PDFSidebar({
+        elements: appConfig.sidebar,
+        pdfViewer: this.pdfViewer,
+        pdfThumbnailViewer: this.pdfThumbnailViewer,
+        eventBus,
+        l10n: this.l10n
+      });
+      this.pdfSidebar.onToggled = this.forceRendering.bind(this);
+      this.pdfSidebarResizer = new _pdf_sidebar_resizer.PDFSidebarResizer(appConfig.sidebarResizer, eventBus, this.l10n);
+    }
   },
   run(config) {
     this.initialize(config).then(webViewerInitialized);
@@ -442,13 +460,17 @@ const PDFViewerApplication = {
     if (this.pdfViewer.isInPresentationMode) {
       return;
     }
-    this.pdfViewer.increaseScale(steps);
+    this.pdfViewer.increaseScale(steps, {
+      drawingDelay: _app_options.AppOptions.get("defaultZoomDelay")
+    });
   },
   zoomOut(steps) {
     if (this.pdfViewer.isInPresentationMode) {
       return;
     }
-    this.pdfViewer.decreaseScale(steps);
+    this.pdfViewer.decreaseScale(steps, {
+      drawingDelay: _app_options.AppOptions.get("defaultZoomDelay")
+    });
   },
   zoomReset() {
     if (this.pdfViewer.isInPresentationMode) {
@@ -478,7 +500,8 @@ const PDFViewerApplication = {
     return this.externalServices.supportsDocumentFonts;
   },
   get loadingBar() {
-    const bar = new _ui_utils.ProgressBar("loadingBar");
+    const barElement = document.getElementById("loadingBar");
+    const bar = barElement ? new _ui_utils.ProgressBar(barElement) : null;
     return (0, _pdf.shadow)(this, "loadingBar", bar);
   },
   get supportedMouseWheelZoomModifierKeys() {
@@ -493,6 +516,9 @@ const PDFViewerApplication = {
     if (downloadUrl) {
       this._downloadUrl = downloadUrl === url ? this.baseUrl : downloadUrl.split("#")[0];
     }
+    if ((0, _pdf.isDataScheme)(url)) {
+      this._hideViewBookmark();
+    }
     let title = (0, _pdf.getPdfFilenameFromUrl)(url, "");
     if (!title) {
       try {
@@ -515,7 +541,13 @@ const PDFViewerApplication = {
     return this._contentDispositionFilename || (0, _pdf.getPdfFilenameFromUrl)(this.url);
   },
   _hideViewBookmark() {
-    this.appConfig.secondaryToolbar.viewBookmarkButton.hidden = true;
+    const {
+      secondaryToolbar
+    } = this.appConfig;
+    secondaryToolbar?.viewBookmarkButton.classList.add("hidden");
+    if (secondaryToolbar?.presentationModeButton.classList.contains("hidden")) {
+      document.getElementById("viewBookmarkSeparator")?.classList.add("hidden");
+    }
   },
   async close() {
     this._unblockDocumentLoadEvent();
@@ -533,10 +565,10 @@ const PDFViewerApplication = {
     this.pdfLoadingTask = null;
     if (this.pdfDocument) {
       this.pdfDocument = null;
-      this.pdfThumbnailViewer.setDocument(null);
+      this.pdfThumbnailViewer?.setDocument(null);
       this.pdfViewer.setDocument(null);
       this.pdfLinkService.setDocument(null);
-      this.pdfDocumentProperties.setDocument(null);
+      this.pdfDocumentProperties?.setDocument(null);
     }
     this.pdfLinkService.externalLinkEnabled = true;
     this.store = null;
@@ -550,18 +582,17 @@ const PDFViewerApplication = {
     this._contentDispositionFilename = null;
     this._contentLength = null;
     this._saveInProgress = false;
-    this._docStats = null;
     this._hasAnnotationEditors = false;
     promises.push(this.pdfScriptingManager.destroyPromise);
     this.setTitle();
-    this.pdfSidebar.reset();
-    this.pdfOutlineViewer.reset();
-    this.pdfAttachmentViewer.reset();
-    this.pdfLayerViewer.reset();
+    this.pdfSidebar?.reset();
+    this.pdfOutlineViewer?.reset();
+    this.pdfAttachmentViewer?.reset();
+    this.pdfLayerViewer?.reset();
     this.pdfHistory?.reset();
     this.findBar?.reset();
-    this.toolbar.reset();
-    this.secondaryToolbar.reset();
+    this.toolbar?.reset();
+    this.secondaryToolbar?.reset();
     this._PDFBug?.cleanup();
     await Promise.all(promises);
   },
@@ -610,7 +641,6 @@ const PDFViewerApplication = {
     }) => {
       this.progress(loaded / total);
     };
-    loadingTask.onUnsupportedFeature = this.fallback.bind(this);
     return loadingTask.promise.then(pdfDocument => {
       this.load(pdfDocument);
     }, reason => {
@@ -691,12 +721,6 @@ const PDFViewerApplication = {
       this.download();
     }
   },
-  fallback(featureId) {
-    this.externalServices.reportTelemetry({
-      type: "unsupportedFeature",
-      featureId
-    });
-  },
   _documentError(message, moreInfo = null) {
     this._unblockDocumentLoadEvent();
     this._otherError(message, moreInfo);
@@ -722,10 +746,9 @@ const PDFViewerApplication = {
       }
     }
     console.error(`${message}\n\n${moreInfoText.join("\n")}`);
-    this.fallback();
   },
   progress(level) {
-    if (this.downloadComplete) {
+    if (!this.loadingBar || this.downloadComplete) {
       return;
     }
     const percent = Math.round(level * 100);
@@ -754,7 +777,7 @@ const PDFViewerApplication = {
     }) => {
       this._contentLength = length;
       this.downloadComplete = true;
-      this.loadingBar.hide();
+      this.loadingBar?.hide();
       firstPagePromise.then(() => {
         this.eventBus.dispatch("documentloaded", {
           source: this
@@ -764,12 +787,15 @@ const PDFViewerApplication = {
     const pageLayoutPromise = pdfDocument.getPageLayout().catch(function () {});
     const pageModePromise = pdfDocument.getPageMode().catch(function () {});
     const openActionPromise = pdfDocument.getOpenAction().catch(function () {});
-    this.toolbar.setPagesCount(pdfDocument.numPages, false);
-    this.secondaryToolbar.setPagesCount(pdfDocument.numPages);
+    this.toolbar?.setPagesCount(pdfDocument.numPages, false);
+    this.secondaryToolbar?.setPagesCount(pdfDocument.numPages);
     let baseDocumentUrl;
     baseDocumentUrl = null;
+    if (baseDocumentUrl && (0, _pdf.isDataScheme)(baseDocumentUrl)) {
+      baseDocumentUrl = null;
+    }
     this.pdfLinkService.setDocument(pdfDocument, baseDocumentUrl);
-    this.pdfDocumentProperties.setDocument(pdfDocument);
+    this.pdfDocumentProperties?.setDocument(pdfDocument);
     const pdfViewer = this.pdfViewer;
     pdfViewer.setDocument(pdfDocument);
     const {
@@ -777,8 +803,7 @@ const PDFViewerApplication = {
       onePageRendered,
       pagesPromise
     } = pdfViewer;
-    const pdfThumbnailViewer = this.pdfThumbnailViewer;
-    pdfThumbnailViewer.setDocument(pdfDocument);
+    this.pdfThumbnailViewer?.setDocument(pdfDocument);
     const storedPromise = (this.store = new _view_history.ViewHistory(pdfDocument.fingerprints[0])).getMultiple({
       page: null,
       zoom: _ui_utils.DEFAULT_SCALE_VALUE,
@@ -792,7 +817,7 @@ const PDFViewerApplication = {
       return Object.create(null);
     });
     firstPagePromise.then(pdfPage => {
-      this.loadingBar.setWidth(this.appConfig.viewerContainer);
+      this.loadingBar?.setWidth(this.appConfig.viewerContainer);
       this._initializeAnnotationStorageCallbacks(pdfDocument);
       Promise.all([_ui_utils.animationStarted, storedPromise, pageLayoutPromise, pageModePromise, openActionPromise]).then(async ([timeStamp, stored, pageLayout, pageMode, openAction]) => {
         const viewOnLoad = _app_options.AppOptions.get("viewOnLoad");
@@ -877,7 +902,7 @@ const PDFViewerApplication = {
         if (pdfDocument !== this.pdfDocument) {
           return;
         }
-        this.pdfOutlineViewer.render({
+        this.pdfOutlineViewer?.render({
           outline,
           pdfDocument
         });
@@ -886,7 +911,7 @@ const PDFViewerApplication = {
         if (pdfDocument !== this.pdfDocument) {
           return;
         }
-        this.pdfAttachmentViewer.render({
+        this.pdfAttachmentViewer?.render({
           attachments
         });
       });
@@ -894,7 +919,7 @@ const PDFViewerApplication = {
         if (pdfDocument !== this.pdfDocument) {
           return;
         }
-        this.pdfLayerViewer.render({
+        this.pdfLayerViewer?.render({
           optionalContentConfig,
           pdfDocument
         });
@@ -950,7 +975,6 @@ const PDFViewerApplication = {
           return false;
         }
         console.warn("Warning: JavaScript support is not enabled");
-        this.fallback(_pdf.UNSUPPORTED_FEATURES.javaScript);
         return true;
       });
       if (!triggerAutoPrint) {
@@ -999,42 +1023,12 @@ const PDFViewerApplication = {
       } else {
         console.warn("Warning: XFA support is not enabled");
       }
-      this.fallback(_pdf.UNSUPPORTED_FEATURES.forms);
     } else if ((info.IsAcroFormPresent || info.IsXFAPresent) && !this.pdfViewer.renderForms) {
       console.warn("Warning: Interactive form support is not enabled");
-      this.fallback(_pdf.UNSUPPORTED_FEATURES.forms);
     }
     if (info.IsSignaturesPresent) {
       console.warn("Warning: Digital signatures validation is not supported");
-      this.fallback(_pdf.UNSUPPORTED_FEATURES.signatures);
-    }
-    let versionId = "other";
-    if (KNOWN_VERSIONS.includes(info.PDFFormatVersion)) {
-      versionId = `v${info.PDFFormatVersion.replace(".", "_")}`;
-    }
-    let generatorId = "other";
-    if (info.Producer) {
-      const producer = info.Producer.toLowerCase();
-      KNOWN_GENERATORS.some(function (generator) {
-        if (!producer.includes(generator)) {
-          return false;
-        }
-        generatorId = generator.replace(/[ .-]/g, "_");
-        return true;
-      });
     }
-    let formType = null;
-    if (info.IsXFAPresent) {
-      formType = "xfa";
-    } else if (info.IsAcroFormPresent) {
-      formType = "acroform";
-    }
-    this.externalServices.reportTelemetry({
-      type: "documentInfo",
-      version: versionId,
-      generator: generatorId,
-      formType
-    });
     this.eventBus.dispatch("metadataloaded", {
       source: this
     });
@@ -1069,9 +1063,9 @@ const PDFViewerApplication = {
       toolbar
     } = this;
     pdfViewer.setPageLabels(labels);
-    pdfThumbnailViewer.setPageLabels(labels);
-    toolbar.setPagesCount(numLabels, true);
-    toolbar.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);
+    pdfThumbnailViewer?.setPageLabels(labels);
+    toolbar?.setPagesCount(numLabels, true);
+    toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);
   },
   _initializePdfHistory({
     fingerprint,
@@ -1146,7 +1140,7 @@ const PDFViewerApplication = {
       }
     };
     this.isInitialViewSet = true;
-    this.pdfSidebar.setInitialView(sidebarView);
+    this.pdfSidebar?.setInitialView(sidebarView);
     setViewerModes(scrollMode, spreadMode);
     if (this.initialBookmark) {
       setRotation(this.initialRotation);
@@ -1157,8 +1151,8 @@ const PDFViewerApplication = {
       setRotation(rotation);
       this.pdfLinkService.setHash(storedHash);
     }
-    this.toolbar.setPageNumber(this.pdfViewer.currentPageNumber, this.pdfViewer.currentPageLabel);
-    this.secondaryToolbar.setPageNumber(this.pdfViewer.currentPageNumber);
+    this.toolbar?.setPageNumber(this.pdfViewer.currentPageNumber, this.pdfViewer.currentPageLabel);
+    this.secondaryToolbar?.setPageNumber(this.pdfViewer.currentPageNumber);
     if (!this.pdfViewer.currentScaleValue) {
       this.pdfViewer.currentScaleValue = _ui_utils.DEFAULT_SCALE_VALUE;
     }
@@ -1168,12 +1162,12 @@ const PDFViewerApplication = {
       return;
     }
     this.pdfViewer.cleanup();
-    this.pdfThumbnailViewer.cleanup();
+    this.pdfThumbnailViewer?.cleanup();
     this.pdfDocument.cleanup(this.pdfViewer.renderer === _ui_utils.RendererType.SVG);
   },
   forceRendering() {
     this.pdfRenderingQueue.printing = !!this.printService;
-    this.pdfRenderingQueue.isThumbnailViewEnabled = this.pdfSidebar.visibleView === _ui_utils.SidebarView.THUMBS;
+    this.pdfRenderingQueue.isThumbnailViewEnabled = this.pdfSidebar?.visibleView === _ui_utils.SidebarView.THUMBS;
     this.pdfRenderingQueue.renderHighestPriority();
   },
   beforePrint() {
@@ -1204,9 +1198,6 @@ const PDFViewerApplication = {
     this.forceRendering();
     this.setTitle();
     printService.layout();
-    this.externalServices.reportTelemetry({
-      type: "print"
-    });
     if (this._hasAnnotationEditors) {
       this.externalServices.reportTelemetry({
         type: "editing",
@@ -1254,6 +1245,7 @@ const PDFViewerApplication = {
     eventBus._on("hashchange", webViewerHashchange);
     eventBus._on("beforeprint", _boundEvents.beforePrint);
     eventBus._on("afterprint", _boundEvents.afterPrint);
+    eventBus._on("pagerender", webViewerPageRender);
     eventBus._on("pagerendered", webViewerPageRendered);
     eventBus._on("updateviewarea", webViewerUpdateViewarea);
     eventBus._on("pagechanging", webViewerPageChanging);
@@ -1366,6 +1358,7 @@ const PDFViewerApplication = {
     eventBus._off("hashchange", webViewerHashchange);
     eventBus._off("beforeprint", _boundEvents.beforePrint);
     eventBus._off("afterprint", _boundEvents.afterPrint);
+    eventBus._off("pagerender", webViewerPageRender);
     eventBus._off("pagerendered", webViewerPageRendered);
     eventBus._off("updateviewarea", webViewerUpdateViewarea);
     eventBus._off("pagechanging", webViewerPageChanging);
@@ -1438,7 +1431,7 @@ const PDFViewerApplication = {
       this._wheelUnusedTicks = 0;
     }
     this._wheelUnusedTicks += ticks;
-    const wholeTicks = Math.sign(this._wheelUnusedTicks) * Math.floor(Math.abs(this._wheelUnusedTicks));
+    const wholeTicks = Math.trunc(this._wheelUnusedTicks);
     this._wheelUnusedTicks -= wholeTicks;
     return wholeTicks;
   },
@@ -1446,18 +1439,6 @@ const PDFViewerApplication = {
     document.blockUnblockOnload?.(false);
     this._unblockDocumentLoadEvent = () => {};
   },
-  _reportDocumentStatsTelemetry() {
-    const {
-      stats
-    } = this.pdfDocument;
-    if (stats !== this._docStats) {
-      this._docStats = stats;
-      this.externalServices.reportTelemetry({
-        type: "documentStats",
-        stats
-      });
-    }
-  },
   get scriptingReady() {
     return this.pdfScriptingManager.ready;
   }
@@ -1558,14 +1539,14 @@ function webViewerInitialized() {
     });
   }
   if (!PDFViewerApplication.supportsPrinting) {
-    appConfig.toolbar.print.classList.add("hidden");
-    appConfig.secondaryToolbar.printButton.classList.add("hidden");
+    appConfig.toolbar?.print.classList.add("hidden");
+    appConfig.secondaryToolbar?.printButton.classList.add("hidden");
   }
   if (!PDFViewerApplication.supportsFullscreen) {
-    appConfig.secondaryToolbar.presentationModeButton.classList.add("hidden");
+    appConfig.secondaryToolbar?.presentationModeButton.classList.add("hidden");
   }
   if (PDFViewerApplication.supportsIntegratedFind) {
-    appConfig.toolbar.viewFind.classList.add("hidden");
+    appConfig.toolbar?.viewFind.classList.add("hidden");
   }
   appConfig.mainContainer.addEventListener("transitionend", function (evt) {
     if (evt.target === this) {
@@ -1586,16 +1567,23 @@ function webViewerInitialized() {
     });
   }
 }
+function webViewerPageRender({
+  pageNumber
+}) {
+  if (pageNumber === PDFViewerApplication.page) {
+    PDFViewerApplication.toolbar?.updateLoadingIndicatorState(true);
+  }
+}
 function webViewerPageRendered({
   pageNumber,
   error
 }) {
   if (pageNumber === PDFViewerApplication.page) {
-    PDFViewerApplication.toolbar.updateLoadingIndicatorState(false);
+    PDFViewerApplication.toolbar?.updateLoadingIndicatorState(false);
   }
-  if (PDFViewerApplication.pdfSidebar.visibleView === _ui_utils.SidebarView.THUMBS) {
+  if (PDFViewerApplication.pdfSidebar?.visibleView === _ui_utils.SidebarView.THUMBS) {
     const pageView = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1);
-    const thumbnailView = PDFViewerApplication.pdfThumbnailViewer.getThumbnail(pageNumber - 1);
+    const thumbnailView = PDFViewerApplication.pdfThumbnailViewer?.getThumbnail(pageNumber - 1);
     if (pageView && thumbnailView) {
       thumbnailView.setImage(pageView);
     }
@@ -1605,7 +1593,6 @@ function webViewerPageRendered({
       PDFViewerApplication._otherError(msg, error);
     });
   }
-  PDFViewerApplication._reportDocumentStatsTelemetry();
 }
 function webViewerPageMode({
   mode
@@ -1632,16 +1619,16 @@ function webViewerPageMode({
       console.error('Invalid "pagemode" hash parameter: ' + mode);
       return;
   }
-  PDFViewerApplication.pdfSidebar.switchView(view, true);
+  PDFViewerApplication.pdfSidebar?.switchView(view, true);
 }
 function webViewerNamedAction(evt) {
   switch (evt.action) {
     case "GoToPage":
-      PDFViewerApplication.appConfig.toolbar.pageNumber.select();
+      PDFViewerApplication.appConfig.toolbar?.pageNumber.select();
       break;
     case "Find":
       if (!PDFViewerApplication.supportsIntegratedFind) {
-        PDFViewerApplication.findBar.toggle();
+        PDFViewerApplication?.findBar.toggle();
       }
       break;
     case "Print":
@@ -1675,11 +1662,10 @@ function webViewerUpdateViewarea({
       rotation: location.rotation
     }).catch(() => {});
   }
-  const href = PDFViewerApplication.pdfLinkService.getAnchorUrl(location.pdfOpenParams);
-  PDFViewerApplication.appConfig.secondaryToolbar.viewBookmarkButton.href = href;
-  const currentPage = PDFViewerApplication.pdfViewer.getPageView(PDFViewerApplication.page - 1);
-  const loading = currentPage?.renderingState !== _ui_utils.RenderingStates.FINISHED;
-  PDFViewerApplication.toolbar.updateLoadingIndicatorState(loading);
+  if (PDFViewerApplication.appConfig.secondaryToolbar) {
+    const href = PDFViewerApplication.pdfLinkService.getAnchorUrl(location.pdfOpenParams);
+    PDFViewerApplication.appConfig.secondaryToolbar.viewBookmarkButton.href = href;
+  }
 }
 function webViewerScrollModeChanged(evt) {
   if (PDFViewerApplication.isInitialViewSet && !PDFViewerApplication.pdfViewer.isInPresentationMode) {
@@ -1700,7 +1686,6 @@ function webViewerResize() {
   if (pdfRenderingQueue.printing && window.matchMedia("print").matches) {
     return;
   }
-  pdfViewer.updateContainerHeightCss();
   if (!pdfDocument) {
     return;
   }
@@ -1787,7 +1772,7 @@ function webViewerPageNumberChanged(evt) {
     PDFViewerApplication.pdfLinkService.goToPage(evt.value);
   }
   if (evt.value !== pdfViewer.currentPageNumber.toString() && evt.value !== pdfViewer.currentPageLabel) {
-    PDFViewerApplication.toolbar.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);
+    PDFViewerApplication.toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);
   }
 }
 function webViewerScaleChanged(evt) {
@@ -1809,7 +1794,7 @@ function webViewerSwitchSpreadMode(evt) {
   PDFViewerApplication.pdfViewer.spreadMode = evt.mode;
 }
 function webViewerDocumentProperties() {
-  PDFViewerApplication.pdfDocumentProperties.open();
+  PDFViewerApplication.pdfDocumentProperties?.open();
 }
 function webViewerFindFromUrlHash(evt) {
   PDFViewerApplication.eventBus.dispatch("find", {
@@ -1847,15 +1832,17 @@ function webViewerUpdateFindControlState({
       rawQuery
     });
   } else {
-    PDFViewerApplication.findBar.updateUIState(state, previous, matchesCount);
+    PDFViewerApplication.findBar?.updateUIState(state, previous, matchesCount);
   }
 }
 function webViewerScaleChanging(evt) {
-  PDFViewerApplication.toolbar.setPageScale(evt.presetValue, evt.scale);
+  PDFViewerApplication.toolbar?.setPageScale(evt.presetValue, evt.scale);
   PDFViewerApplication.pdfViewer.update();
 }
 function webViewerRotationChanging(evt) {
-  PDFViewerApplication.pdfThumbnailViewer.pagesRotation = evt.pagesRotation;
+  if (PDFViewerApplication.pdfThumbnailViewer) {
+    PDFViewerApplication.pdfThumbnailViewer.pagesRotation = evt.pagesRotation;
+  }
   PDFViewerApplication.forceRendering();
   PDFViewerApplication.pdfViewer.currentPageNumber = evt.pageNumber;
 }
@@ -1863,11 +1850,13 @@ function webViewerPageChanging({
   pageNumber,
   pageLabel
 }) {
-  PDFViewerApplication.toolbar.setPageNumber(pageNumber, pageLabel);
-  PDFViewerApplication.secondaryToolbar.setPageNumber(pageNumber);
-  if (PDFViewerApplication.pdfSidebar.visibleView === _ui_utils.SidebarView.THUMBS) {
-    PDFViewerApplication.pdfThumbnailViewer.scrollThumbnailIntoView(pageNumber);
+  PDFViewerApplication.toolbar?.setPageNumber(pageNumber, pageLabel);
+  PDFViewerApplication.secondaryToolbar?.setPageNumber(pageNumber);
+  if (PDFViewerApplication.pdfSidebar?.visibleView === _ui_utils.SidebarView.THUMBS) {
+    PDFViewerApplication.pdfThumbnailViewer?.scrollThumbnailIntoView(pageNumber);
   }
+  const currentPage = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1);
+  PDFViewerApplication.toolbar?.updateLoadingIndicatorState(currentPage?.renderingState === _ui_utils.RenderingStates.RUNNING);
 }
 function webViewerResolutionChange(evt) {
   PDFViewerApplication.pdfViewer.refresh();
@@ -1921,9 +1910,9 @@ function webViewerWheel(evt) {
     const currentScale = pdfViewer.currentScale;
     if (previousScale !== currentScale) {
       const scaleCorrectionFactor = currentScale / previousScale - 1;
-      const rect = pdfViewer.container.getBoundingClientRect();
-      const dx = evt.clientX - rect.left;
-      const dy = evt.clientY - rect.top;
+      const [top, left] = pdfViewer.containerTopLeft;
+      const dx = evt.clientX - left;
+      const dy = evt.clientY - top;
       pdfViewer.container.scrollLeft += dx * scaleCorrectionFactor;
       pdfViewer.container.scrollTop += dy * scaleCorrectionFactor;
     }
@@ -1937,11 +1926,11 @@ function webViewerTouchStart(evt) {
   }
 }
 function webViewerClick(evt) {
-  if (!PDFViewerApplication.secondaryToolbar.isOpen) {
+  if (!PDFViewerApplication.secondaryToolbar?.isOpen) {
     return;
   }
   const appConfig = PDFViewerApplication.appConfig;
-  if (PDFViewerApplication.pdfViewer.containsElement(evt.target) || appConfig.toolbar.container.contains(evt.target) && evt.target !== appConfig.secondaryToolbar.toggleButton) {
+  if (PDFViewerApplication.pdfViewer.containsElement(evt.target) || appConfig.toolbar?.container.contains(evt.target) && evt.target !== appConfig.secondaryToolbar?.toggleButton) {
     PDFViewerApplication.secondaryToolbar.close();
   }
 }
@@ -1961,7 +1950,7 @@ function webViewerKeyDown(evt) {
     switch (evt.keyCode) {
       case 70:
         if (!PDFViewerApplication.supportsIntegratedFind && !evt.shiftKey) {
-          PDFViewerApplication.findBar.open();
+          PDFViewerApplication.findBar?.open();
           handled = true;
         }
         break;
@@ -2054,8 +2043,10 @@ function webViewerKeyDown(evt) {
         });
         break;
       case 71:
-        PDFViewerApplication.appConfig.toolbar.pageNumber.select();
-        handled = true;
+        if (PDFViewerApplication.appConfig.toolbar) {
+          PDFViewerApplication.appConfig.toolbar.pageNumber.select();
+          handled = true;
+        }
         break;
     }
   }
@@ -2099,11 +2090,11 @@ function webViewerKeyDown(evt) {
         turnPage = -1;
         break;
       case 27:
-        if (PDFViewerApplication.secondaryToolbar.isOpen) {
+        if (PDFViewerApplication.secondaryToolbar?.isOpen) {
           PDFViewerApplication.secondaryToolbar.close();
           handled = true;
         }
-        if (!PDFViewerApplication.supportsIntegratedFind && PDFViewerApplication.findBar.opened) {
+        if (!PDFViewerApplication.supportsIntegratedFind && PDFViewerApplication.findBar?.opened) {
           PDFViewerApplication.findBar.close();
           handled = true;
         }
@@ -2145,16 +2136,16 @@ function webViewerKeyDown(evt) {
         }
         break;
       case 83:
-        PDFViewerApplication.pdfCursorTools.switchTool(_pdf_cursor_tools.CursorTool.SELECT);
+        PDFViewerApplication.pdfCursorTools?.switchTool(_pdf_cursor_tools.CursorTool.SELECT);
         break;
       case 72:
-        PDFViewerApplication.pdfCursorTools.switchTool(_pdf_cursor_tools.CursorTool.HAND);
+        PDFViewerApplication.pdfCursorTools?.switchTool(_pdf_cursor_tools.CursorTool.HAND);
         break;
       case 82:
         PDFViewerApplication.rotatePages(90);
         break;
       case 115:
-        PDFViewerApplication.pdfSidebar.toggle();
+        PDFViewerApplication.pdfSidebar?.toggle();
         break;
     }
     if (turnPage !== 0 && (!turnOnlyIfPageFit || pdfViewer.currentScaleValue === "page-fit")) {

+ 4 - 0
lib/web/app_options.js

@@ -62,6 +62,10 @@ const defaultOptions = {
     value: 0,
     kind: OptionKind.VIEWER + OptionKind.PREFERENCE
   },
+  defaultZoomDelay: {
+    value: -1,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
   defaultZoomValue: {
     value: "",
     kind: OptionKind.VIEWER + OptionKind.PREFERENCE

+ 1 - 1
lib/web/chromecom.js

@@ -306,7 +306,7 @@ class ChromeExternalServices extends _app.DefaultExternalServices {
       callbacks.onOpenWithURL(url, length, originalUrl);
     });
   }
-  static createDownloadManager(options) {
+  static createDownloadManager() {
     return new _download_manager.DownloadManager();
   }
   static createPreferences() {

+ 1 - 1
lib/web/debugger.js

@@ -335,7 +335,7 @@ const Stepper = function StepperClosure() {
           table.classList.add("showText");
           decArgs.append(table);
           table.append(charCodeRow, fontCharRow, unicodeRow);
-        } else if (fn === "restore") {
+        } else if (fn === "restore" && this.indentLevel > 0) {
           this.indentLevel--;
         }
         line.append(c("td", " ".repeat(this.indentLevel * 2) + fn));

+ 0 - 132
lib/web/default_factory.js

@@ -1,132 +0,0 @@
-/**
- * @licstart The following is the entire license notice for the
- * JavaScript code in this page
- *
- * Copyright 2022 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @licend The above is the entire license notice for the
- * JavaScript code in this page
- */
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-exports.DefaultXfaLayerFactory = exports.DefaultTextLayerFactory = exports.DefaultStructTreeLayerFactory = exports.DefaultAnnotationLayerFactory = exports.DefaultAnnotationEditorLayerFactory = void 0;
-var _annotation_editor_layer_builder = require("./annotation_editor_layer_builder.js");
-var _annotation_layer_builder = require("./annotation_layer_builder.js");
-var _l10n_utils = require("./l10n_utils.js");
-var _pdf_link_service = require("./pdf_link_service.js");
-var _struct_tree_layer_builder = require("./struct_tree_layer_builder.js");
-var _text_layer_builder = require("./text_layer_builder.js");
-var _xfa_layer_builder = require("./xfa_layer_builder.js");
-class DefaultAnnotationLayerFactory {
-  createAnnotationLayerBuilder({
-    pageDiv,
-    pdfPage,
-    annotationStorage = null,
-    imageResourcesPath = "",
-    renderForms = true,
-    l10n = _l10n_utils.NullL10n,
-    enableScripting = false,
-    hasJSActionsPromise = null,
-    mouseState = null,
-    fieldObjectsPromise = null,
-    annotationCanvasMap = null,
-    accessibilityManager = null
-  }) {
-    return new _annotation_layer_builder.AnnotationLayerBuilder({
-      pageDiv,
-      pdfPage,
-      imageResourcesPath,
-      renderForms,
-      linkService: new _pdf_link_service.SimpleLinkService(),
-      l10n,
-      annotationStorage,
-      enableScripting,
-      hasJSActionsPromise,
-      fieldObjectsPromise,
-      mouseState,
-      annotationCanvasMap,
-      accessibilityManager
-    });
-  }
-}
-exports.DefaultAnnotationLayerFactory = DefaultAnnotationLayerFactory;
-class DefaultAnnotationEditorLayerFactory {
-  createAnnotationEditorLayerBuilder({
-    uiManager = null,
-    pageDiv,
-    pdfPage,
-    accessibilityManager = null,
-    l10n,
-    annotationStorage = null
-  }) {
-    return new _annotation_editor_layer_builder.AnnotationEditorLayerBuilder({
-      uiManager,
-      pageDiv,
-      pdfPage,
-      accessibilityManager,
-      l10n,
-      annotationStorage
-    });
-  }
-}
-exports.DefaultAnnotationEditorLayerFactory = DefaultAnnotationEditorLayerFactory;
-class DefaultStructTreeLayerFactory {
-  createStructTreeLayerBuilder({
-    pdfPage
-  }) {
-    return new _struct_tree_layer_builder.StructTreeLayerBuilder({
-      pdfPage
-    });
-  }
-}
-exports.DefaultStructTreeLayerFactory = DefaultStructTreeLayerFactory;
-class DefaultTextLayerFactory {
-  createTextLayerBuilder({
-    textLayerDiv,
-    pageIndex,
-    viewport,
-    eventBus,
-    highlighter,
-    accessibilityManager = null
-  }) {
-    return new _text_layer_builder.TextLayerBuilder({
-      textLayerDiv,
-      pageIndex,
-      viewport,
-      eventBus,
-      highlighter,
-      accessibilityManager
-    });
-  }
-}
-exports.DefaultTextLayerFactory = DefaultTextLayerFactory;
-class DefaultXfaLayerFactory {
-  createXfaLayerBuilder({
-    pageDiv,
-    pdfPage,
-    annotationStorage = null
-  }) {
-    return new _xfa_layer_builder.XfaLayerBuilder({
-      pageDiv,
-      pdfPage,
-      annotationStorage,
-      linkService: new _pdf_link_service.SimpleLinkService()
-    });
-  }
-}
-exports.DefaultXfaLayerFactory = DefaultXfaLayerFactory;

+ 1 - 1
lib/web/firefoxcom.js

@@ -318,7 +318,7 @@ class FirefoxExternalServices extends _app.DefaultExternalServices {
   static reportTelemetry(data) {
     FirefoxCom.request("reportTelemetry", JSON.stringify(data));
   }
-  static createDownloadManager(options) {
+  static createDownloadManager() {
     return new DownloadManager();
   }
   static createPreferences() {

+ 1 - 1
lib/web/genericcom.js

@@ -42,7 +42,7 @@ class GenericPreferences extends _preferences.BasePreferences {
   }
 }
 class GenericExternalServices extends _app.DefaultExternalServices {
-  static createDownloadManager(options) {
+  static createDownloadManager() {
     return new _download_manager.DownloadManager();
   }
   static createPreferences() {

+ 1 - 54
lib/web/interfaces.js

@@ -24,7 +24,7 @@
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.IRenderableView = exports.IPDFXfaLayerFactory = exports.IPDFTextLayerFactory = exports.IPDFStructTreeLayerFactory = exports.IPDFLinkService = exports.IPDFAnnotationLayerFactory = exports.IPDFAnnotationEditorLayerFactory = exports.IL10n = exports.IDownloadManager = void 0;
+exports.IRenderableView = exports.IPDFLinkService = exports.IL10n = exports.IDownloadManager = void 0;
 class IPDFLinkService {
   get pagesCount() {}
   get page() {}
@@ -56,59 +56,6 @@ class IRenderableView {
   draw() {}
 }
 exports.IRenderableView = IRenderableView;
-class IPDFTextLayerFactory {
-  createTextLayerBuilder({
-    textLayerDiv,
-    pageIndex,
-    viewport,
-    eventBus,
-    highlighter,
-    accessibilityManager
-  }) {}
-}
-exports.IPDFTextLayerFactory = IPDFTextLayerFactory;
-class IPDFAnnotationLayerFactory {
-  createAnnotationLayerBuilder({
-    pageDiv,
-    pdfPage,
-    annotationStorage = null,
-    imageResourcesPath = "",
-    renderForms = true,
-    l10n = undefined,
-    enableScripting = false,
-    hasJSActionsPromise = null,
-    mouseState = null,
-    fieldObjectsPromise = null,
-    annotationCanvasMap = null,
-    accessibilityManager = null
-  }) {}
-}
-exports.IPDFAnnotationLayerFactory = IPDFAnnotationLayerFactory;
-class IPDFAnnotationEditorLayerFactory {
-  createAnnotationEditorLayerBuilder({
-    uiManager = null,
-    pageDiv,
-    pdfPage,
-    l10n,
-    annotationStorage = null,
-    accessibilityManager
-  }) {}
-}
-exports.IPDFAnnotationEditorLayerFactory = IPDFAnnotationEditorLayerFactory;
-class IPDFXfaLayerFactory {
-  createXfaLayerBuilder({
-    pageDiv,
-    pdfPage,
-    annotationStorage = null
-  }) {}
-}
-exports.IPDFXfaLayerFactory = IPDFXfaLayerFactory;
-class IPDFStructTreeLayerFactory {
-  createStructTreeLayerBuilder({
-    pdfPage
-  }) {}
-}
-exports.IPDFStructTreeLayerFactory = IPDFStructTreeLayerFactory;
 class IDownloadManager {
   downloadUrl(url, filename) {}
   downloadData(data, filename, contentType) {}

+ 2 - 1
lib/web/pdf_find_controller.js

@@ -88,7 +88,8 @@ function normalize(text) {
   } else {
     const replace = Object.keys(CHARACTERS_TO_NORMALIZE).join("");
     const toNormalizeWithNFKC = "\u2460-\u2473" + "\u24b6-\u24ff" + "\u3244-\u32bf" + "\u32d0-\u32fe" + "\uff00-\uffef";
-    const regexp = `([${replace}])|([${toNormalizeWithNFKC}])|(\\p{M}+(?:-\\n)?)|(\\S-\\n)|(\\p{Ideographic}\\n)|(\\n)`;
+    const CJK = "(?:\\p{Ideographic}|[\u3040-\u30FF])";
+    const regexp = `([${replace}])|([${toNormalizeWithNFKC}])|(\\p{M}+(?:-\\n)?)|(\\S-\\n)|(${CJK}\\n)|(\\n)`;
     if (syllablePositions.length === 0) {
       normalizationRegex = noSyllablesRegExp = new RegExp(regexp + "|(\\u0000)", "gum");
     } else {

+ 277 - 198
lib/web/pdf_page_view.js

@@ -27,12 +27,24 @@ Object.defineProperty(exports, "__esModule", {
 exports.PDFPageView = void 0;
 var _pdf = require("../pdf");
 var _ui_utils = require("./ui_utils.js");
+var _annotation_editor_layer_builder = require("./annotation_editor_layer_builder.js");
+var _annotation_layer_builder = require("./annotation_layer_builder.js");
 var _app_options = require("./app_options.js");
 var _l10n_utils = require("./l10n_utils.js");
+var _struct_tree_layer_builder = require("./struct_tree_layer_builder.js");
 var _text_accessibility = require("./text_accessibility.js");
+var _text_highlighter = require("./text_highlighter.js");
+var _text_layer_builder = require("./text_layer_builder.js");
+var _xfa_layer_builder = require("./xfa_layer_builder.js");
 const MAX_CANVAS_PIXELS = _app_options.compatibilityParams.maxCanvasPixels || 16777216;
+const DEFAULT_LAYER_PROPERTIES = () => {
+  return null;
+};
 class PDFPageView {
   #annotationMode = _pdf.AnnotationMode.ENABLE_FORMS;
+  #layerProperties = null;
+  #previousRotation = null;
+  #renderingState = _ui_utils.RenderingStates.INITIAL;
   #useThumbnailCanvas = {
     initialOptionalContent: true,
     regularAnnotations: true
@@ -42,6 +54,7 @@ class PDFPageView {
     const defaultViewport = options.defaultViewport;
     this.id = options.id;
     this.renderingId = "page" + this.id;
+    this.#layerProperties = options.layerProperties || DEFAULT_LAYER_PROPERTIES;
     this.pdfPage = null;
     this.pageLabel = null;
     this.rotation = 0;
@@ -54,24 +67,15 @@ class PDFPageView {
     this.#annotationMode = options.annotationMode ?? _pdf.AnnotationMode.ENABLE_FORMS;
     this.imageResourcesPath = options.imageResourcesPath || "";
     this.useOnlyCssZoom = options.useOnlyCssZoom || false;
+    this.isOffscreenCanvasSupported = options.isOffscreenCanvasSupported ?? true;
     this.maxCanvasPixels = options.maxCanvasPixels || MAX_CANVAS_PIXELS;
     this.pageColors = options.pageColors || null;
     this.eventBus = options.eventBus;
     this.renderingQueue = options.renderingQueue;
-    this.textLayerFactory = options.textLayerFactory;
-    this.annotationLayerFactory = options.annotationLayerFactory;
-    this.annotationEditorLayerFactory = options.annotationEditorLayerFactory;
-    this.xfaLayerFactory = options.xfaLayerFactory;
-    this.textHighlighter = options.textHighlighterFactory?.createTextHighlighter({
-      pageIndex: this.id - 1,
-      eventBus: this.eventBus
-    });
-    this.structTreeLayerFactory = options.structTreeLayerFactory;
     this.renderer = options.renderer || _ui_utils.RendererType.CANVAS;
     this.l10n = options.l10n || _l10n_utils.NullL10n;
     this.paintTask = null;
     this.paintedViewportMap = new WeakMap();
-    this.renderingState = _ui_utils.RenderingStates.INITIAL;
     this.resume = null;
     this._renderError = null;
     this._isStandalone = !this.renderingQueue?.hasViewer();
@@ -84,8 +88,6 @@ class PDFPageView {
     this.structTreeLayer = null;
     const div = document.createElement("div");
     div.className = "page";
-    div.style.width = Math.floor(this.viewport.width) + "px";
-    div.style.height = Math.floor(this.viewport.height) + "px";
     div.setAttribute("data-page-number", this.id);
     div.setAttribute("role", "region");
     this.l10n.get("page_landmark", {
@@ -94,8 +96,10 @@ class PDFPageView {
       div.setAttribute("aria-label", msg);
     });
     this.div = div;
+    this.#setDimensions();
     container?.append(div);
     if (this._isStandalone) {
+      _ui_utils.docStyle.setProperty("--scale-factor", this.scale * _pdf.PixelsPerInch.PDF_TO_CSS_UNITS);
       const {
         optionalContentConfigPromise
       } = options;
@@ -109,6 +113,39 @@ class PDFPageView {
       }
     }
   }
+  get renderingState() {
+    return this.#renderingState;
+  }
+  set renderingState(state) {
+    this.#renderingState = state;
+    switch (state) {
+      case _ui_utils.RenderingStates.INITIAL:
+      case _ui_utils.RenderingStates.PAUSED:
+        this.loadingIconDiv?.classList.add("notVisible");
+        break;
+      case _ui_utils.RenderingStates.RUNNING:
+        this.loadingIconDiv?.classList.remove("notVisible");
+        break;
+      case _ui_utils.RenderingStates.FINISHED:
+        if (this.loadingIconDiv) {
+          this.loadingIconDiv.remove();
+          delete this.loadingIconDiv;
+        }
+        break;
+    }
+  }
+  #setDimensions() {
+    const {
+      viewport
+    } = this;
+    if (this.pdfPage) {
+      if (this.#previousRotation === viewport.rotation) {
+        return;
+      }
+      this.#previousRotation = viewport.rotation;
+    }
+    (0, _pdf.setLayerDimensions)(this.div, viewport, true, false);
+  }
   setPdfPage(pdfPage) {
     this.pdfPage = pdfPage;
     this.pdfPageRotate = pdfPage.rotate;
@@ -117,18 +154,26 @@ class PDFPageView {
       scale: this.scale * _pdf.PixelsPerInch.PDF_TO_CSS_UNITS,
       rotation: totalRotation
     });
+    this.#setDimensions();
     this.reset();
   }
   destroy() {
     this.reset();
     this.pdfPage?.cleanup();
   }
-  async _renderAnnotationLayer() {
+  get _textHighlighter() {
+    return (0, _pdf.shadow)(this, "_textHighlighter", new _text_highlighter.TextHighlighter({
+      pageIndex: this.id - 1,
+      eventBus: this.eventBus,
+      findController: this.#layerProperties().findController
+    }));
+  }
+  async #renderAnnotationLayer() {
     let error = null;
     try {
       await this.annotationLayer.render(this.viewport, "display");
     } catch (ex) {
-      console.error(`_renderAnnotationLayer: "${ex}".`);
+      console.error(`#renderAnnotationLayer: "${ex}".`);
       error = ex;
     } finally {
       this.eventBus.dispatch("annotationlayerrendered", {
@@ -138,12 +183,12 @@ class PDFPageView {
       });
     }
   }
-  async _renderAnnotationEditorLayer() {
+  async #renderAnnotationEditorLayer() {
     let error = null;
     try {
       await this.annotationEditorLayer.render(this.viewport, "display");
     } catch (ex) {
-      console.error(`_renderAnnotationEditorLayer: "${ex}".`);
+      console.error(`#renderAnnotationEditorLayer: "${ex}".`);
       error = ex;
     } finally {
       this.eventBus.dispatch("annotationeditorlayerrendered", {
@@ -153,15 +198,15 @@ class PDFPageView {
       });
     }
   }
-  async _renderXfaLayer() {
+  async #renderXfaLayer() {
     let error = null;
     try {
       const result = await this.xfaLayer.render(this.viewport, "display");
-      if (result?.textDivs && this.textHighlighter) {
-        this._buildXfaTextContentItems(result.textDivs);
+      if (result?.textDivs && this._textHighlighter) {
+        this.#buildXfaTextContentItems(result.textDivs);
       }
     } catch (ex) {
-      console.error(`_renderXfaLayer: "${ex}".`);
+      console.error(`#renderXfaLayer: "${ex}".`);
       error = ex;
     } finally {
       this.eventBus.dispatch("xfalayerrendered", {
@@ -171,14 +216,58 @@ class PDFPageView {
       });
     }
   }
-  async _buildXfaTextContentItems(textDivs) {
+  async #renderTextLayer() {
+    const {
+      pdfPage,
+      textLayer,
+      viewport
+    } = this;
+    if (!textLayer) {
+      return;
+    }
+    let error = null;
+    try {
+      if (!textLayer.renderingDone) {
+        const readableStream = pdfPage.streamTextContent({
+          includeMarkedContent: true
+        });
+        textLayer.setTextContentSource(readableStream);
+      }
+      await textLayer.render(viewport);
+    } catch (ex) {
+      if (ex instanceof _pdf.AbortException) {
+        return;
+      }
+      console.error(`#renderTextLayer: "${ex}".`);
+      error = ex;
+    }
+    this.eventBus.dispatch("textlayerrendered", {
+      source: this,
+      pageNumber: this.id,
+      numTextDivs: textLayer.numTextDivs,
+      error
+    });
+    this.#renderStructTreeLayer();
+  }
+  async #renderStructTreeLayer() {
+    if (!this.textLayer) {
+      return;
+    }
+    this.structTreeLayer ||= new _struct_tree_layer_builder.StructTreeLayerBuilder();
+    const tree = await (!this.structTreeLayer.renderingDone ? this.pdfPage.getStructTree() : null);
+    const treeDom = this.structTreeLayer?.render(tree);
+    if (treeDom) {
+      this.canvas?.append(treeDom);
+    }
+  }
+  async #buildXfaTextContentItems(textDivs) {
     const text = await this.pdfPage.getTextContent();
     const items = [];
     for (const item of text.items) {
       items.push(item.str);
     }
-    this.textHighlighter.setTextMapping(textDivs, items);
-    this.textHighlighter.enable();
+    this._textHighlighter.setTextMapping(textDivs, items);
+    this._textHighlighter.enable();
   }
   _resetZoomLayer(removeFromDOM = false) {
     if (!this.zoomLayer) {
@@ -197,22 +286,23 @@ class PDFPageView {
     keepZoomLayer = false,
     keepAnnotationLayer = false,
     keepAnnotationEditorLayer = false,
-    keepXfaLayer = false
+    keepXfaLayer = false,
+    keepTextLayer = false
   } = {}) {
     this.cancelRendering({
       keepAnnotationLayer,
       keepAnnotationEditorLayer,
-      keepXfaLayer
+      keepXfaLayer,
+      keepTextLayer
     });
     this.renderingState = _ui_utils.RenderingStates.INITIAL;
     const div = this.div;
-    div.style.width = Math.floor(this.viewport.width) + "px";
-    div.style.height = Math.floor(this.viewport.height) + "px";
     const childNodes = div.childNodes,
       zoomLayerNode = keepZoomLayer && this.zoomLayer || null,
       annotationLayerNode = keepAnnotationLayer && this.annotationLayer?.div || null,
       annotationEditorLayerNode = keepAnnotationEditorLayer && this.annotationEditorLayer?.div || null,
-      xfaLayerNode = keepXfaLayer && this.xfaLayer?.div || null;
+      xfaLayerNode = keepXfaLayer && this.xfaLayer?.div || null,
+      textLayerNode = keepTextLayer && this.textLayer?.div || null;
     for (let i = childNodes.length - 1; i >= 0; i--) {
       const node = childNodes[i];
       switch (node) {
@@ -220,6 +310,8 @@ class PDFPageView {
         case annotationLayerNode:
         case annotationEditorLayerNode:
         case xfaLayerNode:
+        case textLayerNode:
+        case this.loadingIconDiv:
           continue;
       }
       node.remove();
@@ -230,12 +322,13 @@ class PDFPageView {
     }
     if (annotationEditorLayerNode) {
       this.annotationEditorLayer.hide();
-    } else {
-      this.annotationEditorLayer?.destroy();
     }
     if (xfaLayerNode) {
       this.xfaLayer.hide();
     }
+    if (textLayerNode) {
+      this.textLayer.hide();
+    }
     if (!zoomLayerNode) {
       if (this.canvas) {
         this.paintedViewportMap.delete(this.canvas);
@@ -249,21 +342,21 @@ class PDFPageView {
       this.paintedViewportMap.delete(this.svg);
       delete this.svg;
     }
-    this.loadingIconDiv = document.createElement("div");
-    this.loadingIconDiv.className = "loadingIcon notVisible";
-    if (this._isStandalone) {
-      this.toggleLoadingIconSpinner(true);
+    if (!this.loadingIconDiv) {
+      this.loadingIconDiv = document.createElement("div");
+      this.loadingIconDiv.className = "loadingIcon notVisible";
+      this.loadingIconDiv.setAttribute("role", "img");
+      this.l10n.get("loading").then(msg => {
+        this.loadingIconDiv?.setAttribute("aria-label", msg);
+      });
+      div.append(this.loadingIconDiv);
     }
-    this.loadingIconDiv.setAttribute("role", "img");
-    this.l10n.get("loading").then(msg => {
-      this.loadingIconDiv?.setAttribute("aria-label", msg);
-    });
-    div.append(this.loadingIconDiv);
   }
   update({
     scale = 0,
     rotation = null,
-    optionalContentConfigPromise = null
+    optionalContentConfigPromise = null,
+    drawingDelay = -1
   }) {
     this.scale = scale || this.scale;
     if (typeof rotation === "number") {
@@ -283,6 +376,7 @@ class PDFPageView {
       scale: this.scale * _pdf.PixelsPerInch.PDF_TO_CSS_UNITS,
       rotation: totalRotation
     });
+    this.#setDimensions();
     if (this._isStandalone) {
       _ui_utils.docStyle.setProperty("--scale-factor", this.viewport.scale);
     }
@@ -291,7 +385,8 @@ class PDFPageView {
         target: this.svg,
         redrawAnnotationLayer: true,
         redrawAnnotationEditorLayer: true,
-        redrawXfaLayer: true
+        redrawXfaLayer: true,
+        redrawTextLayer: true
       });
       this.eventBus.dispatch("pagerendered", {
         source: this,
@@ -309,13 +404,27 @@ class PDFPageView {
         isScalingRestricted = true;
       }
     }
+    const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000;
     if (this.canvas) {
-      if (this.useOnlyCssZoom || this.hasRestrictedScaling && isScalingRestricted) {
+      if (postponeDrawing || this.useOnlyCssZoom || this.hasRestrictedScaling && isScalingRestricted) {
+        if (postponeDrawing && this.renderingState !== _ui_utils.RenderingStates.FINISHED) {
+          this.cancelRendering({
+            keepZoomLayer: true,
+            keepAnnotationLayer: true,
+            keepAnnotationEditorLayer: true,
+            keepXfaLayer: true,
+            keepTextLayer: true,
+            cancelExtraDelay: drawingDelay
+          });
+          this.renderingState = _ui_utils.RenderingStates.FINISHED;
+        }
         this.cssTransform({
           target: this.canvas,
           redrawAnnotationLayer: true,
           redrawAnnotationEditorLayer: true,
-          redrawXfaLayer: true
+          redrawXfaLayer: true,
+          redrawTextLayer: !postponeDrawing,
+          hideTextLayer: postponeDrawing
         });
         this.eventBus.dispatch("pagerendered", {
           source: this,
@@ -340,23 +449,29 @@ class PDFPageView {
       keepZoomLayer: true,
       keepAnnotationLayer: true,
       keepAnnotationEditorLayer: true,
-      keepXfaLayer: true
+      keepXfaLayer: true,
+      keepTextLayer: true
     });
   }
   cancelRendering({
     keepAnnotationLayer = false,
     keepAnnotationEditorLayer = false,
-    keepXfaLayer = false
+    keepXfaLayer = false,
+    keepTextLayer = false,
+    cancelExtraDelay = 0
   } = {}) {
     if (this.paintTask) {
-      this.paintTask.cancel();
+      this.paintTask.cancel(cancelExtraDelay);
       this.paintTask = null;
     }
     this.resume = null;
-    if (this.textLayer) {
+    if (this.textLayer && (!keepTextLayer || !this.textLayer.div)) {
       this.textLayer.cancel();
       this.textLayer = null;
     }
+    if (this.structTreeLayer && !this.textLayer) {
+      this.structTreeLayer = null;
+    }
     if (this.annotationLayer && (!keepAnnotationLayer || !this.annotationLayer.div)) {
       this.annotationLayer.cancel();
       this.annotationLayer = null;
@@ -369,74 +484,67 @@ class PDFPageView {
     if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {
       this.xfaLayer.cancel();
       this.xfaLayer = null;
-      this.textHighlighter?.disable();
-    }
-    if (this._onTextLayerRendered) {
-      this.eventBus._off("textlayerrendered", this._onTextLayerRendered);
-      this._onTextLayerRendered = null;
+      this._textHighlighter?.disable();
     }
   }
   cssTransform({
     target,
     redrawAnnotationLayer = false,
     redrawAnnotationEditorLayer = false,
-    redrawXfaLayer = false
+    redrawXfaLayer = false,
+    redrawTextLayer = false,
+    hideTextLayer = false
   }) {
-    const width = this.viewport.width;
-    const height = this.viewport.height;
-    const div = this.div;
-    target.style.width = target.parentNode.style.width = div.style.width = Math.floor(width) + "px";
-    target.style.height = target.parentNode.style.height = div.style.height = Math.floor(height) + "px";
-    const relativeRotation = this.viewport.rotation - this.paintedViewportMap.get(target).rotation;
-    const absRotation = Math.abs(relativeRotation);
-    let scaleX = 1,
-      scaleY = 1;
-    if (absRotation === 90 || absRotation === 270) {
-      scaleX = height / width;
-      scaleY = width / height;
-    }
-    target.style.transform = `rotate(${relativeRotation}deg) scale(${scaleX}, ${scaleY})`;
-    if (this.textLayer) {
-      const textLayerViewport = this.textLayer.viewport;
-      const textRelativeRotation = this.viewport.rotation - textLayerViewport.rotation;
-      const textAbsRotation = Math.abs(textRelativeRotation);
-      let scale = width / textLayerViewport.width;
-      if (textAbsRotation === 90 || textAbsRotation === 270) {
-        scale = width / textLayerViewport.height;
+    if (target instanceof HTMLCanvasElement) {
+      if (!target.hasAttribute("zooming")) {
+        target.setAttribute("zooming", true);
+        const {
+          style
+        } = target;
+        style.width = style.height = "";
       }
-      const textLayerDiv = this.textLayer.textLayerDiv;
-      let transX, transY;
-      switch (textAbsRotation) {
-        case 0:
-          transX = transY = 0;
-          break;
-        case 90:
-          transX = 0;
-          transY = "-" + textLayerDiv.style.height;
-          break;
-        case 180:
-          transX = "-" + textLayerDiv.style.width;
-          transY = "-" + textLayerDiv.style.height;
-          break;
-        case 270:
-          transX = "-" + textLayerDiv.style.width;
-          transY = 0;
-          break;
-        default:
-          console.error("Bad rotation value.");
-          break;
+    } else {
+      const div = this.div;
+      const {
+        width,
+        height
+      } = this.viewport;
+      target.style.width = target.parentNode.style.width = div.style.width = Math.floor(width) + "px";
+      target.style.height = target.parentNode.style.height = div.style.height = Math.floor(height) + "px";
+    }
+    const originalViewport = this.paintedViewportMap.get(target);
+    if (this.viewport !== originalViewport) {
+      const relativeRotation = this.viewport.rotation - originalViewport.rotation;
+      const absRotation = Math.abs(relativeRotation);
+      let scaleX = 1,
+        scaleY = 1;
+      if (absRotation === 90 || absRotation === 270) {
+        const {
+          width,
+          height
+        } = this.viewport;
+        scaleX = height / width;
+        scaleY = width / height;
+      }
+      if (absRotation !== 0) {
+        target.style.transform = `rotate(${relativeRotation}deg) scale(${scaleX}, ${scaleY})`;
       }
-      textLayerDiv.style.transform = `rotate(${textAbsRotation}deg) ` + `scale(${scale}) ` + `translate(${transX}, ${transY})`;
-      textLayerDiv.style.transformOrigin = "0% 0%";
     }
     if (redrawAnnotationLayer && this.annotationLayer) {
-      this._renderAnnotationLayer();
+      this.#renderAnnotationLayer();
     }
     if (redrawAnnotationEditorLayer && this.annotationEditorLayer) {
-      this._renderAnnotationEditorLayer();
+      this.#renderAnnotationEditorLayer();
     }
     if (redrawXfaLayer && this.xfaLayer) {
-      this._renderXfaLayer();
+      this.#renderXfaLayer();
+    }
+    if (this.textLayer) {
+      if (hideTextLayer) {
+        this.textLayer.hide();
+      } else if (redrawTextLayer) {
+        this.#renderTextLayer();
+      }
     }
   }
   get width() {
@@ -448,9 +556,6 @@ class PDFPageView {
   getPagePoint(x, y) {
     return this.viewport.convertToPdfPoint(x, y);
   }
-  toggleLoadingIconSpinner(viewVisible = false) {
-    this.loadingIconDiv?.classList.toggle("notVisible", !viewVisible);
-  }
   draw() {
     if (this.renderingState !== _ui_utils.RenderingStates.INITIAL) {
       console.error("Must be in new state before drawing");
@@ -462,53 +567,43 @@ class PDFPageView {
     } = this;
     if (!pdfPage) {
       this.renderingState = _ui_utils.RenderingStates.FINISHED;
-      if (this.loadingIconDiv) {
-        this.loadingIconDiv.remove();
-        delete this.loadingIconDiv;
-      }
       return Promise.reject(new Error("pdfPage is not loaded"));
     }
     this.renderingState = _ui_utils.RenderingStates.RUNNING;
     const canvasWrapper = document.createElement("div");
-    canvasWrapper.style.width = div.style.width;
-    canvasWrapper.style.height = div.style.height;
     canvasWrapper.classList.add("canvasWrapper");
-    const lastDivBeforeTextDiv = this.annotationLayer?.div || this.annotationEditorLayer?.div;
-    if (lastDivBeforeTextDiv) {
-      lastDivBeforeTextDiv.before(canvasWrapper);
-    } else {
-      div.append(canvasWrapper);
-    }
-    let textLayer = null;
-    if (this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE && this.textLayerFactory) {
+    div.append(canvasWrapper);
+    if (!this.textLayer && this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE && !pdfPage.isPureXfa) {
       this._accessibilityManager ||= new _text_accessibility.TextAccessibilityManager();
-      const textLayerDiv = document.createElement("div");
-      textLayerDiv.className = "textLayer";
-      textLayerDiv.style.width = canvasWrapper.style.width;
-      textLayerDiv.style.height = canvasWrapper.style.height;
-      if (lastDivBeforeTextDiv) {
-        lastDivBeforeTextDiv.before(textLayerDiv);
-      } else {
-        div.append(textLayerDiv);
-      }
-      textLayer = this.textLayerFactory.createTextLayerBuilder({
-        textLayerDiv,
-        pageIndex: this.id - 1,
-        viewport: this.viewport,
-        eventBus: this.eventBus,
-        highlighter: this.textHighlighter,
-        accessibilityManager: this._accessibilityManager
+      this.textLayer = new _text_layer_builder.TextLayerBuilder({
+        highlighter: this._textHighlighter,
+        accessibilityManager: this._accessibilityManager,
+        isOffscreenCanvasSupported: this.isOffscreenCanvasSupported
       });
+      div.append(this.textLayer.div);
     }
-    this.textLayer = textLayer;
-    if (this.#annotationMode !== _pdf.AnnotationMode.DISABLE && this.annotationLayerFactory) {
+    if (!this.annotationLayer && this.#annotationMode !== _pdf.AnnotationMode.DISABLE) {
+      const {
+        annotationStorage,
+        downloadManager,
+        enableScripting,
+        fieldObjectsPromise,
+        hasJSActionsPromise,
+        linkService
+      } = this.#layerProperties();
       this._annotationCanvasMap ||= new Map();
-      this.annotationLayer ||= this.annotationLayerFactory.createAnnotationLayerBuilder({
+      this.annotationLayer = new _annotation_layer_builder.AnnotationLayerBuilder({
         pageDiv: div,
         pdfPage,
+        annotationStorage,
         imageResourcesPath: this.imageResourcesPath,
         renderForms: this.#annotationMode === _pdf.AnnotationMode.ENABLE_FORMS,
+        linkService,
+        downloadManager,
         l10n: this.l10n,
+        enableScripting,
+        hasJSActionsPromise,
+        fieldObjectsPromise,
         annotationCanvasMap: this._annotationCanvasMap,
         accessibilityManager: this._accessibilityManager
       });
@@ -540,10 +635,6 @@ class PDFPageView {
       }
       this._renderError = error;
       this.renderingState = _ui_utils.RenderingStates.FINISHED;
-      if (this.loadingIconDiv) {
-        this.loadingIconDiv.remove();
-        delete this.loadingIconDiv;
-      }
       this._resetZoomLayer(true);
       this.#useThumbnailCanvas.regularAnnotations = !paintTask.separateAnnots;
       this.eventBus.dispatch("pagerendered", {
@@ -561,64 +652,45 @@ class PDFPageView {
     paintTask.onRenderContinue = renderContinueCallback;
     this.paintTask = paintTask;
     const resultPromise = paintTask.promise.then(() => {
-      return finishPaintTask(null).then(() => {
-        if (textLayer) {
-          const readableStream = pdfPage.streamTextContent({
-            includeMarkedContent: true
-          });
-          textLayer.setTextContentStream(readableStream);
-          textLayer.render();
-        }
+      return finishPaintTask(null).then(async () => {
+        this.#renderTextLayer();
         if (this.annotationLayer) {
-          this._renderAnnotationLayer().then(() => {
-            if (this.annotationEditorLayerFactory) {
-              this.annotationEditorLayer ||= this.annotationEditorLayerFactory.createAnnotationEditorLayerBuilder({
-                pageDiv: div,
-                pdfPage,
-                l10n: this.l10n,
-                accessibilityManager: this._accessibilityManager
-              });
-              this._renderAnnotationEditorLayer();
-            }
+          await this.#renderAnnotationLayer();
+        }
+        if (!this.annotationEditorLayer) {
+          const {
+            annotationEditorUIManager
+          } = this.#layerProperties();
+          if (!annotationEditorUIManager) {
+            return;
+          }
+          this.annotationEditorLayer = new _annotation_editor_layer_builder.AnnotationEditorLayerBuilder({
+            uiManager: annotationEditorUIManager,
+            pageDiv: div,
+            pdfPage,
+            l10n: this.l10n,
+            accessibilityManager: this._accessibilityManager
           });
         }
+        this.#renderAnnotationEditorLayer();
       });
     }, function (reason) {
       return finishPaintTask(reason);
     });
-    if (this.xfaLayerFactory) {
-      this.xfaLayer ||= this.xfaLayerFactory.createXfaLayerBuilder({
-        pageDiv: div,
-        pdfPage
-      });
-      this._renderXfaLayer();
-    }
-    if (this.structTreeLayerFactory && this.textLayer && this.canvas) {
-      this._onTextLayerRendered = event => {
-        if (event.pageNumber !== this.id) {
-          return;
-        }
-        this.eventBus._off("textlayerrendered", this._onTextLayerRendered);
-        this._onTextLayerRendered = null;
-        if (!this.canvas) {
-          return;
-        }
-        this.pdfPage.getStructTree().then(tree => {
-          if (!tree) {
-            return;
-          }
-          if (!this.canvas) {
-            return;
-          }
-          const treeDom = this.structTreeLayer.render(tree);
-          treeDom.classList.add("structTree");
-          this.canvas.append(treeDom);
+    if (pdfPage.isPureXfa) {
+      if (!this.xfaLayer) {
+        const {
+          annotationStorage,
+          linkService
+        } = this.#layerProperties();
+        this.xfaLayer = new _xfa_layer_builder.XfaLayerBuilder({
+          pageDiv: div,
+          pdfPage,
+          annotationStorage,
+          linkService
         });
-      };
-      this.eventBus._on("textlayerrendered", this._onTextLayerRendered);
-      this.structTreeLayer = this.structTreeLayerFactory.createStructTreeLayerBuilder({
-        pdfPage
-      });
+      }
+      this.#renderXfaLayer();
     }
     div.setAttribute("data-loaded", true);
     this.eventBus.dispatch("pagerender", {
@@ -634,14 +706,18 @@ class PDFPageView {
       onRenderContinue(cont) {
         cont();
       },
-      cancel() {
-        renderTask.cancel();
+      cancel(extraDelay = 0) {
+        renderTask.cancel(extraDelay);
       },
       get separateAnnots() {
         return renderTask.separateAnnots;
       }
     };
     const viewport = this.viewport;
+    const {
+      width,
+      height
+    } = viewport;
     const canvas = document.createElement("canvas");
     canvas.setAttribute("role", "presentation");
     canvas.hidden = true;
@@ -662,11 +738,11 @@ class PDFPageView {
       const actualSizeViewport = viewport.clone({
         scale: _pdf.PixelsPerInch.PDF_TO_CSS_UNITS
       });
-      outputScale.sx *= actualSizeViewport.width / viewport.width;
-      outputScale.sy *= actualSizeViewport.height / viewport.height;
+      outputScale.sx *= actualSizeViewport.width / width;
+      outputScale.sy *= actualSizeViewport.height / height;
     }
     if (this.maxCanvasPixels > 0) {
-      const pixelsInViewport = viewport.width * viewport.height;
+      const pixelsInViewport = width * height;
       const maxScale = Math.sqrt(this.maxCanvasPixels / pixelsInViewport);
       if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
         outputScale.sx = maxScale;
@@ -680,14 +756,17 @@ class PDFPageView {
     const sfy = (0, _ui_utils.approximateFraction)(outputScale.sy);
     canvas.width = (0, _ui_utils.roundToDivide)(viewport.width * outputScale.sx, sfx[0]);
     canvas.height = (0, _ui_utils.roundToDivide)(viewport.height * outputScale.sy, sfy[0]);
-    canvas.style.width = (0, _ui_utils.roundToDivide)(viewport.width, sfx[1]) + "px";
-    canvas.style.height = (0, _ui_utils.roundToDivide)(viewport.height, sfy[1]) + "px";
+    const {
+      style
+    } = canvas;
+    style.width = (0, _ui_utils.roundToDivide)(viewport.width, sfx[1]) + "px";
+    style.height = (0, _ui_utils.roundToDivide)(viewport.height, sfy[1]) + "px";
     this.paintedViewportMap.set(canvas, viewport);
     const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null;
     const renderContext = {
       canvasContext: ctx,
       transform,
-      viewport: this.viewport,
+      viewport,
       annotationMode: this.#annotationMode,
       optionalContentConfigPromise: this._optionalContentConfigPromise,
       annotationCanvasMap: this._annotationCanvasMap,

+ 7 - 26
lib/web/pdf_scripting_manager.js

@@ -39,7 +39,6 @@ class PDFScriptingManager {
     this._closeCapability = null;
     this._destroyCapability = null;
     this._scripting = null;
-    this._mouseState = Object.create(null);
     this._ready = false;
     this._eventBus = eventBus;
     this._sandboxBundleSrc = sandboxBundleSrc;
@@ -110,18 +109,9 @@ class PDFScriptingManager {
       });
       this._closeCapability?.resolve();
     });
-    this._domEvents.set("mousedown", event => {
-      this._mouseState.isDown = true;
-    });
-    this._domEvents.set("mouseup", event => {
-      this._mouseState.isDown = false;
-    });
     for (const [name, listener] of this._internalEvents) {
       this._eventBus._on(name, listener);
     }
-    for (const [name, listener] of this._domEvents) {
-      window.addEventListener(name, listener, true);
-    }
     try {
       const docProperties = await this._getDocProperties();
       if (pdfDocument !== this._pdfDocument) {
@@ -182,9 +172,6 @@ class PDFScriptingManager {
       name: "DidPrint"
     });
   }
-  get mouseState() {
-    return this._mouseState;
-  }
   get destroyPromise() {
     return this._destroyCapability?.promise || null;
   }
@@ -194,9 +181,6 @@ class PDFScriptingManager {
   get _internalEvents() {
     return (0, _pdf.shadow)(this, "_internalEvents", new Map());
   }
-  get _domEvents() {
-    return (0, _pdf.shadow)(this, "_domEvents", new Map());
-  }
   get _pageOpenPending() {
     return (0, _pdf.shadow)(this, "_pageOpenPending", new Set());
   }
@@ -220,12 +204,14 @@ class PDFScriptingManager {
           console.error(value);
           break;
         case "layout":
-          if (isInPresentationMode) {
-            return;
+          {
+            if (isInPresentationMode) {
+              return;
+            }
+            const modes = (0, _ui_utils.apiPageLayoutToViewerModes)(value);
+            this._pdfViewer.spreadMode = modes.spreadMode;
+            break;
           }
-          const modes = (0, _ui_utils.apiPageLayoutToViewerModes)(value);
-          this._pdfViewer.spreadMode = modes.spreadMode;
-          break;
         case "page-num":
           this._pdfViewer.currentPageNumber = value + 1;
           break;
@@ -386,14 +372,9 @@ class PDFScriptingManager {
       this._eventBus._off(name, listener);
     }
     this._internalEvents.clear();
-    for (const [name, listener] of this._domEvents) {
-      window.removeEventListener(name, listener, true);
-    }
-    this._domEvents.clear();
     this._pageOpenPending.clear();
     this._visitedPages.clear();
     this._scripting = null;
-    delete this._mouseState.isDown;
     this._ready = false;
     this._destroyCapability?.resolve();
   }

+ 27 - 27
lib/web/pdf_viewer.component.js

@@ -30,30 +30,7 @@ Object.defineProperty(exports, "AnnotationLayerBuilder", {
     return _annotation_layer_builder.AnnotationLayerBuilder;
   }
 });
-Object.defineProperty(exports, "DefaultAnnotationLayerFactory", {
-  enumerable: true,
-  get: function () {
-    return _default_factory.DefaultAnnotationLayerFactory;
-  }
-});
-Object.defineProperty(exports, "DefaultStructTreeLayerFactory", {
-  enumerable: true,
-  get: function () {
-    return _default_factory.DefaultStructTreeLayerFactory;
-  }
-});
-Object.defineProperty(exports, "DefaultTextLayerFactory", {
-  enumerable: true,
-  get: function () {
-    return _default_factory.DefaultTextLayerFactory;
-  }
-});
-Object.defineProperty(exports, "DefaultXfaLayerFactory", {
-  enumerable: true,
-  get: function () {
-    return _default_factory.DefaultXfaLayerFactory;
-  }
-});
+exports.DefaultXfaLayerFactory = exports.DefaultTextLayerFactory = exports.DefaultStructTreeLayerFactory = exports.DefaultAnnotationLayerFactory = void 0;
 Object.defineProperty(exports, "DownloadManager", {
   enumerable: true,
   get: function () {
@@ -180,7 +157,6 @@ Object.defineProperty(exports, "parseQueryString", {
     return _ui_utils.parseQueryString;
   }
 });
-var _default_factory = require("./default_factory.js");
 var _pdf_link_service = require("./pdf_link_service.js");
 var _ui_utils = require("./ui_utils.js");
 var _annotation_layer_builder = require("./annotation_layer_builder.js");
@@ -197,5 +173,29 @@ var _pdf_viewer = require("./pdf_viewer.js");
 var _struct_tree_layer_builder = require("./struct_tree_layer_builder.js");
 var _text_layer_builder = require("./text_layer_builder.js");
 var _xfa_layer_builder = require("./xfa_layer_builder.js");
-const pdfjsVersion = '3.1.81';
-const pdfjsBuild = '0766898d5';
+const pdfjsVersion = '3.2.146';
+const pdfjsBuild = '3fd2a3548';
+class DefaultAnnotationLayerFactory {
+  constructor() {
+    throw new Error("The `DefaultAnnotationLayerFactory` has been removed, " + "please use the `annotationMode` option when initializing " + "the `PDFPageView`-instance to control AnnotationLayer rendering.");
+  }
+}
+exports.DefaultAnnotationLayerFactory = DefaultAnnotationLayerFactory;
+class DefaultStructTreeLayerFactory {
+  constructor() {
+    throw new Error("The `DefaultStructTreeLayerFactory` has been removed, " + "this functionality is automatically enabled when the TextLayer is used.");
+  }
+}
+exports.DefaultStructTreeLayerFactory = DefaultStructTreeLayerFactory;
+class DefaultTextLayerFactory {
+  constructor() {
+    throw new Error("The `DefaultTextLayerFactory` has been removed, " + "please use the `textLayerMode` option when initializing " + "the `PDFPageView`-instance to control TextLayer rendering.");
+  }
+}
+exports.DefaultTextLayerFactory = DefaultTextLayerFactory;
+class DefaultXfaLayerFactory {
+  constructor() {
+    throw new Error("The `DefaultXfaLayerFactory` has been removed, " + "please use the `enableXfa` option when calling " + "the `getDocument`-function to control XfaLayer rendering.");
+  }
+}
+exports.DefaultXfaLayerFactory = DefaultXfaLayerFactory;

+ 117 - 165
lib/web/pdf_viewer.js

@@ -27,16 +27,10 @@ Object.defineProperty(exports, "__esModule", {
 exports.PagesCountLimit = exports.PDFViewer = exports.PDFPageViewBuffer = void 0;
 var _pdf = require("../pdf");
 var _ui_utils = require("./ui_utils.js");
-var _annotation_editor_layer_builder = require("./annotation_editor_layer_builder.js");
-var _annotation_layer_builder = require("./annotation_layer_builder.js");
 var _l10n_utils = require("./l10n_utils.js");
 var _pdf_page_view = require("./pdf_page_view.js");
 var _pdf_rendering_queue = require("./pdf_rendering_queue.js");
 var _pdf_link_service = require("./pdf_link_service.js");
-var _struct_tree_layer_builder = require("./struct_tree_layer_builder.js");
-var _text_highlighter = require("./text_highlighter.js");
-var _text_layer_builder = require("./text_layer_builder.js");
-var _xfa_layer_builder = require("./xfa_layer_builder.js");
 const DEFAULT_CACHE_SIZE = 10;
 const ENABLE_PERMISSIONS_CLASS = "enablePermissions";
 const PagesCountLimit = {
@@ -102,16 +96,20 @@ class PDFViewer {
   #annotationEditorMode = _pdf.AnnotationEditorType.NONE;
   #annotationEditorUIManager = null;
   #annotationMode = _pdf.AnnotationMode.ENABLE_FORMS;
+  #containerTopLeft = null;
   #enablePermissions = false;
   #previousContainerHeight = 0;
+  #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));
   #scrollModePageState = null;
   #onVisibilityChange = null;
+  #scaleTimeoutId = null;
   constructor(options) {
-    const viewerVersion = '3.1.81';
+    const viewerVersion = '3.2.146';
     if (_pdf.version !== viewerVersion) {
       throw new Error(`The API version "${_pdf.version}" does not match the Viewer version "${viewerVersion}".`);
     }
     this.container = options.container;
+    this.#resizeObserver.observe(this.container);
     this.viewer = options.viewer || options.container.firstElementChild;
     if (!(this.container?.tagName.toUpperCase() === "DIV" && this.viewer?.tagName.toUpperCase() === "DIV")) {
       throw new Error("Invalid `container` and/or `viewer` option.");
@@ -132,6 +130,7 @@ class PDFViewer {
     this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
     this.renderer = options.renderer || _ui_utils.RendererType.CANVAS;
     this.useOnlyCssZoom = options.useOnlyCssZoom || false;
+    this.isOffscreenCanvasSupported = options.isOffscreenCanvasSupported ?? true;
     this.maxCanvasPixels = options.maxCanvasPixels;
     this.l10n = options.l10n || _l10n_utils.NullL10n;
     this.#enablePermissions = options.enablePermissions || false;
@@ -156,7 +155,7 @@ class PDFViewer {
     if (this.removePageBorders) {
       this.viewer.classList.add("removePageBorders");
     }
-    this.updateContainerHeightCss();
+    this.#updateContainerHeightCss();
   }
   get pagesCount() {
     return this._pages.length;
@@ -243,7 +242,9 @@ class PDFViewer {
     if (!this.pdfDocument) {
       return;
     }
-    this._setScale(val, false);
+    this._setScale(val, {
+      noScroll: false
+    });
   }
   get currentScaleValue() {
     return this._currentScaleValue;
@@ -252,7 +253,9 @@ class PDFViewer {
     if (!this.pdfDocument) {
       return;
     }
-    this._setScale(val, false);
+    this._setScale(val, {
+      noScroll: false
+    });
   }
   get pagesRotation() {
     return this._pagesRotation;
@@ -273,14 +276,13 @@ class PDFViewer {
     }
     this._pagesRotation = rotation;
     const pageNumber = this._currentPageNumber;
-    const updateArgs = {
+    this.refresh(true, {
       rotation
-    };
-    for (const pageView of this._pages) {
-      pageView.update(updateArgs);
-    }
+    });
     if (this._currentScaleValue) {
-      this._setScale(this._currentScaleValue, true);
+      this._setScale(this._currentScaleValue, {
+        noScroll: true
+      });
     }
     this.eventBus.dispatch("rotationchanging", {
       source: this,
@@ -300,6 +302,35 @@ class PDFViewer {
   get pagesPromise() {
     return this.pdfDocument ? this._pagesCapability.promise : null;
   }
+  #layerProperties() {
+    const self = this;
+    return {
+      get annotationEditorUIManager() {
+        return self.#annotationEditorUIManager;
+      },
+      get annotationStorage() {
+        return self.pdfDocument?.annotationStorage;
+      },
+      get downloadManager() {
+        return self.downloadManager;
+      },
+      get enableScripting() {
+        return !!self._scriptingManager;
+      },
+      get fieldObjectsPromise() {
+        return self.pdfDocument?.getFieldObjects();
+      },
+      get findController() {
+        return self.findController;
+      },
+      get hasJSActionsPromise() {
+        return self.pdfDocument?.hasJSActions();
+      },
+      get linkService() {
+        return self.linkService;
+      }
+    };
+  }
   #initializePermissions(permissions) {
     const params = {
       annotationEditorMode: this.#annotationEditorMode,
@@ -355,7 +386,6 @@ class PDFViewer {
     if (!pdfDocument) {
       return;
     }
-    const isPureXfa = pdfDocument.isPureXfa;
     const pagesCount = pdfDocument.numPages;
     const firstPagePromise = pdfDocument.getPage(1);
     const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig();
@@ -410,10 +440,10 @@ class PDFViewer {
       } = this.#initializePermissions(permissions);
       if (annotationEditorMode !== _pdf.AnnotationEditorType.DISABLE) {
         const mode = annotationEditorMode;
-        if (isPureXfa) {
+        if (pdfDocument.isPureXfa) {
           console.warn("Warning: XFA-editing is not implemented.");
         } else if (isValidAnnotationEditorMode(mode)) {
-          this.#annotationEditorUIManager = new _pdf.AnnotationEditorUIManager(this.container, this.eventBus);
+          this.#annotationEditorUIManager = new _pdf.AnnotationEditorUIManager(this.container, this.eventBus, pdfDocument?.annotationStorage);
           if (mode !== _pdf.AnnotationEditorType.NONE) {
             this.#annotationEditorUIManager.updateMode(mode);
           }
@@ -421,15 +451,13 @@ class PDFViewer {
           console.error(`Invalid AnnotationEditor mode: ${mode}`);
         }
       }
+      const layerProperties = this.#layerProperties.bind(this);
       const viewerElement = this._scrollMode === _ui_utils.ScrollMode.PAGE ? null : this.viewer;
       const scale = this.currentScale;
       const viewport = firstPdfPage.getViewport({
         scale: scale * _pdf.PixelsPerInch.PDF_TO_CSS_UNITS
       });
-      const textLayerFactory = textLayerMode !== _ui_utils.TextLayerMode.DISABLE && !isPureXfa ? this : null;
-      const annotationLayerFactory = annotationMode !== _pdf.AnnotationMode.DISABLE ? this : null;
-      const xfaLayerFactory = isPureXfa ? this : null;
-      const annotationEditorLayerFactory = this.#annotationEditorUIManager ? this : null;
+      _ui_utils.docStyle.setProperty("--scale-factor", viewport.scale);
       for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
         const pageView = new _pdf_page_view.PDFPageView({
           container: viewerElement,
@@ -439,20 +467,16 @@ class PDFViewer {
           defaultViewport: viewport.clone(),
           optionalContentConfigPromise,
           renderingQueue: this.renderingQueue,
-          textLayerFactory,
           textLayerMode,
-          annotationLayerFactory,
           annotationMode,
-          xfaLayerFactory,
-          annotationEditorLayerFactory,
-          textHighlighterFactory: this,
-          structTreeLayerFactory: this,
           imageResourcesPath: this.imageResourcesPath,
           renderer: this.renderer,
           useOnlyCssZoom: this.useOnlyCssZoom,
+          isOffscreenCanvasSupported: this.isOffscreenCanvasSupported,
           maxCanvasPixels: this.maxCanvasPixels,
           pageColors: this.pageColors,
-          l10n: this.l10n
+          l10n: this.l10n,
+          layerProperties
         });
         this._pages.push(pageView);
       }
@@ -665,7 +689,11 @@ class PDFViewer {
   #isSameScale(newScale) {
     return newScale === this._currentScale || Math.abs(newScale - this._currentScale) < 1e-15;
   }
-  _setScaleUpdatePages(newScale, newValue, noScroll = false, preset = false) {
+  _setScaleUpdatePages(newScale, newValue, {
+    noScroll = false,
+    preset = false,
+    drawingDelay = -1
+  }) {
     this._currentScaleValue = newValue.toString();
     if (this.#isSameScale(newScale)) {
       if (preset) {
@@ -678,11 +706,16 @@ class PDFViewer {
       return;
     }
     _ui_utils.docStyle.setProperty("--scale-factor", newScale * _pdf.PixelsPerInch.PDF_TO_CSS_UNITS);
-    const updateArgs = {
-      scale: newScale
-    };
-    for (const pageView of this._pages) {
-      pageView.update(updateArgs);
+    const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000;
+    this.refresh(true, {
+      scale: newScale,
+      drawingDelay: postponeDrawing ? drawingDelay : -1
+    });
+    if (postponeDrawing) {
+      this.#scaleTimeoutId = setTimeout(() => {
+        this.#scaleTimeoutId = null;
+        this.refresh();
+      }, drawingDelay);
     }
     this._currentScale = newScale;
     if (!noScroll) {
@@ -708,7 +741,6 @@ class PDFViewer {
     if (this.defaultRenderingQueue) {
       this.update();
     }
-    this.updateContainerHeightCss();
   }
   get _pageWidthScaleFactor() {
     if (this._spreadMode !== _ui_utils.SpreadMode.NONE && this._scrollMode !== _ui_utils.ScrollMode.HORIZONTAL) {
@@ -716,10 +748,11 @@ class PDFViewer {
     }
     return 1;
   }
-  _setScale(value, noScroll = false) {
+  _setScale(value, options) {
     let scale = parseFloat(value);
     if (scale > 0) {
-      this._setScaleUpdatePages(scale, value, noScroll, false);
+      options.preset = false;
+      this._setScaleUpdatePages(scale, value, options);
     } else {
       const currentPage = this._pages[this._currentPageNumber - 1];
       if (!currentPage) {
@@ -729,6 +762,9 @@ class PDFViewer {
         vPadding = _ui_utils.VERTICAL_PADDING;
       if (this.isInPresentationMode) {
         hPadding = vPadding = 4;
+        if (this._spreadMode !== _ui_utils.SpreadMode.NONE) {
+          hPadding *= 2;
+        }
       } else if (this.removePageBorders) {
         hPadding = vPadding = 0;
       } else if (this._scrollMode === _ui_utils.ScrollMode.HORIZONTAL) {
@@ -757,13 +793,16 @@ class PDFViewer {
           console.error(`_setScale: "${value}" is an unknown zoom value.`);
           return;
       }
-      this._setScaleUpdatePages(scale, value, noScroll, true);
+      options.preset = true;
+      this._setScaleUpdatePages(scale, value, options);
     }
   }
   #resetCurrentPageView() {
     const pageView = this._pages[this._currentPageNumber - 1];
     if (this.isInPresentationMode) {
-      this._setScale(this._currentScaleValue, true);
+      this._setScale(this._currentScaleValue, {
+        noScroll: true
+      });
     }
     this.#scrollIntoView(pageView);
   }
@@ -1023,24 +1062,11 @@ class PDFViewer {
     }
     return this.scroll.down;
   }
-  #toggleLoadingIconSpinner(visibleIds) {
-    for (const id of visibleIds) {
-      const pageView = this._pages[id - 1];
-      pageView?.toggleLoadingIconSpinner(true);
-    }
-    for (const pageView of this.#buffer) {
-      if (visibleIds.has(pageView.id)) {
-        continue;
-      }
-      pageView.toggleLoadingIconSpinner(false);
-    }
-  }
   forceRendering(currentlyVisiblePages) {
     const visiblePages = currentlyVisiblePages || this._getVisiblePages();
     const scrollAhead = this.#getScrollAhead(visiblePages);
     const preRenderExtra = this._spreadMode !== _ui_utils.SpreadMode.NONE && this._scrollMode !== _ui_utils.ScrollMode.HORIZONTAL;
     const pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, scrollAhead, preRenderExtra);
-    this.#toggleLoadingIconSpinner(visiblePages.ids);
     if (pageView) {
       this.#ensurePdfPageLoaded(pageView).then(() => {
         this.renderingQueue.renderView(pageView);
@@ -1049,100 +1075,6 @@ class PDFViewer {
     }
     return false;
   }
-  createTextLayerBuilder({
-    textLayerDiv,
-    pageIndex,
-    viewport,
-    eventBus,
-    highlighter,
-    accessibilityManager = null
-  }) {
-    return new _text_layer_builder.TextLayerBuilder({
-      textLayerDiv,
-      eventBus,
-      pageIndex,
-      viewport,
-      highlighter,
-      accessibilityManager
-    });
-  }
-  createTextHighlighter({
-    pageIndex,
-    eventBus
-  }) {
-    return new _text_highlighter.TextHighlighter({
-      eventBus,
-      pageIndex,
-      findController: this.isInPresentationMode ? null : this.findController
-    });
-  }
-  createAnnotationLayerBuilder({
-    pageDiv,
-    pdfPage,
-    annotationStorage = this.pdfDocument?.annotationStorage,
-    imageResourcesPath = "",
-    renderForms = true,
-    l10n = _l10n_utils.NullL10n,
-    enableScripting = this.enableScripting,
-    hasJSActionsPromise = this.pdfDocument?.hasJSActions(),
-    mouseState = this._scriptingManager?.mouseState,
-    fieldObjectsPromise = this.pdfDocument?.getFieldObjects(),
-    annotationCanvasMap = null,
-    accessibilityManager = null
-  }) {
-    return new _annotation_layer_builder.AnnotationLayerBuilder({
-      pageDiv,
-      pdfPage,
-      annotationStorage,
-      imageResourcesPath,
-      renderForms,
-      linkService: this.linkService,
-      downloadManager: this.downloadManager,
-      l10n,
-      enableScripting,
-      hasJSActionsPromise,
-      mouseState,
-      fieldObjectsPromise,
-      annotationCanvasMap,
-      accessibilityManager
-    });
-  }
-  createAnnotationEditorLayerBuilder({
-    uiManager = this.#annotationEditorUIManager,
-    pageDiv,
-    pdfPage,
-    accessibilityManager = null,
-    l10n,
-    annotationStorage = this.pdfDocument?.annotationStorage
-  }) {
-    return new _annotation_editor_layer_builder.AnnotationEditorLayerBuilder({
-      uiManager,
-      pageDiv,
-      pdfPage,
-      annotationStorage,
-      accessibilityManager,
-      l10n
-    });
-  }
-  createXfaLayerBuilder({
-    pageDiv,
-    pdfPage,
-    annotationStorage = this.pdfDocument?.annotationStorage
-  }) {
-    return new _xfa_layer_builder.XfaLayerBuilder({
-      pageDiv,
-      pdfPage,
-      annotationStorage,
-      linkService: this.linkService
-    });
-  }
-  createStructTreeLayerBuilder({
-    pdfPage
-  }) {
-    return new _struct_tree_layer_builder.StructTreeLayerBuilder({
-      pdfPage
-    });
-  }
   get hasEqualPageSizes() {
     const firstPageView = this._pages[0];
     for (let i = 1, ii = this._pages.length; i < ii; ++i) {
@@ -1193,13 +1125,9 @@ class PDFViewer {
       return;
     }
     this._optionalContentConfigPromise = promise;
-    const updateArgs = {
+    this.refresh(false, {
       optionalContentConfigPromise: promise
-    };
-    for (const pageView of this._pages) {
-      pageView.update(updateArgs);
-    }
-    this.update();
+    });
     this.eventBus.dispatch("optionalcontentconfigchanged", {
       source: this,
       promise
@@ -1240,7 +1168,9 @@ class PDFViewer {
       this._updateSpreadMode();
     }
     if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
-      this._setScale(this._currentScaleValue, true);
+      this._setScale(this._currentScaleValue, {
+        noScroll: true
+      });
     }
     this._setCurrentPageNumber(pageNumber, true);
     this.update();
@@ -1296,7 +1226,9 @@ class PDFViewer {
       return;
     }
     if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
-      this._setScale(this._currentScaleValue, true);
+      this._setScale(this._currentScaleValue, {
+        noScroll: true
+      });
     }
     this._setCurrentPageNumber(pageNumber, true);
     this.update();
@@ -1422,31 +1354,46 @@ class PDFViewer {
     this.currentPageNumber = Math.max(currentPageNumber - advance, 1);
     return true;
   }
-  increaseScale(steps = 1) {
+  increaseScale(steps = 1, options = null) {
     let newScale = this._currentScale;
     do {
       newScale = (newScale * _ui_utils.DEFAULT_SCALE_DELTA).toFixed(2);
       newScale = Math.ceil(newScale * 10) / 10;
       newScale = Math.min(_ui_utils.MAX_SCALE, newScale);
     } while (--steps > 0 && newScale < _ui_utils.MAX_SCALE);
-    this.currentScaleValue = newScale;
+    options ||= Object.create(null);
+    options.noScroll = false;
+    this._setScale(newScale, options);
   }
-  decreaseScale(steps = 1) {
+  decreaseScale(steps = 1, options = null) {
     let newScale = this._currentScale;
     do {
       newScale = (newScale / _ui_utils.DEFAULT_SCALE_DELTA).toFixed(2);
       newScale = Math.floor(newScale * 10) / 10;
       newScale = Math.max(_ui_utils.MIN_SCALE, newScale);
     } while (--steps > 0 && newScale > _ui_utils.MIN_SCALE);
-    this.currentScaleValue = newScale;
+    options ||= Object.create(null);
+    options.noScroll = false;
+    this._setScale(newScale, options);
   }
-  updateContainerHeightCss() {
-    const height = this.container.clientHeight;
+  #updateContainerHeightCss(height = this.container.clientHeight) {
     if (height !== this.#previousContainerHeight) {
       this.#previousContainerHeight = height;
       _ui_utils.docStyle.setProperty("--viewer-container-height", `${height}px`);
     }
   }
+  #resizeObserverCallback(entries) {
+    for (const entry of entries) {
+      if (entry.target === this.container) {
+        this.#updateContainerHeightCss(Math.floor(entry.borderBoxSize[0].blockSize));
+        this.#containerTopLeft = null;
+        break;
+      }
+    }
+  }
+  get containerTopLeft() {
+    return this.#containerTopLeft ||= [this.container.offsetTop, this.container.offsetLeft];
+  }
   get annotationEditorMode() {
     return this.#annotationEditorUIManager ? this.#annotationEditorMode : _pdf.AnnotationEditorType.DISABLE;
   }
@@ -1479,15 +1426,20 @@ class PDFViewer {
     }
     this.#annotationEditorUIManager.updateParams(type, value);
   }
-  refresh() {
+  refresh(noUpdate = false, updateArgs = Object.create(null)) {
     if (!this.pdfDocument) {
       return;
     }
-    const updateArgs = {};
     for (const pageView of this._pages) {
       pageView.update(updateArgs);
     }
-    this.update();
+    if (this.#scaleTimeoutId !== null) {
+      clearTimeout(this.#scaleTimeoutId);
+      this.#scaleTimeoutId = null;
+    }
+    if (!noUpdate) {
+      this.update();
+    }
   }
 }
 exports.PDFViewer = PDFViewer;

+ 1 - 0
lib/web/preferences.js

@@ -31,6 +31,7 @@ class BasePreferences {
     "annotationEditorMode": 0,
     "annotationMode": 2,
     "cursorToolOnLoad": 0,
+    "defaultZoomDelay": -1,
     "defaultZoomValue": "",
     "disablePageLabels": false,
     "enablePermissions": false,

+ 14 - 10
lib/web/struct_tree_layer_builder.js

@@ -69,15 +69,19 @@ const PDF_ROLE_TO_HTML_ROLE = {
 };
 const HEADING_PATTERN = /^H(\d+)$/;
 class StructTreeLayerBuilder {
-  constructor({
-    pdfPage
-  }) {
-    this.pdfPage = pdfPage;
+  #treeDom = undefined;
+  get renderingDone() {
+    return this.#treeDom !== undefined;
   }
   render(structTree) {
-    return this._walk(structTree);
+    if (this.#treeDom !== undefined) {
+      return this.#treeDom;
+    }
+    const treeDom = this.#walk(structTree);
+    treeDom?.classList.add("structTree");
+    return this.#treeDom = treeDom;
   }
-  _setAttributes(structElement, htmlElement) {
+  #setAttributes(structElement, htmlElement) {
     if (structElement.alt !== undefined) {
       htmlElement.setAttribute("aria-label", structElement.alt);
     }
@@ -88,7 +92,7 @@ class StructTreeLayerBuilder {
       htmlElement.setAttribute("lang", structElement.lang);
     }
   }
-  _walk(node) {
+  #walk(node) {
     if (!node) {
       return null;
     }
@@ -105,13 +109,13 @@ class StructTreeLayerBuilder {
         element.setAttribute("role", PDF_ROLE_TO_HTML_ROLE[role]);
       }
     }
-    this._setAttributes(node, element);
+    this.#setAttributes(node, element);
     if (node.children) {
       if (node.children.length === 1 && "id" in node.children[0]) {
-        this._setAttributes(node.children[0], element);
+        this.#setAttributes(node.children[0], element);
       } else {
         for (const kid of node.children) {
-          element.append(this._walk(kid));
+          element.append(this.#walk(kid));
         }
       }
     }

+ 4 - 3
lib/web/text_highlighter.js

@@ -71,6 +71,7 @@ class TextHighlighter {
       this.eventBus._off("updatetextlayermatches", this._onUpdateTextLayerMatches);
       this._onUpdateTextLayerMatches = null;
     }
+    this._updateMatches(true);
   }
   _convertMatches(matches, matchesLength) {
     if (!matches) {
@@ -203,8 +204,8 @@ class TextHighlighter {
       appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
     }
   }
-  _updateMatches() {
-    if (!this.enabled) {
+  _updateMatches(reset = false) {
+    if (!this.enabled && !reset) {
       return;
     }
     const {
@@ -226,7 +227,7 @@ class TextHighlighter {
       }
       clearedUntilDivIdx = match.end.divIdx + 1;
     }
-    if (!findController?.highlightMatches) {
+    if (!findController?.highlightMatches || reset) {
       return;
     }
     const pageMatches = findController.pageMatches[pageIdx] || null;

+ 71 - 39
lib/web/text_layer_builder.js

@@ -27,63 +27,94 @@ Object.defineProperty(exports, "__esModule", {
 exports.TextLayerBuilder = void 0;
 var _pdf = require("../pdf");
 class TextLayerBuilder {
+  #rotation = 0;
+  #scale = 0;
+  #textContentSource = null;
   constructor({
-    textLayerDiv,
-    eventBus,
-    pageIndex,
-    viewport,
     highlighter = null,
-    accessibilityManager = null
+    accessibilityManager = null,
+    isOffscreenCanvasSupported = true
   }) {
-    this.textLayerDiv = textLayerDiv;
-    this.eventBus = eventBus;
-    this.textContent = null;
     this.textContentItemsStr = [];
-    this.textContentStream = null;
     this.renderingDone = false;
-    this.pageNumber = pageIndex + 1;
-    this.viewport = viewport;
     this.textDivs = [];
+    this.textDivProperties = new WeakMap();
     this.textLayerRenderTask = null;
     this.highlighter = highlighter;
     this.accessibilityManager = accessibilityManager;
-    this.#bindMouse();
+    this.isOffscreenCanvasSupported = isOffscreenCanvasSupported;
+    this.div = document.createElement("div");
+    this.div.className = "textLayer";
+    this.hide();
   }
   #finishRendering() {
     this.renderingDone = true;
     const endOfContent = document.createElement("div");
     endOfContent.className = "endOfContent";
-    this.textLayerDiv.append(endOfContent);
-    this.eventBus.dispatch("textlayerrendered", {
-      source: this,
-      pageNumber: this.pageNumber,
-      numTextDivs: this.textDivs.length
-    });
+    this.div.append(endOfContent);
+    this.#bindMouse();
+  }
+  get numTextDivs() {
+    return this.textDivs.length;
   }
-  render(timeout = 0) {
-    if (!(this.textContent || this.textContentStream) || this.renderingDone) {
+  async render(viewport) {
+    if (!this.#textContentSource) {
+      throw new Error('No "textContentSource" parameter specified.');
+    }
+    const scale = viewport.scale * (globalThis.devicePixelRatio || 1);
+    const {
+      rotation
+    } = viewport;
+    if (this.renderingDone) {
+      const mustRotate = rotation !== this.#rotation;
+      const mustRescale = scale !== this.#scale;
+      if (mustRotate || mustRescale) {
+        this.hide();
+        (0, _pdf.updateTextLayer)({
+          container: this.div,
+          viewport,
+          textDivs: this.textDivs,
+          textDivProperties: this.textDivProperties,
+          isOffscreenCanvasSupported: this.isOffscreenCanvasSupported,
+          mustRescale,
+          mustRotate
+        });
+        this.#scale = scale;
+        this.#rotation = rotation;
+      }
+      this.show();
       return;
     }
     this.cancel();
-    this.textDivs.length = 0;
     this.highlighter?.setTextMapping(this.textDivs, this.textContentItemsStr);
     this.accessibilityManager?.setTextMapping(this.textDivs);
-    const textLayerFrag = document.createDocumentFragment();
     this.textLayerRenderTask = (0, _pdf.renderTextLayer)({
-      textContent: this.textContent,
-      textContentStream: this.textContentStream,
-      container: textLayerFrag,
-      viewport: this.viewport,
+      textContentSource: this.#textContentSource,
+      container: this.div,
+      viewport,
       textDivs: this.textDivs,
+      textDivProperties: this.textDivProperties,
       textContentItemsStr: this.textContentItemsStr,
-      timeout
+      isOffscreenCanvasSupported: this.isOffscreenCanvasSupported
     });
-    this.textLayerRenderTask.promise.then(() => {
-      this.textLayerDiv.append(textLayerFrag);
-      this.#finishRendering();
+    await this.textLayerRenderTask.promise;
+    this.#finishRendering();
+    this.#scale = scale;
+    this.#rotation = rotation;
+    this.show();
+    this.accessibilityManager?.enable();
+  }
+  hide() {
+    if (!this.div.hidden) {
+      this.highlighter?.disable();
+      this.div.hidden = true;
+    }
+  }
+  show() {
+    if (this.div.hidden && this.renderingDone) {
+      this.div.hidden = false;
       this.highlighter?.enable();
-      this.accessibilityManager?.enable();
-    }, function (reason) {});
+    }
   }
   cancel() {
     if (this.textLayerRenderTask) {
@@ -92,17 +123,18 @@ class TextLayerBuilder {
     }
     this.highlighter?.disable();
     this.accessibilityManager?.disable();
+    this.textContentItemsStr.length = 0;
+    this.textDivs.length = 0;
+    this.textDivProperties = new WeakMap();
   }
-  setTextContentStream(readableStream) {
-    this.cancel();
-    this.textContentStream = readableStream;
-  }
-  setTextContent(textContent) {
+  setTextContentSource(source) {
     this.cancel();
-    this.textContent = textContent;
+    this.#textContentSource = source;
   }
   #bindMouse() {
-    const div = this.textLayerDiv;
+    const {
+      div
+    } = this;
     div.addEventListener("mousedown", evt => {
       const end = div.querySelector(".endOfContent");
       if (!end) {

+ 1 - 2
lib/web/ui_utils.js

@@ -434,8 +434,7 @@ class ProgressBar {
   #classList = null;
   #percent = 0;
   #visible = true;
-  constructor(id) {
-    const bar = document.getElementById(id);
+  constructor(bar) {
     this.#classList = bar.classList;
   }
   get percent() {

+ 82 - 0
lib/web/viewer-geckoview.js

@@ -0,0 +1,82 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * JavaScript code in this page
+ *
+ * Copyright 2022 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * JavaScript code in this page
+ */
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+Object.defineProperty(exports, "PDFViewerApplication", {
+  enumerable: true,
+  get: function () {
+    return _app.PDFViewerApplication;
+  }
+});
+exports.PDFViewerApplicationConstants = void 0;
+Object.defineProperty(exports, "PDFViewerApplicationOptions", {
+  enumerable: true,
+  get: function () {
+    return _app_options.AppOptions;
+  }
+});
+var _ui_utils = require("./ui_utils.js");
+var _app_options = require("./app_options.js");
+var _pdf_link_service = require("./pdf_link_service.js");
+var _app = require("./app.js");
+const pdfjsVersion = '3.2.146';
+const pdfjsBuild = '3fd2a3548';
+const AppConstants = {
+  LinkTarget: _pdf_link_service.LinkTarget,
+  RenderingStates: _ui_utils.RenderingStates,
+  ScrollMode: _ui_utils.ScrollMode,
+  SpreadMode: _ui_utils.SpreadMode
+};
+exports.PDFViewerApplicationConstants = AppConstants;
+window.PDFViewerApplication = _app.PDFViewerApplication;
+window.PDFViewerApplicationConstants = AppConstants;
+window.PDFViewerApplicationOptions = _app_options.AppOptions;
+;
+function getViewerConfiguration() {
+  return {
+    appContainer: document.body,
+    mainContainer: document.getElementById("viewerContainer"),
+    viewerContainer: document.getElementById("viewer"),
+    passwordOverlay: {
+      dialog: document.getElementById("passwordDialog"),
+      label: document.getElementById("passwordText"),
+      input: document.getElementById("password"),
+      submitButton: document.getElementById("passwordSubmit"),
+      cancelButton: document.getElementById("passwordCancel")
+    },
+    printContainer: document.getElementById("printContainer"),
+    openFileInput: document.getElementById("fileInput")
+  };
+}
+function webViewerLoad() {
+  const config = getViewerConfiguration();
+  _app.PDFViewerApplication.run(config);
+}
+document.blockUnblockOnload?.(true);
+if (document.readyState === "interactive" || document.readyState === "complete") {
+  webViewerLoad();
+} else {
+  document.addEventListener("DOMContentLoaded", webViewerLoad, true);
+}

+ 24 - 28
lib/web/xfa_layer_builder.js

@@ -42,7 +42,7 @@ class XfaLayerBuilder {
     this.div = null;
     this._cancelled = false;
   }
-  render(viewport, intent = "display") {
+  async render(viewport, intent = "display") {
     if (intent === "print") {
       const parameters = {
         viewport: viewport.clone({
@@ -57,35 +57,31 @@ class XfaLayerBuilder {
       const div = document.createElement("div");
       this.pageDiv.append(div);
       parameters.div = div;
-      const result = _pdf.XfaLayer.render(parameters);
-      return Promise.resolve(result);
+      return _pdf.XfaLayer.render(parameters);
     }
-    return this.pdfPage.getXfa().then(xfaHtml => {
-      if (this._cancelled || !xfaHtml) {
-        return {
-          textDivs: []
-        };
-      }
-      const parameters = {
-        viewport: viewport.clone({
-          dontFlip: true
-        }),
-        div: this.div,
-        xfaHtml,
-        annotationStorage: this.annotationStorage,
-        linkService: this.linkService,
-        intent
+    const xfaHtml = await this.pdfPage.getXfa();
+    if (this._cancelled || !xfaHtml) {
+      return {
+        textDivs: []
       };
-      if (this.div) {
-        return _pdf.XfaLayer.update(parameters);
-      }
-      this.div = document.createElement("div");
-      this.pageDiv.append(this.div);
-      parameters.div = this.div;
-      return _pdf.XfaLayer.render(parameters);
-    }).catch(error => {
-      console.error(error);
-    });
+    }
+    const parameters = {
+      viewport: viewport.clone({
+        dontFlip: true
+      }),
+      div: this.div,
+      xfaHtml,
+      annotationStorage: this.annotationStorage,
+      linkService: this.linkService,
+      intent
+    };
+    if (this.div) {
+      return _pdf.XfaLayer.update(parameters);
+    }
+    this.div = document.createElement("div");
+    this.pageDiv.append(this.div);
+    parameters.div = this.div;
+    return _pdf.XfaLayer.render(parameters);
   }
   cancel() {
     this._cancelled = true;

+ 2 - 2
package.json

@@ -1,6 +1,6 @@
 {
   "name": "pdfjs-dist",
-  "version": "3.1.81",
+  "version": "3.2.146",
   "main": "build/pdf.js",
   "types": "types/src/pdf.d.ts",
   "description": "Generic build of Mozilla's PDF.js library.",
@@ -13,7 +13,7 @@
   "bugs": "https://github.com/mozilla/pdf.js/issues",
   "license": "Apache-2.0",
   "optionalDependencies": {
-    "canvas": "^2.10.2"
+    "canvas": "^2.11.0"
   },
   "dependencies": {
     "web-streams-polyfill": "^3.2.1"

+ 14 - 14
types/src/display/annotation_layer.d.ts

@@ -20,7 +20,6 @@ export type AnnotationElementParameters = {
     enableScripting?: boolean | undefined;
     hasJSActions?: boolean | undefined;
     fieldObjects?: Object | undefined;
-    mouseState?: Object | undefined;
 };
 export type AnnotationLayerParameters = {
     viewport: PageViewport;
@@ -29,6 +28,7 @@ export type AnnotationLayerParameters = {
     page: PDFPageProxy;
     linkService: IPDFLinkService;
     downloadManager: any;
+    annotationStorage?: AnnotationStorage | undefined;
     /**
      * - Path for image resources, mainly
      * for annotation icons. Include trailing slash.
@@ -44,7 +44,11 @@ export type AnnotationLayerParameters = {
      * The default value is `false`.
      */
     hasJSActions?: boolean | undefined;
+    fieldObjects?: {
+        [x: string]: Object[];
+    } | null | undefined;
     annotationCanvasMap?: Map<string, HTMLCanvasElement> | undefined;
+    accessibilityManager?: any;
 };
 /**
  * @typedef {Object} AnnotationLayerParameters
@@ -54,37 +58,33 @@ export type AnnotationLayerParameters = {
  * @property {PDFPageProxy} page
  * @property {IPDFLinkService} linkService
  * @property {IDownloadManager} downloadManager
+ * @property {AnnotationStorage} [annotationStorage]
  * @property {string} [imageResourcesPath] - Path for image resources, mainly
  *   for annotation icons. Include trailing slash.
  * @property {boolean} renderForms
  * @property {boolean} [enableScripting] - Enable embedded script execution.
  * @property {boolean} [hasJSActions] - Some fields have JS actions.
  *   The default value is `false`.
+ * @property {Object<string, Array<Object>> | null} [fieldObjects]
  * @property {Map<string, HTMLCanvasElement>} [annotationCanvasMap]
+ * @property {TextAccessibilityManager} [accessibilityManager]
  */
 export class AnnotationLayer {
-    static "__#30@#appendElement"(element: any, id: any, div: any, accessibilityManager: any): void;
+    static "__#24@#appendElement"(element: any, id: any, div: any, accessibilityManager: any): void;
     /**
      * Render a new annotation layer with all annotation elements.
      *
-     * @public
-     * @param {AnnotationLayerParameters} parameters
+     * @param {AnnotationLayerParameters} params
      * @memberof AnnotationLayer
      */
-    public static render(parameters: AnnotationLayerParameters): void;
+    static render(params: AnnotationLayerParameters): void;
     /**
      * Update the annotation elements on existing annotation layer.
      *
-     * @public
-     * @param {AnnotationLayerParameters} parameters
+     * @param {AnnotationLayerParameters} params
      * @memberof AnnotationLayer
      */
-    public static update(parameters: AnnotationLayerParameters): void;
-    /**
-     * @param {HTMLDivElement} div
-     * @param {PageViewport} viewport
-     */
-    static "__#30@#setDimensions"(div: HTMLDivElement, { width, height, rotation }: PageViewport): void;
-    static "__#30@#setAnnotationCanvasMap"(div: any, annotationCanvasMap: any): void;
+    static update(params: AnnotationLayerParameters): void;
+    static "__#24@#setAnnotationCanvasMap"(div: any, annotationCanvasMap: any): void;
 }
 import { AnnotationStorage } from "./annotation_storage.js";

+ 14 - 5
types/src/display/api.d.ts

@@ -725,7 +725,12 @@ export class PDFDocumentLoadingTask {
      * The callback receives an {@link UNSUPPORTED_FEATURES} argument.
      * @type {function}
      */
-    onUnsupportedFeature: Function;
+    set onUnsupportedFeature(arg: Function | null);
+    /**
+     * @type {function | null} The current callback used with unsupported
+     * features.
+     */
+    get onUnsupportedFeature(): Function | null;
     /**
      * Promise for document loading task completion.
      * @type {Promise<PDFDocumentProxy>}
@@ -737,6 +742,7 @@ export class PDFDocumentLoadingTask {
      *   completed.
      */
     destroy(): Promise<void>;
+    #private;
 }
 /**
  * Proxy to a `PDFDocument` in the worker thread.
@@ -1195,7 +1201,6 @@ export class PDFPageProxy {
     cleanupAfterRender: boolean;
     pendingCleanup: boolean;
     _intentStates: Map<any, any>;
-    _annotationPromises: Map<any, any>;
     destroyed: boolean;
     /**
      * @type {number} Page number of the page. First page is 1.
@@ -1235,6 +1240,10 @@ export class PDFPageProxy {
      *   {Object} with JS actions.
      */
     getJSActions(): Promise<Object>;
+    /**
+     * @type {boolean} True if only XFA form.
+     */
+    get isPureXfa(): boolean;
     /**
      * @returns {Promise<Object | null>} A promise that is resolved with
      *   an {Object} with a fake DOM object (a tree structure where elements
@@ -1285,8 +1294,6 @@ export class PDFPageProxy {
      * @private
      */
     private _destroy;
-    _jsActionsPromise: any;
-    _structTreePromise: any;
     /**
      * Cleans up resources allocated by the page.
      *
@@ -1403,8 +1410,10 @@ export class RenderTask {
      * Cancels the rendering task. If the task is currently rendering it will
      * not be cancelled until graphics pauses with a timeout. The promise that
      * this object extends will be rejected when cancelled.
+     *
+     * @param {number} [extraDelay]
      */
-    cancel(): void;
+    cancel(extraDelay?: number | undefined): void;
     /**
      * Whether form fields are rendered separately from the main operatorList.
      * @type {boolean}

+ 2 - 2
types/src/display/canvas.d.ts

@@ -85,9 +85,9 @@ export class CanvasGraphics {
     transform(a: any, b: any, c: any, d: any, e: any, f: any): void;
     constructPath(ops: any, args: any, minMax: any): void;
     closePath(): void;
-    stroke(consumePath: any): void;
+    stroke(consumePath?: boolean): void;
     closeStroke(): void;
-    fill(consumePath: any): void;
+    fill(consumePath?: boolean): void;
     eoFill(): void;
     fillStroke(): void;
     eoFillStroke(): void;

+ 14 - 1
types/src/display/display_utils.d.ts

@@ -165,6 +165,11 @@ export class PageViewport {
     transform: number[];
     width: number;
     height: number;
+    /**
+     * The original, un-scaled, viewport dimensions.
+     * @type {Object}
+     */
+    get rawDims(): Object;
     /**
      * Clones viewport, with optional additional properties.
      * @param {PageViewportCloneParameters} [params]
@@ -228,9 +233,17 @@ export class PixelsPerInch {
 declare const RenderingCancelledException_base: any;
 export class RenderingCancelledException extends RenderingCancelledException_base {
     [x: string]: any;
-    constructor(msg: any, type: any);
+    constructor(msg: any, type: any, extraDelay?: number);
     type: any;
+    extraDelay: number;
 }
+/**
+ * @param {HTMLDivElement} div
+ * @param {PageViewport} viewport
+ * @param {boolean} mustFlip
+ * @param {boolean} mustRotate
+ */
+export function setLayerDimensions(div: HTMLDivElement, viewport: PageViewport, mustFlip?: boolean, mustRotate?: boolean): void;
 export class StatTimer {
     started: any;
     times: any[];

+ 13 - 24
types/src/display/editor/annotation_editor_layer.d.ts

@@ -1,6 +1,6 @@
 export type AnnotationEditor = import("./editor.js").AnnotationEditor;
 export type AnnotationEditorUIManager = import("./tools.js").AnnotationEditorUIManager;
-export type AnnotationStorage = import("../annotation_storage.js").AnnotationStorage;
+export type PageViewport = import("../display_utils.js").PageViewport;
 export type TextAccessibilityManager = any;
 export type IL10n = any;
 export type AnnotationEditorLayerOptions = {
@@ -8,22 +8,27 @@ export type AnnotationEditorLayerOptions = {
     div: HTMLDivElement;
     uiManager: AnnotationEditorUIManager;
     enabled: boolean;
-    annotationStorage: AnnotationStorage;
     accessibilityManager?: any;
     pageIndex: number;
     l10n: any;
 };
+export type RenderEditorLayerOptions = {
+    viewport: PageViewport;
+};
 /**
  * @typedef {Object} AnnotationEditorLayerOptions
  * @property {Object} mode
  * @property {HTMLDivElement} div
  * @property {AnnotationEditorUIManager} uiManager
  * @property {boolean} enabled
- * @property {AnnotationStorage} annotationStorage
  * @property {TextAccessibilityManager} [accessibilityManager]
  * @property {number} pageIndex
  * @property {IL10n} l10n
  */
+/**
+ * @typedef {Object} RenderEditorLayerOptions
+ * @property {PageViewport} viewport
+ */
 /**
  * Manage all the different editors on a page.
  */
@@ -33,7 +38,6 @@ export class AnnotationEditorLayer {
      * @param {AnnotationEditorLayerOptions} options
      */
     constructor(options: AnnotationEditorLayerOptions);
-    annotationStorage: import("../annotation_storage.js").AnnotationStorage;
     pageIndex: number;
     div: HTMLDivElement;
     /**
@@ -86,11 +90,6 @@ export class AnnotationEditorLayer {
      */
     add(editor: AnnotationEditor): void;
     moveEditorInDOM(editor: any): void;
-    /**
-     * Add an editor in the annotation storage.
-     * @param {AnnotationEditor} editor
-     */
-    addToAnnotationStorage(editor: AnnotationEditor): void;
     /**
      * Add or rebuild depending if it has been removed or not.
      * @param {AnnotationEditor} editor
@@ -163,29 +162,19 @@ export class AnnotationEditorLayer {
     destroy(): void;
     /**
      * Render the main editor.
-     * @param {Object} parameters
+     * @param {RenderEditorLayerOptions} parameters
      */
-    render(parameters: Object): void;
-    viewport: any;
+    render({ viewport }: RenderEditorLayerOptions): void;
+    viewport: import("../display_utils.js").PageViewport | undefined;
     /**
      * Update the main editor.
-     * @param {Object} parameters
-     */
-    update(parameters: Object): void;
-    /**
-     * Get the scale factor from the viewport.
-     * @returns {number}
+     * @param {RenderEditorLayerOptions} parameters
      */
-    get scaleFactor(): number;
+    update({ viewport }: RenderEditorLayerOptions): void;
     /**
      * Get page dimensions.
      * @returns {Object} dimensions.
      */
     get pageDimensions(): Object;
-    get viewportBaseDimensions(): any[];
-    /**
-     * Set the dimensions of the main div.
-     */
-    setDimensions(): void;
     #private;
 }

+ 24 - 3
types/src/display/editor/editor.d.ts

@@ -1,5 +1,10 @@
 export type AnnotationEditorLayer = import("./annotation_editor_layer.js").AnnotationEditorLayer;
+export type AnnotationEditorUIManager = import("./tools.js").AnnotationEditorUIManager;
 export type AnnotationEditorParameters = {
+    /**
+     * - the global manager
+     */
+    uiManager: AnnotationEditorUIManager;
     /**
      * - the layer containing this editor
      */
@@ -19,6 +24,7 @@ export type AnnotationEditorParameters = {
 };
 /**
  * @typedef {Object} AnnotationEditorParameters
+ * @property {AnnotationEditorUIManager} uiManager - the global manager
  * @property {AnnotationEditorLayer} parent - the layer containing this editor
  * @property {string} id - editor id
  * @property {number} x - x-coordinate
@@ -37,13 +43,15 @@ export class AnnotationEditor {
      *
      * @param {Object} data
      * @param {AnnotationEditorLayer} parent
+     * @param {AnnotationEditorUIManager} uiManager
      * @returns {AnnotationEditor}
      */
-    static deserialize(data: Object, parent: AnnotationEditorLayer): AnnotationEditor;
+    static deserialize(data: Object, parent: AnnotationEditorLayer, uiManager: AnnotationEditorUIManager): AnnotationEditor;
     /**
      * @param {AnnotationEditorParameters} parameters
      */
     constructor(parameters: AnnotationEditorParameters);
+    _uiManager: null;
     parent: import("./annotation_editor_layer.js").AnnotationEditorLayer;
     id: string;
     width: any;
@@ -51,10 +59,18 @@ export class AnnotationEditor {
     pageIndex: number;
     name: any;
     div: HTMLDivElement | null;
+    rotation: any;
+    pageDimensions: any[];
+    pageTranslation: any[];
     x: number;
     y: number;
-    rotation: any;
     isAttachedToDOM: boolean;
+    /**
+     * Add some commands into the CommandManager (undo/redo stuff).
+     * @param {Object} params
+     */
+    addCommands(params: Object): void;
+    get currentLayer(): any;
     /**
      * This editor will be behind the others.
      */
@@ -63,6 +79,7 @@ export class AnnotationEditor {
      * This editor will be in the foreground.
      */
     setInForeground(): void;
+    setParent(parent: any): void;
     /**
      * onfocus callback.
      */
@@ -77,6 +94,7 @@ export class AnnotationEditor {
      * Commit the data contained in this editor.
      */
     commit(): void;
+    addToAnnotationStorage(): void;
     /**
      * We use drag-and-drop in order to move an editor on a page.
      * @param {DragEvent} event
@@ -104,6 +122,9 @@ export class AnnotationEditor {
      * @param {number} y
      */
     screenToPageTranslation(x: number, y: number): number[];
+    get parentScale(): any;
+    get parentRotation(): any;
+    get parentDimensions(): number[];
     /**
      * Set the dimensions of this editor.
      * @param {number} width
@@ -126,7 +147,7 @@ export class AnnotationEditor {
      * @param {PointerEvent} event
      */
     pointerdown(event: PointerEvent): void;
-    getRect(tx: any, ty: any): number[];
+    getRect(tx: any, ty: any): any[];
     getRectInCurrentCoords(rect: any, pageHeight: any): any[];
     /**
      * Executed once this editor has been rendered.

+ 2 - 2
types/src/display/editor/freetext.d.ts

@@ -14,7 +14,7 @@ export class FreeTextEditor extends AnnotationEditor {
     static updateDefaultParams(type: any, value: any): void;
     static get defaultPropertiesToUpdate(): any[][];
     /** @inheritdoc */
-    static deserialize(data: any, parent: any): AnnotationEditor;
+    static deserialize(data: any, parent: any, uiManager: any): AnnotationEditor;
     constructor(params: any);
     /** @inheritdoc */
     updateParams(type: any, value: any): void;
@@ -50,7 +50,7 @@ export class FreeTextEditor extends AnnotationEditor {
         fontSize: any;
         value: string;
         pageIndex: number;
-        rect: number[];
+        rect: any[];
         rotation: any;
     } | null;
     #private;

+ 3 - 2
types/src/display/editor/ink.d.ts

@@ -17,7 +17,7 @@ export class InkEditor extends AnnotationEditor {
      */
     static "__#2@#buildPath2D"(bezier: Arra<number[]>): Path2D;
     /** @inheritdoc */
-    static deserialize(data: any, parent: any): AnnotationEditor;
+    static deserialize(data: any, parent: any, uiManager: any): AnnotationEditor;
     constructor(params: any);
     color: any;
     thickness: any;
@@ -33,6 +33,7 @@ export class InkEditor extends AnnotationEditor {
     /** @inheritdoc */
     get propertiesToUpdate(): any[][];
     canvas: HTMLCanvasElement | null | undefined;
+    onScaleChanging(): void;
     /**
      * onpointerdown callback for the canvas we're drawing on.
      * @param {PointerEvent} event
@@ -75,7 +76,7 @@ export class InkEditor extends AnnotationEditor {
             points: number[];
         }[];
         pageIndex: number;
-        rect: number[];
+        rect: any[];
         rotation: any;
     } | null;
     #private;

+ 20 - 2
types/src/display/editor/tools.d.ts

@@ -10,12 +10,29 @@ export type AnnotationEditorLayer = import("./annotation_editor_layer.js").Annot
  */
 export class AnnotationEditorUIManager {
     static _keyboardManager: KeyboardManager;
-    constructor(container: any, eventBus: any);
+    constructor(container: any, eventBus: any, annotationStorage: any);
+    viewParameters: {
+        realScale: number;
+        rotation: number;
+    };
     destroy(): void;
     onPageChanging({ pageNumber }: {
         pageNumber: any;
     }): void;
     focusMainContainer(): void;
+    addShouldRescale(editor: any): void;
+    removeShouldRescale(editor: any): void;
+    onScaleChanging({ scale }: {
+        scale: any;
+    }): void;
+    onRotationChanging({ pagesRotation }: {
+        pagesRotation: any;
+    }): void;
+    /**
+     * Add an editor in the annotation storage.
+     * @param {AnnotationEditor} editor
+     */
+    addToAnnotationStorage(editor: AnnotationEditor): void;
     /**
      * Copy callback.
      * @param {ClipboardEvent} event
@@ -56,6 +73,8 @@ export class AnnotationEditorUIManager {
      * @returns {string}
      */
     getId(): string;
+    get currentLayer(): any;
+    get currentPageIndex(): number;
     /**
      * Add a new layer for a page which will contains the editors.
      * @param {AnnotationEditorLayer} layer
@@ -252,7 +271,6 @@ export class CommandManager {
  * non-mac OSes.
  */
 export class KeyboardManager {
-    static get platform(): any;
     /**
      * Create a new keyboard manager class.
      * @param {Array<Array>} callbacks - an array containing an array of shortcuts

+ 2 - 2
types/src/display/fetch_stream.d.ts

@@ -34,7 +34,7 @@ declare class PDFFetchStreamReader implements IPDFStreamReader {
     get isRangeSupported(): boolean;
     get isStreamingSupported(): boolean;
     read(): Promise<{
-        value: undefined;
+        value: Uint8Array | undefined;
         done: true;
     } | {
         value: ArrayBufferLike;
@@ -56,7 +56,7 @@ declare class PDFFetchStreamRangeReader implements IPDFStreamRangeReader {
     onProgress: any;
     get isStreamingSupported(): boolean;
     read(): Promise<{
-        value: undefined;
+        value: Uint8Array | undefined;
         done: true;
     } | {
         value: ArrayBufferLike;

+ 85 - 32
types/src/display/text_layer.d.ts

@@ -1,33 +1,36 @@
+export type PageViewport = import("./display_utils").PageViewport;
+export type TextContent = import("./api").TextContent;
 /**
  * Text layer render parameters.
  */
 export type TextLayerRenderParameters = {
     /**
      * - Text content to
-     * render (the object is returned by the page's `getTextContent` method).
+     * render, i.e. the value returned by the page's `streamTextContent` or
+     * `getTextContent` method.
      */
-    textContent?: import("./api").TextContent | undefined;
+    textContentSource: ReadableStream | TextContent;
     /**
-     * - Text content stream to
-     * render (the stream is returned by the page's `streamTextContent` method).
+     * - The DOM node that will contain the text
+     * runs.
      */
-    textContentStream?: ReadableStream<any> | undefined;
+    container: HTMLElement;
     /**
-     * - The DOM node that
-     * will contain the text runs.
+     * - The target viewport to properly layout
+     * the text runs.
      */
-    container: DocumentFragment | HTMLElement;
-    /**
-     * - The target
-     * viewport to properly layout the text runs.
-     */
-    viewport: import("./display_utils").PageViewport;
+    viewport: PageViewport;
     /**
      * - HTML elements that correspond to
      * the text items of the textContent input.
      * This is output and shall initially be set to an empty array.
      */
     textDivs?: HTMLElement[] | undefined;
+    /**
+     * - Some properties
+     * weakly mapped to the HTML elements used to render the text.
+     */
+    textDivProperties?: WeakMap<HTMLElement, Object> | undefined;
     /**
      * - Strings that correspond to
      * the `str` property of the text items of the textContent input.
@@ -35,43 +38,88 @@ export type TextLayerRenderParameters = {
      */
     textContentItemsStr?: string[] | undefined;
     /**
-     * - Delay in milliseconds before rendering of the
-     * text runs occurs.
+     * true if we can use
+     * OffscreenCanvas to measure string widths.
      */
-    timeout?: number | undefined;
+    isOffscreenCanvasSupported?: boolean | undefined;
 };
 /**
- * @param {TextLayerRenderParameters} renderParameters
+ * Text layer update parameters.
+ */
+export type TextLayerUpdateParameters = {
+    /**
+     * - The DOM node that will contain the text
+     * runs.
+     */
+    container: HTMLElement;
+    /**
+     * - The target viewport to properly layout
+     * the text runs.
+     */
+    viewport: PageViewport;
+    /**
+     * - HTML elements that correspond to
+     * the text items of the textContent input.
+     * This is output and shall initially be set to an empty array.
+     */
+    textDivs?: HTMLElement[] | undefined;
+    /**
+     * - Some properties
+     * weakly mapped to the HTML elements used to render the text.
+     */
+    textDivProperties?: WeakMap<HTMLElement, Object> | undefined;
+    /**
+     * true if we can use
+     * OffscreenCanvas to measure string widths.
+     */
+    isOffscreenCanvasSupported?: boolean | undefined;
+    /**
+     * true if the text layer must be rotated.
+     */
+    mustRotate?: boolean | undefined;
+    /**
+     * true if the text layer contents must be
+     * rescaled.
+     */
+    mustRescale?: boolean | undefined;
+};
+/**
+ * @param {TextLayerRenderParameters} params
  * @returns {TextLayerRenderTask}
  */
-export function renderTextLayer(renderParameters: TextLayerRenderParameters): TextLayerRenderTask;
+export function renderTextLayer(params: TextLayerRenderParameters): TextLayerRenderTask;
 export class TextLayerRenderTask {
-    constructor({ textContent, textContentStream, container, viewport, textDivs, textContentItemsStr, }: {
-        textContent: any;
-        textContentStream: any;
+    constructor({ textContentSource, container, viewport, textDivs, textDivProperties, textContentItemsStr, isOffscreenCanvasSupported, }: {
+        textContentSource: any;
         container: any;
         viewport: any;
         textDivs: any;
+        textDivProperties: any;
         textContentItemsStr: any;
+        isOffscreenCanvasSupported: any;
     });
-    _textContent: any;
-    _textContentStream: any;
+    _textContentSource: any;
+    _isReadableStream: boolean;
     _container: any;
-    _document: any;
-    _viewport: any;
+    _rootContainer: any;
     _textDivs: any;
     _textContentItemsStr: any;
     _fontInspectorEnabled: boolean;
     _reader: any;
-    _layoutTextLastFontSize: any;
-    _layoutTextLastFontFamily: any;
-    _layoutTextCtx: any;
-    _textDivProperties: WeakMap<object, any>;
-    _renderingDone: boolean;
+    _textDivProperties: any;
     _canceled: boolean;
     _capability: import("../shared/util.js").PromiseCapability;
-    _renderTimer: any;
-    _devicePixelRatio: number;
+    _layoutTextParams: {
+        prevFontSize: null;
+        prevFontFamily: null;
+        div: null;
+        scale: number;
+        properties: null;
+        ctx: CanvasRenderingContext2D | OffscreenRenderingContext | null;
+    };
+    _transform: any[];
+    _pageWidth: any;
+    _pageHeight: any;
     /**
      * Promise for textLayer rendering task completion.
      * @type {Promise<void>}
@@ -94,3 +142,8 @@ export class TextLayerRenderTask {
      */
     private _render;
 }
+/**
+ * @param {TextLayerUpdateParameters} params
+ * @returns {undefined}
+ */
+export function updateTextLayer({ container, viewport, textDivs, textDivProperties, isOffscreenCanvasSupported, mustRotate, mustRescale, }: TextLayerUpdateParameters): undefined;

+ 6 - 1
types/src/pdf.d.ts

@@ -1,9 +1,11 @@
+export type OnProgressParameters = import("./display/api").OnProgressParameters;
 export type PDFDocumentLoadingTask = import("./display/api").PDFDocumentLoadingTask;
 export type PDFDocumentProxy = import("./display/api").PDFDocumentProxy;
 export type PDFPageProxy = import("./display/api").PDFPageProxy;
 export type RenderTask = import("./display/api").RenderTask;
 export type PageViewport = import("./display/display_utils").PageViewport;
 export type TextLayerRenderTask = import("./display/text_layer").TextLayerRenderTask;
+import { AbortException } from "./shared/util.js";
 import { AnnotationEditorLayer } from "./display/editor/annotation_editor_layer.js";
 import { AnnotationEditorParamsType } from "./shared/util.js";
 import { AnnotationEditorType } from "./shared/util.js";
@@ -20,6 +22,7 @@ import { getPdfFilenameFromUrl } from "./display/display_utils.js";
 import { getXfaPageViewport } from "./display/display_utils.js";
 import { GlobalWorkerOptions } from "./display/worker_options.js";
 import { InvalidPDFException } from "./shared/util.js";
+import { isDataScheme } from "./display/display_utils.js";
 import { isPdfFile } from "./display/display_utils.js";
 import { loadScript } from "./display/display_utils.js";
 import { MissingPDFException } from "./shared/util.js";
@@ -32,12 +35,14 @@ import { PermissionFlag } from "./shared/util.js";
 import { PixelsPerInch } from "./display/display_utils.js";
 import { RenderingCancelledException } from "./display/display_utils.js";
 import { renderTextLayer } from "./display/text_layer.js";
+import { setLayerDimensions } from "./display/display_utils.js";
 import { shadow } from "./shared/util.js";
 import { SVGGraphics } from "./display/svg.js";
 import { UnexpectedResponseException } from "./shared/util.js";
 import { UNSUPPORTED_FEATURES } from "./shared/util.js";
+import { updateTextLayer } from "./display/text_layer.js";
 import { Util } from "./shared/util.js";
 import { VerbosityLevel } from "./shared/util.js";
 import { version } from "./display/api.js";
 import { XfaLayer } from "./display/xfa_layer.js";
-export { AnnotationEditorLayer, AnnotationEditorParamsType, AnnotationEditorType, AnnotationEditorUIManager, AnnotationLayer, AnnotationMode, build, CMapCompressionType, createPromiseCapability, createValidAbsoluteUrl, getDocument, getFilenameFromUrl, getPdfFilenameFromUrl, getXfaPageViewport, GlobalWorkerOptions, InvalidPDFException, isPdfFile, loadScript, MissingPDFException, OPS, PasswordResponses, PDFDataRangeTransport, PDFDateString, PDFWorker, PermissionFlag, PixelsPerInch, RenderingCancelledException, renderTextLayer, shadow, SVGGraphics, UnexpectedResponseException, UNSUPPORTED_FEATURES, Util, VerbosityLevel, version, XfaLayer };
+export { AbortException, AnnotationEditorLayer, AnnotationEditorParamsType, AnnotationEditorType, AnnotationEditorUIManager, AnnotationLayer, AnnotationMode, build, CMapCompressionType, createPromiseCapability, createValidAbsoluteUrl, getDocument, getFilenameFromUrl, getPdfFilenameFromUrl, getXfaPageViewport, GlobalWorkerOptions, InvalidPDFException, isDataScheme, isPdfFile, loadScript, MissingPDFException, OPS, PasswordResponses, PDFDataRangeTransport, PDFDateString, PDFWorker, PermissionFlag, PixelsPerInch, RenderingCancelledException, renderTextLayer, setLayerDimensions, shadow, SVGGraphics, UnexpectedResponseException, UNSUPPORTED_FEATURES, updateTextLayer, Util, VerbosityLevel, version, XfaLayer };

+ 1 - 0
types/src/shared/util.d.ts

@@ -219,6 +219,7 @@ export class FeatureTest {
     static get isLittleEndian(): any;
     static get isEvalSupported(): any;
     static get isOffscreenCanvasSupported(): any;
+    static get platform(): any;
 }
 export const FONT_IDENTITY_MATRIX: number[];
 export namespace FontType {

+ 13 - 22
types/web/annotation_editor_layer_builder.d.ts

@@ -1,34 +1,22 @@
 export type PDFPageProxy = import("../src/display/api").PDFPageProxy;
 export type PageViewport = import("../src/display/display_utils").PageViewport;
-export type IPDFLinkService = import("./interfaces").IPDFLinkService;
 export type AnnotationEditorUIManager = import("../src/display/editor/tools.js").AnnotationEditorUIManager;
-export type AnnotationStorage = any;
 export type TextAccessibilityManager = import("./text_accessibility.js").TextAccessibilityManager;
 export type IL10n = import("./interfaces").IL10n;
 export type AnnotationEditorLayerBuilderOptions = {
-    /**
-     * - Editor mode
-     */
-    mode: number;
+    uiManager?: import("../src/display/editor/tools.js").AnnotationEditorUIManager | undefined;
     pageDiv: HTMLDivElement;
     pdfPage: PDFPageProxy;
-    accessibilityManager: TextAccessibilityManager;
-    annotationStorage: any;
-    /**
-     * - Localization service.
-     */
-    l10n: IL10n;
-    uiManager: AnnotationEditorUIManager;
+    l10n?: import("./interfaces").IL10n | undefined;
+    accessibilityManager?: import("./text_accessibility.js").TextAccessibilityManager | undefined;
 };
 /**
  * @typedef {Object} AnnotationEditorLayerBuilderOptions
- * @property {number} mode - Editor mode
+ * @property {AnnotationEditorUIManager} [uiManager]
  * @property {HTMLDivElement} pageDiv
  * @property {PDFPageProxy} pdfPage
- * @property {TextAccessibilityManager} accessibilityManager
- * @property {AnnotationStorage} annotationStorage
- * @property {IL10n} l10n - Localization service.
- * @property {AnnotationEditorUIManager} uiManager
+ * @property {IL10n} [l10n]
+ * @property {TextAccessibilityManager} [accessibilityManager]
  */
 export class AnnotationEditorLayerBuilder {
     /**
@@ -37,9 +25,13 @@ export class AnnotationEditorLayerBuilder {
     constructor(options: AnnotationEditorLayerBuilderOptions);
     pageDiv: HTMLDivElement;
     pdfPage: import("../src/display/api").PDFPageProxy;
-    annotationStorage: any;
-    accessibilityManager: import("./text_accessibility.js").TextAccessibilityManager;
-    l10n: import("./interfaces").IL10n;
+    accessibilityManager: import("./text_accessibility.js").TextAccessibilityManager | undefined;
+    l10n: {
+        getLanguage(): Promise<string>;
+        getDirection(): Promise<string>;
+        get(key: any, args?: null, fallback?: any): Promise<any>;
+        translate(element: any): Promise<void>;
+    };
     annotationEditorLayer: any;
     div: HTMLDivElement | null;
     _cancelled: boolean;
@@ -51,6 +43,5 @@ export class AnnotationEditorLayerBuilder {
     cancel(): void;
     hide(): void;
     show(): void;
-    destroy(): void;
     #private;
 }

+ 3 - 6
types/web/annotation_layer_builder.d.ts

@@ -25,9 +25,8 @@ export type AnnotationLayerBuilderOptions = {
     fieldObjectsPromise?: Promise<{
         [x: string]: Object[];
     } | null> | undefined;
-    mouseState?: Object | undefined;
     annotationCanvasMap?: Map<string, HTMLCanvasElement> | undefined;
-    accessibilityManager: any;
+    accessibilityManager?: any;
 };
 /**
  * @typedef {Object} AnnotationLayerBuilderOptions
@@ -44,15 +43,14 @@ export type AnnotationLayerBuilderOptions = {
  * @property {Promise<boolean>} [hasJSActionsPromise]
  * @property {Promise<Object<string, Array<Object>> | null>}
  *   [fieldObjectsPromise]
- * @property {Object} [mouseState]
  * @property {Map<string, HTMLCanvasElement>} [annotationCanvasMap]
- * @property {TextAccessibilityManager} accessibilityManager
+ * @property {TextAccessibilityManager} [accessibilityManager]
  */
 export class AnnotationLayerBuilder {
     /**
      * @param {AnnotationLayerBuilderOptions} options
      */
-    constructor({ pageDiv, pdfPage, linkService, downloadManager, annotationStorage, imageResourcesPath, renderForms, l10n, enableScripting, hasJSActionsPromise, fieldObjectsPromise, mouseState, annotationCanvasMap, accessibilityManager, }: AnnotationLayerBuilderOptions);
+    constructor({ pageDiv, pdfPage, linkService, downloadManager, annotationStorage, imageResourcesPath, renderForms, l10n, enableScripting, hasJSActionsPromise, fieldObjectsPromise, annotationCanvasMap, accessibilityManager, }: AnnotationLayerBuilderOptions);
     pageDiv: HTMLDivElement;
     pdfPage: import("../src/display/api").PDFPageProxy;
     linkService: import("./interfaces").IPDFLinkService;
@@ -66,7 +64,6 @@ export class AnnotationLayerBuilder {
     _fieldObjectsPromise: Promise<{
         [x: string]: Object[];
     } | null>;
-    _mouseState: Object;
     _annotationCanvasMap: Map<string, HTMLCanvasElement>;
     _accessibilityManager: any;
     div: HTMLDivElement | null;

+ 0 - 174
types/web/default_factory.d.ts

@@ -1,174 +0,0 @@
-export type PDFPageProxy = import("../src/display/api").PDFPageProxy;
-export type PageViewport = import("../src/display/display_utils").PageViewport;
-export type EventBus = import("./event_utils").EventBus;
-export type IDownloadManager = import("./interfaces").IDownloadManager;
-export type IL10n = import("./interfaces").IL10n;
-export type IPDFAnnotationLayerFactory = import("./interfaces").IPDFAnnotationLayerFactory;
-export type IPDFAnnotationEditorLayerFactory = import("./interfaces").IPDFAnnotationEditorLayerFactory;
-export type IPDFLinkService = import("./interfaces").IPDFLinkService;
-export type IPDFStructTreeLayerFactory = import("./interfaces").IPDFStructTreeLayerFactory;
-export type IPDFTextLayerFactory = import("./interfaces").IPDFTextLayerFactory;
-export type IPDFXfaLayerFactory = import("./interfaces").IPDFXfaLayerFactory;
-export type TextHighlighter = import("./text_highlighter").TextHighlighter;
-export type TextAccessibilityManager = import("./text_accessibility.js").TextAccessibilityManager;
-/**
- * @implements IPDFAnnotationEditorLayerFactory
- */
-export class DefaultAnnotationEditorLayerFactory implements IPDFAnnotationEditorLayerFactory {
-    /**
-     * @typedef {Object} CreateAnnotationEditorLayerBuilderParameters
-     * @property {AnnotationEditorUIManager} [uiManager]
-     * @property {HTMLDivElement} pageDiv
-     * @property {PDFPageProxy} pdfPage
-     * @property {IL10n} l10n
-     * @property {AnnotationStorage} [annotationStorage] - Storage for annotation
-     * @property {TextAccessibilityManager} [accessibilityManager]
-     *   data in forms.
-     */
-    /**
-     * @param {CreateAnnotationEditorLayerBuilderParameters}
-     * @returns {AnnotationEditorLayerBuilder}
-     */
-    createAnnotationEditorLayerBuilder({ uiManager, pageDiv, pdfPage, accessibilityManager, l10n, annotationStorage, }: {
-        uiManager?: any;
-        pageDiv: HTMLDivElement;
-        pdfPage: PDFPageProxy;
-        l10n: IL10n;
-        /**
-         * - Storage for annotation
-         */
-        annotationStorage?: any;
-        /**
-         * data in forms.
-         */
-        accessibilityManager?: import("./text_accessibility.js").TextAccessibilityManager | undefined;
-    }): AnnotationEditorLayerBuilder;
-}
-/**
- * @implements IPDFAnnotationLayerFactory
- */
-export class DefaultAnnotationLayerFactory implements IPDFAnnotationLayerFactory {
-    /**
-     * @typedef {Object} CreateAnnotationLayerBuilderParameters
-     * @property {HTMLDivElement} pageDiv
-     * @property {PDFPageProxy} pdfPage
-     * @property {AnnotationStorage} [annotationStorage] - Storage for annotation
-     *   data in forms.
-     * @property {string} [imageResourcesPath] - Path for image resources, mainly
-     *   for annotation icons. Include trailing slash.
-     * @property {boolean} renderForms
-     * @property {IL10n} l10n
-     * @property {boolean} [enableScripting]
-     * @property {Promise<boolean>} [hasJSActionsPromise]
-     * @property {Object} [mouseState]
-     * @property {Promise<Object<string, Array<Object>> | null>}
-     *   [fieldObjectsPromise]
-     * @property {Map<string, HTMLCanvasElement>} [annotationCanvasMap] - Map some
-     *   annotation ids with canvases used to render them.
-     * @property {TextAccessibilityManager} [accessibilityManager]
-     */
-    /**
-     * @param {CreateAnnotationLayerBuilderParameters}
-     * @returns {AnnotationLayerBuilder}
-     */
-    createAnnotationLayerBuilder({ pageDiv, pdfPage, annotationStorage, imageResourcesPath, renderForms, l10n, enableScripting, hasJSActionsPromise, mouseState, fieldObjectsPromise, annotationCanvasMap, accessibilityManager, }: {
-        pageDiv: HTMLDivElement;
-        pdfPage: PDFPageProxy;
-        /**
-         * - Storage for annotation
-         * data in forms.
-         */
-        annotationStorage?: any;
-        /**
-         * - Path for image resources, mainly
-         * for annotation icons. Include trailing slash.
-         */
-        imageResourcesPath?: string | undefined;
-        renderForms: boolean;
-        l10n: IL10n;
-        enableScripting?: boolean | undefined;
-        hasJSActionsPromise?: Promise<boolean> | undefined;
-        mouseState?: Object | undefined;
-        fieldObjectsPromise?: Promise<{
-            [x: string]: Object[];
-        } | null> | undefined;
-        /**
-         * - Map some
-         * annotation ids with canvases used to render them.
-         */
-        annotationCanvasMap?: Map<string, HTMLCanvasElement> | undefined;
-        accessibilityManager?: import("./text_accessibility.js").TextAccessibilityManager | undefined;
-    }): AnnotationLayerBuilder;
-}
-/**
- * @implements IPDFStructTreeLayerFactory
- */
-export class DefaultStructTreeLayerFactory implements IPDFStructTreeLayerFactory {
-    /**
-     * @typedef {Object} CreateStructTreeLayerBuilderParameters
-     * @property {PDFPageProxy} pdfPage
-     */
-    /**
-     * @param {CreateStructTreeLayerBuilderParameters}
-     * @returns {StructTreeLayerBuilder}
-     */
-    createStructTreeLayerBuilder({ pdfPage }: {
-        pdfPage: PDFPageProxy;
-    }): StructTreeLayerBuilder;
-}
-/**
- * @implements IPDFTextLayerFactory
- */
-export class DefaultTextLayerFactory implements IPDFTextLayerFactory {
-    /**
-     * @typedef {Object} CreateTextLayerBuilderParameters
-     * @property {HTMLDivElement} textLayerDiv
-     * @property {number} pageIndex
-     * @property {PageViewport} viewport
-     * @property {EventBus} eventBus
-     * @property {TextHighlighter} highlighter
-     * @property {TextAccessibilityManager} [accessibilityManager]
-     */
-    /**
-     * @param {CreateTextLayerBuilderParameters}
-     * @returns {TextLayerBuilder}
-     */
-    createTextLayerBuilder({ textLayerDiv, pageIndex, viewport, eventBus, highlighter, accessibilityManager, }: {
-        textLayerDiv: HTMLDivElement;
-        pageIndex: number;
-        viewport: PageViewport;
-        eventBus: EventBus;
-        highlighter: TextHighlighter;
-        accessibilityManager?: import("./text_accessibility.js").TextAccessibilityManager | undefined;
-    }): TextLayerBuilder;
-}
-/**
- * @implements IPDFXfaLayerFactory
- */
-export class DefaultXfaLayerFactory implements IPDFXfaLayerFactory {
-    /**
-     * @typedef {Object} CreateXfaLayerBuilderParameters
-     * @property {HTMLDivElement} pageDiv
-     * @property {PDFPageProxy} pdfPage
-     * @property {AnnotationStorage} [annotationStorage] - Storage for annotation
-     *   data in forms.
-     */
-    /**
-     * @param {CreateXfaLayerBuilderParameters}
-     * @returns {XfaLayerBuilder}
-     */
-    createXfaLayerBuilder({ pageDiv, pdfPage, annotationStorage }: {
-        pageDiv: HTMLDivElement;
-        pdfPage: PDFPageProxy;
-        /**
-         * - Storage for annotation
-         * data in forms.
-         */
-        annotationStorage?: any;
-    }): XfaLayerBuilder;
-}
-import { AnnotationEditorLayerBuilder } from "./annotation_editor_layer_builder.js";
-import { AnnotationLayerBuilder } from "./annotation_layer_builder.js";
-import { StructTreeLayerBuilder } from "./struct_tree_layer_builder.js";
-import { TextLayerBuilder } from "./text_layer_builder.js";
-import { XfaLayerBuilder } from "./xfa_layer_builder.js";

+ 0 - 172
types/web/interfaces.d.ts

@@ -1,14 +1,6 @@
 export type PDFPageProxy = import("../src/display/api").PDFPageProxy;
 export type PageViewport = import("../src/display/display_utils").PageViewport;
-export type AnnotationLayerBuilder = import("./annotation_layer_builder").AnnotationLayerBuilder;
-export type AnnotationEditorLayerBuilder = import("./annotation_editor_layer_builder").AnnotationEditorLayerBuilder;
-export type EventBus = import("./event_utils").EventBus;
-export type StructTreeLayerBuilder = any;
-export type TextHighlighter = import("./text_highlighter").TextHighlighter;
-export type TextLayerBuilder = import("./text_layer_builder").TextLayerBuilder;
 export type RenderingStates = any;
-export type XfaLayerBuilder = import("./xfa_layer_builder").XfaLayerBuilder;
-export type TextAccessibilityManager = import("./text_accessibility.js").TextAccessibilityManager;
 /**
  * @interface
  */
@@ -67,106 +59,9 @@ export class IL10n {
      */
     translate(element: HTMLElement): Promise<void>;
 }
-/**
- * @interface
- */
-export class IPDFAnnotationEditorLayerFactory {
-    /**
-     * @typedef {Object} CreateAnnotationEditorLayerBuilderParameters
-     * @property {AnnotationEditorUIManager} [uiManager]
-     * @property {HTMLDivElement} pageDiv
-     * @property {PDFPageProxy} pdfPage
-     * @property {IL10n} l10n
-     * @property {AnnotationStorage} [annotationStorage] - Storage for annotation
-     * @property {TextAccessibilityManager} [accessibilityManager]
-     *   data in forms.
-     */
-    /**
-     * @param {CreateAnnotationEditorLayerBuilderParameters}
-     * @returns {AnnotationEditorLayerBuilder}
-     */
-    createAnnotationEditorLayerBuilder({ uiManager, pageDiv, pdfPage, l10n, annotationStorage, accessibilityManager, }: {
-        uiManager?: any;
-        pageDiv: HTMLDivElement;
-        pdfPage: PDFPageProxy;
-        l10n: IL10n;
-        /**
-         * - Storage for annotation
-         */
-        annotationStorage?: any;
-        /**
-         * data in forms.
-         */
-        accessibilityManager?: import("./text_accessibility.js").TextAccessibilityManager | undefined;
-    }): AnnotationEditorLayerBuilder;
-}
-/**
- * @interface
- */
-export class IPDFAnnotationLayerFactory {
-    /**
-     * @typedef {Object} CreateAnnotationLayerBuilderParameters
-     * @property {HTMLDivElement} pageDiv
-     * @property {PDFPageProxy} pdfPage
-     * @property {AnnotationStorage} [annotationStorage] - Storage for annotation
-     *   data in forms.
-     * @property {string} [imageResourcesPath] - Path for image resources, mainly
-     *   for annotation icons. Include trailing slash.
-     * @property {boolean} renderForms
-     * @property {IL10n} l10n
-     * @property {boolean} [enableScripting]
-     * @property {Promise<boolean>} [hasJSActionsPromise]
-     * @property {Object} [mouseState]
-     * @property {Promise<Object<string, Array<Object>> | null>}
-     *   [fieldObjectsPromise]
-     * @property {Map<string, HTMLCanvasElement>} [annotationCanvasMap] - Map some
-     *   annotation ids with canvases used to render them.
-     * @property {TextAccessibilityManager} [accessibilityManager]
-     */
-    /**
-     * @param {CreateAnnotationLayerBuilderParameters}
-     * @returns {AnnotationLayerBuilder}
-     */
-    createAnnotationLayerBuilder({ pageDiv, pdfPage, annotationStorage, imageResourcesPath, renderForms, l10n, enableScripting, hasJSActionsPromise, mouseState, fieldObjectsPromise, annotationCanvasMap, accessibilityManager, }: {
-        pageDiv: HTMLDivElement;
-        pdfPage: PDFPageProxy;
-        /**
-         * - Storage for annotation
-         * data in forms.
-         */
-        annotationStorage?: any;
-        /**
-         * - Path for image resources, mainly
-         * for annotation icons. Include trailing slash.
-         */
-        imageResourcesPath?: string | undefined;
-        renderForms: boolean;
-        l10n: IL10n;
-        enableScripting?: boolean | undefined;
-        hasJSActionsPromise?: Promise<boolean> | undefined;
-        mouseState?: Object | undefined;
-        fieldObjectsPromise?: Promise<{
-            [x: string]: Object[];
-        } | null> | undefined;
-        /**
-         * - Map some
-         * annotation ids with canvases used to render them.
-         */
-        annotationCanvasMap?: Map<string, HTMLCanvasElement> | undefined;
-        accessibilityManager?: import("./text_accessibility.js").TextAccessibilityManager | undefined;
-    }): AnnotationLayerBuilder;
-}
 /** @typedef {import("../src/display/api").PDFPageProxy} PDFPageProxy */
 /** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */
-/** @typedef {import("./annotation_layer_builder").AnnotationLayerBuilder} AnnotationLayerBuilder */
-/** @typedef {import("./annotation_editor_layer_builder").AnnotationEditorLayerBuilder} AnnotationEditorLayerBuilder */
-/** @typedef {import("./event_utils").EventBus} EventBus */
-/** @typedef {import("./struct_tree_builder").StructTreeLayerBuilder} StructTreeLayerBuilder */
-/** @typedef {import("./text_highlighter").TextHighlighter} TextHighlighter */
-/** @typedef {import("./text_layer_builder").TextLayerBuilder} TextLayerBuilder */
 /** @typedef {import("./ui_utils").RenderingStates} RenderingStates */
-/** @typedef {import("./xfa_layer_builder").XfaLayerBuilder} XfaLayerBuilder */
-/** @typedef {import("./text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
 /**
  * @interface
  */
@@ -253,73 +148,6 @@ export class IPDFLinkService {
      */
     isPageCached(pageNumber: number): void;
 }
-/**
- * @interface
- */
-export class IPDFStructTreeLayerFactory {
-    /**
-     * @typedef {Object} CreateStructTreeLayerBuilderParameters
-     * @property {PDFPageProxy} pdfPage
-     */
-    /**
-     * @param {CreateStructTreeLayerBuilderParameters}
-     * @returns {StructTreeLayerBuilder}
-     */
-    createStructTreeLayerBuilder({ pdfPage }: {
-        pdfPage: PDFPageProxy;
-    }): any;
-}
-/**
- * @interface
- */
-export class IPDFTextLayerFactory {
-    /**
-     * @typedef {Object} CreateTextLayerBuilderParameters
-     * @property {HTMLDivElement} textLayerDiv
-     * @property {number} pageIndex
-     * @property {PageViewport} viewport
-     * @property {EventBus} eventBus
-     * @property {TextHighlighter} highlighter
-     * @property {TextAccessibilityManager} [accessibilityManager]
-     */
-    /**
-     * @param {CreateTextLayerBuilderParameters}
-     * @returns {TextLayerBuilder}
-     */
-    createTextLayerBuilder({ textLayerDiv, pageIndex, viewport, eventBus, highlighter, accessibilityManager, }: {
-        textLayerDiv: HTMLDivElement;
-        pageIndex: number;
-        viewport: PageViewport;
-        eventBus: EventBus;
-        highlighter: TextHighlighter;
-        accessibilityManager?: import("./text_accessibility.js").TextAccessibilityManager | undefined;
-    }): TextLayerBuilder;
-}
-/**
- * @interface
- */
-export class IPDFXfaLayerFactory {
-    /**
-     * @typedef {Object} CreateXfaLayerBuilderParameters
-     * @property {HTMLDivElement} pageDiv
-     * @property {PDFPageProxy} pdfPage
-     * @property {AnnotationStorage} [annotationStorage] - Storage for annotation
-     *   data in forms.
-     */
-    /**
-     * @param {CreateXfaLayerBuilderParameters}
-     * @returns {XfaLayerBuilder}
-     */
-    createXfaLayerBuilder({ pageDiv, pdfPage, annotationStorage }: {
-        pageDiv: HTMLDivElement;
-        pdfPage: PDFPageProxy;
-        /**
-         * - Storage for annotation
-         * data in forms.
-         */
-        annotationStorage?: any;
-    }): XfaLayerBuilder;
-}
 /**
  * @interface
  */

+ 0 - 4
types/web/l10n_utils.d.ts

@@ -2,11 +2,7 @@ export function fixupLangCode(langCode: any): any;
 export function getL10nFallback(key: any, args: any): any;
 export namespace NullL10n {
     function getLanguage(): Promise<string>;
-    function getLanguage(): Promise<string>;
-    function getDirection(): Promise<string>;
     function getDirection(): Promise<string>;
     function get(key: any, args?: null, fallback?: any): Promise<any>;
-    function get(key: any, args?: null, fallback?: any): Promise<any>;
-    function translate(element: any): Promise<void>;
     function translate(element: any): Promise<void>;
 }

+ 1 - 1
types/web/pdf_link_service.d.ts

@@ -75,7 +75,7 @@ export namespace LinkTarget {
  * @implements {IPDFLinkService}
  */
 export class PDFLinkService implements IPDFLinkService {
-    static "__#31@#isValidExplicitDestination"(dest: any): boolean;
+    static "__#26@#isValidExplicitDestination"(dest: any): boolean;
     /**
      * @param {PDFLinkServiceOptions} options
      */

+ 34 - 46
types/web/pdf_page_view.d.ts

@@ -2,11 +2,6 @@ export type PageViewport = import("../src/display/display_utils").PageViewport;
 export type OptionalContentConfig = import("../src/display/optional_content_config").OptionalContentConfig;
 export type EventBus = import("./event_utils").EventBus;
 export type IL10n = import("./interfaces").IL10n;
-export type IPDFAnnotationLayerFactory = import("./interfaces").IPDFAnnotationLayerFactory;
-export type IPDFAnnotationEditorLayerFactory = import("./interfaces").IPDFAnnotationEditorLayerFactory;
-export type IPDFStructTreeLayerFactory = import("./interfaces").IPDFStructTreeLayerFactory;
-export type IPDFTextLayerFactory = import("./interfaces").IPDFTextLayerFactory;
-export type IPDFXfaLayerFactory = import("./interfaces").IPDFXfaLayerFactory;
 export type IRenderableView = import("./interfaces").IRenderableView;
 export type PDFRenderingQueue = import("./pdf_rendering_queue").PDFRenderingQueue;
 export type PDFPageViewOptions = {
@@ -40,7 +35,6 @@ export type PDFPageViewOptions = {
      * - The rendering queue object.
      */
     renderingQueue?: import("./pdf_rendering_queue").PDFRenderingQueue | undefined;
-    textLayerFactory?: import("./interfaces").IPDFTextLayerFactory | undefined;
     /**
      * - Controls if the text layer used for
      * selection and searching is created. The constants from {TextLayerMode}
@@ -55,11 +49,6 @@ export type PDFPageViewOptions = {
      * The default value is `AnnotationMode.ENABLE_FORMS`.
      */
     annotationMode?: number | undefined;
-    annotationLayerFactory?: import("./interfaces").IPDFAnnotationLayerFactory | undefined;
-    annotationEditorLayerFactory?: import("./interfaces").IPDFAnnotationEditorLayerFactory | undefined;
-    xfaLayerFactory?: import("./interfaces").IPDFXfaLayerFactory | undefined;
-    structTreeLayerFactory?: import("./interfaces").IPDFStructTreeLayerFactory | undefined;
-    textHighlighterFactory?: Object | undefined;
     /**
      * - Path for image resources, mainly
      * for annotation icons. Include trailing slash.
@@ -70,6 +59,11 @@ export type PDFPageViewOptions = {
      * value is `false`.
      */
     useOnlyCssZoom?: boolean | undefined;
+    /**
+     * - Allows to use an
+     * OffscreenCanvas if needed.
+     */
+    isOffscreenCanvasSupported?: boolean | undefined;
     /**
      * - The maximum supported canvas size in
      * total pixels, i.e. width * height. Use -1 for no limit. The default value
@@ -86,6 +80,11 @@ export type PDFPageViewOptions = {
      * - Localization service.
      */
     l10n?: import("./interfaces").IL10n | undefined;
+    /**
+     * - The function that is used to lookup
+     * the necessary layer-properties.
+     */
+    layerProperties?: Function | undefined;
 };
 /**
  * @implements {IRenderableView}
@@ -108,16 +107,11 @@ export class PDFPageView implements IRenderableView {
     textLayerMode: number;
     imageResourcesPath: string;
     useOnlyCssZoom: boolean;
+    isOffscreenCanvasSupported: boolean;
     maxCanvasPixels: any;
     pageColors: Object | null;
     eventBus: import("./event_utils").EventBus;
     renderingQueue: import("./pdf_rendering_queue").PDFRenderingQueue | undefined;
-    textLayerFactory: import("./interfaces").IPDFTextLayerFactory | undefined;
-    annotationLayerFactory: import("./interfaces").IPDFAnnotationLayerFactory | undefined;
-    annotationEditorLayerFactory: import("./interfaces").IPDFAnnotationEditorLayerFactory | undefined;
-    xfaLayerFactory: import("./interfaces").IPDFXfaLayerFactory | undefined;
-    textHighlighter: any;
-    structTreeLayerFactory: import("./interfaces").IPDFStructTreeLayerFactory | undefined;
     renderer: any;
     l10n: {
         getLanguage(): Promise<string>;
@@ -128,81 +122,71 @@ export class PDFPageView implements IRenderableView {
     paintTask: {
         promise: any;
         onRenderContinue(cont: any): void;
-        cancel(): void;
+        cancel(extraDelay?: number): void;
         readonly separateAnnots: any;
     } | null;
     paintedViewportMap: WeakMap<object, any>;
-    renderingState: number;
     resume: (() => void) | null;
     _renderError: any;
     _isStandalone: boolean | undefined;
     _annotationCanvasMap: any;
-    annotationLayer: any;
-    annotationEditorLayer: any;
-    textLayer: import("./text_layer_builder.js").TextLayerBuilder | null;
+    annotationLayer: AnnotationLayerBuilder | null;
+    annotationEditorLayer: AnnotationEditorLayerBuilder | null;
+    textLayer: TextLayerBuilder | null;
     zoomLayer: ParentNode | null;
-    xfaLayer: any;
+    xfaLayer: XfaLayerBuilder | null;
     structTreeLayer: any;
     div: HTMLDivElement;
+    set renderingState(arg: number);
+    get renderingState(): number;
     setPdfPage(pdfPage: any): void;
     destroy(): void;
-    /**
-     * @private
-     */
-    private _renderAnnotationLayer;
-    /**
-     * @private
-     */
-    private _renderAnnotationEditorLayer;
-    /**
-     * @private
-     */
-    private _renderXfaLayer;
-    _buildXfaTextContentItems(textDivs: any): Promise<void>;
+    get _textHighlighter(): any;
     /**
      * @private
      */
     private _resetZoomLayer;
-    reset({ keepZoomLayer, keepAnnotationLayer, keepAnnotationEditorLayer, keepXfaLayer, }?: {
+    reset({ keepZoomLayer, keepAnnotationLayer, keepAnnotationEditorLayer, keepXfaLayer, keepTextLayer, }?: {
         keepZoomLayer?: boolean | undefined;
         keepAnnotationLayer?: boolean | undefined;
         keepAnnotationEditorLayer?: boolean | undefined;
         keepXfaLayer?: boolean | undefined;
+        keepTextLayer?: boolean | undefined;
     }): void;
     loadingIconDiv: HTMLDivElement | undefined;
-    update({ scale, rotation, optionalContentConfigPromise }: {
+    update({ scale, rotation, optionalContentConfigPromise, drawingDelay, }: {
         scale?: number | undefined;
         rotation?: null | undefined;
         optionalContentConfigPromise?: null | undefined;
+        drawingDelay?: number | undefined;
     }): void;
     /**
      * PLEASE NOTE: Most likely you want to use the `this.reset()` method,
      *              rather than calling this one directly.
      */
-    cancelRendering({ keepAnnotationLayer, keepAnnotationEditorLayer, keepXfaLayer, }?: {
+    cancelRendering({ keepAnnotationLayer, keepAnnotationEditorLayer, keepXfaLayer, keepTextLayer, cancelExtraDelay, }?: {
         keepAnnotationLayer?: boolean | undefined;
         keepAnnotationEditorLayer?: boolean | undefined;
         keepXfaLayer?: boolean | undefined;
+        keepTextLayer?: boolean | undefined;
+        cancelExtraDelay?: number | undefined;
     }): void;
-    _onTextLayerRendered: any;
-    cssTransform({ target, redrawAnnotationLayer, redrawAnnotationEditorLayer, redrawXfaLayer, }: {
+    cssTransform({ target, redrawAnnotationLayer, redrawAnnotationEditorLayer, redrawXfaLayer, redrawTextLayer, hideTextLayer, }: {
         target: any;
         redrawAnnotationLayer?: boolean | undefined;
         redrawAnnotationEditorLayer?: boolean | undefined;
         redrawXfaLayer?: boolean | undefined;
+        redrawTextLayer?: boolean | undefined;
+        hideTextLayer?: boolean | undefined;
     }): void;
     get width(): number;
     get height(): number;
     getPagePoint(x: any, y: any): Object;
-    /**
-     * @ignore
-     */
-    toggleLoadingIconSpinner(viewVisible?: boolean): void;
     draw(): any;
     paintOnCanvas(canvasWrapper: any): {
         promise: any;
         onRenderContinue(cont: any): void;
-        cancel(): void;
+        cancel(extraDelay?: number): void;
         readonly separateAnnots: any;
     };
     canvas: HTMLCanvasElement | undefined;
@@ -225,4 +209,8 @@ export class PDFPageView implements IRenderableView {
     get thumbnailCanvas(): HTMLCanvasElement | null | undefined;
     #private;
 }
+import { AnnotationLayerBuilder } from "./annotation_layer_builder.js";
+import { AnnotationEditorLayerBuilder } from "./annotation_editor_layer_builder.js";
+import { TextLayerBuilder } from "./text_layer_builder.js";
+import { XfaLayerBuilder } from "./xfa_layer_builder.js";
 import { OutputScale } from "./ui_utils.js";

Някои файлове не бяха показани, защото твърде много файлове са промени