PageSourceSearch

https://pletox.com/js/vendor/pdfjs/pdf.js

js pletox.com collected 2026-09-24 11:58:16 UTC 798,756 bytes, 26,370 lines download raw bytes

vendor: 4,177 bytes, lines 1-169
1/**
2 * @licstart The following is the entire license notice for the
3 * JavaScript code in this page
4 *
5 * Copyright 2024 Mozilla Foundation
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *     http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * @licend The above is the entire license notice for the
20 * JavaScript code in this page
21 */
22
23/**
24 * pdfjsVersion = 5.4.624
25 * pdfjsBuild = 384c6208b
26 */
27/******/ // The require scope
28/******/ var __webpack_require__ = {};
29/******/ 
30/************************************************************************/
31/******/ /* webpack/runtime/define property getters */
32/******/ (() => {
33/******/ 	// define getter functions for harmony exports
34/******/ 	__webpack_require__.d = (exports, definition) => {
35/******/ 		for(var key in definition) {
36/******/ 			if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
37/******/ 				Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
38/******/ 			}
39/******/ 		}
40/******/ 	};
41/******/ })();
42/******/ 
43/******/ /* webpack/runtime/hasOwnProperty shorthand */
44/******/ (() => {
45/******/ 	__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
46/******/ })();
47/******/ 
48/************************************************************************/
49var __webpack_exports__ = {};
50
51;// ./src/shared/util.js
52const isNodeJS = typeof process === "object" && process + "" === "[object process]" && !process.versions.nw && !(process.versions.electron && process.type && process.type !== "browser");
53const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
54const LINE_FACTOR = 1.35;
55const LINE_DESCENT_FACTOR = 0.35;
56const BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR;
57const RenderingIntentFlag = {
58  ANY: 0x01,
59  DISPLAY: 0x02,
60  PRINT: 0x04,
61  SAVE: 0x08,
62  ANNOTATIONS_FORMS: 0x10,
63  ANNOTATIONS_STORAGE: 0x20,
64  ANNOTATIONS_DISABLE: 0x40,
65  IS_EDITING: 0x80,
66  OPLIST: 0x100
67};
68const AnnotationMode = {
69  DISABLE: 0,
70  ENABLE: 1,
71  ENABLE_FORMS: 2,
72  ENABLE_STORAGE: 3
73};
74const AnnotationEditorPrefix = "pdfjs_internal_editor_";
75const AnnotationEditorType = {
76  DISABLE: -1,
77  NONE: 0,
78  FREETEXT: 3,
79  HIGHLIGHT: 9,
80  STAMP: 13,
81  INK: 15,
82  POPUP: 16,
83  SIGNATURE: 101,
84  COMMENT: 102
85};
86const AnnotationEditorParamsType = {
87  RESIZE: 1,
88  CREATE: 2,
89  FREETEXT_SIZE: 11,
90  FREETEXT_COLOR: 12,
91  FREETEXT_OPACITY: 13,
92  INK_COLOR: 21,
93  INK_THICKNESS: 22,
94  INK_OPACITY: 23,
95  HIGHLIGHT_COLOR: 31,
96  HIGHLIGHT_THICKNESS: 32,
97  HIGHLIGHT_FREE: 33,
98  HIGHLIGHT_SHOW_ALL: 34,
99  DRAW_STEP: 41
100};
101const PermissionFlag = {
102  PRINT: 0x04,
103  MODIFY_CONTENTS: 0x08,
104  COPY: 0x10,
105  MODIFY_ANNOTATIONS: 0x20,
106  FILL_INTERACTIVE_FORMS: 0x100,
107  COPY_FOR_ACCESSIBILITY: 0x200,
108  ASSEMBLE: 0x400,
109  PRINT_HIGH_QUALITY: 0x800
110};
111const MeshFigureType = {
112  TRIANGLES: 1,
113  LATTICE: 2,
114  PATCH: 3
115};
116const TextRenderingMode = {
117  FILL: 0,
118  STROKE: 1,
119  FILL_STROKE: 2,
120  INVISIBLE: 3,
121  FILL_ADD_TO_PATH: 4,
122  STROKE_ADD_TO_PATH: 5,
123  FILL_STROKE_ADD_TO_PATH: 6,
124  ADD_TO_PATH: 7,
125  FILL_STROKE_MASK: 3,
126  ADD_TO_PATH_FLAG: 4
127};
128const util_ImageKind = {
129  GRAYSCALE_1BPP: 1,
130  RGB_24BPP: 2,
131  RGBA_32BPP: 3
132};
133const AnnotationType = {
134  TEXT: 1,
135  LINK: 2,
136  FREETEXT: 3,
137  LINE: 4,
138  SQUARE: 5,
139  CIRCLE: 6,
140  POLYGON: 7,
141  POLYLINE: 8,
142  HIGHLIGHT: 9,
143  UNDERLINE: 10,
144  SQUIGGLY: 11,
145  STRIKEOUT: 12,
146  STAMP: 13,
147  CARET: 14,
148  INK: 15,
149  POPUP: 16,
150  FILEATTACHMENT: 17,
151  SOUND: 18,
152  MOVIE: 19,
153  WIDGET: 20,
154  SCREEN: 21,
155  PRINTERMARK: 22,
156  TRAPNET: 23,
157  WATERMARK: 24,
158  THREED: 25,
159  REDACT: 26
160};
161const AnnotationReplyType = {
162  GROUP: "Group",
163  REPLY: "R"
164};
165const AnnotationFlag = {
166  INVISIBLE: 0x01,
167  HIDDEN: 0x02,
168  PRINT: 0x04,
169  NOZOOM: 0x08,
170  NOROTATE: 0x10,
171  NOVIEW: 0x20,
172  READONLY: 0x40,
173  LOCKED: 0x80,
174  TOGGLENOVIEW: 0x100,
175  LOCKEDCONTENTS: 0x200
176};
177const AnnotationFieldFlag = {
178  READONLY: 0x0000001,
179  REQUIRED: 0x0000002,
180  NOEXPORT: 0x0000004,
181  MULTILINE: 0x0001000,
182  PASSWORD: 0x0002000,
183  NOTOGGLETOOFF: 0x0004000,
184  RADIO: 0x0008000,
185  PUSHBUTTON: 0x0010000,
186  COMBO: 0x0020000,
187  EDIT: 0x0040000,
188  SORT: 0x0080000,
189  FILESELECT: 0x0100000,
190  MULTISELECT: 0x0200000,
191  DONOTSPELLCHECK: 0x0400000,
192  DONOTSCROLL: 0x0800000,
193  COMB: 0x1000000,
194  RICHTEXT: 0x2000000,
195  RADIOSINUNISON: 0x2000000,
196  COMMITONSELCHANGE: 0x4000000
197};
198const AnnotationBorderStyleType = {
199  SOLID: 1,
200  DASHED: 2,
201  BEVELED: 3,
202  INSET: 4,
203  UNDERLINE: 5
204};
205const AnnotationActionEventType = {
206  E: "Mouse Enter",
207  X: "Mouse Exit",
208  D: "Mouse Down",
209  U: "Mouse Up",
210  Fo: "Focus",
211  Bl: "Blur",
212  PO: "PageOpen",
213  PC: "PageClose",
214  PV: "PageVisible",
215  PI: "PageInvisible",
216  K: "Keystroke",
217  F: "Format",
218  V: "Validate",
219  C: "Calculate"
220};
221const DocumentActionEventType = {
222  WC: "WillClose",
223  WS: "WillSave",
224  DS: "DidSave",
225  WP: "WillPrint",
226  DP: "DidPrint"
227};
228const PageActionEventType = {
229  O: "PageOpen",
230  C: "PageClose"
231};
232const VerbosityLevel = {
233  ERRORS: 0,
234  WARNINGS: 1,
235  INFOS: 5
236};
237const OPS = {
238  dependency: 1,
239  setLineWidth: 2,
240  setLineCap: 3,
241  setLineJoin: 4,
242  setMiterLimit: 5,
243  setDash: 6,
244  setRenderingIntent: 7,
245  setFlatness: 8,
246  setGState: 9,
247  save: 10,
248  restore: 11,
249  transform: 12,
250  moveTo: 13,
251  lineTo: 14,
252  curveTo: 15,
253  curveTo2: 16,
vendor: 5,587 bytes, lines 254-487
254  curveTo3: 17,
255  closePath: 18,
256  rectangle: 19,
257  stroke: 20,
258  closeStroke: 21,
259  fill: 22,
260  eoFill: 23,
261  fillStroke: 24,
262  eoFillStroke: 25,
263  closeFillStroke: 26,
264  closeEOFillStroke: 27,
265  endPath: 28,
266  clip: 29,
267  eoClip: 30,
268  beginText: 31,
269  endText: 32,
270  setCharSpacing: 33,
271  setWordSpacing: 34,
272  setHScale: 35,
273  setLeading: 36,
274  setFont: 37,
275  setTextRenderingMode: 38,
276  setTextRise: 39,
277  moveText: 40,
278  setLeadingMoveText: 41,
279  setTextMatrix: 42,
280  nextLine: 43,
281  showText: 44,
282  showSpacedText: 45,
283  nextLineShowText: 46,
284  nextLineSetSpacingShowText: 47,
285  setCharWidth: 48,
286  setCharWidthAndBounds: 49,
287  setStrokeColorSpace: 50,
288  setFillColorSpace: 51,
289  setStrokeColor: 52,
290  setStrokeColorN: 53,
291  setFillColor: 54,
292  setFillColorN: 55,
293  setStrokeGray: 56,
294  setFillGray: 57,
295  setStrokeRGBColor: 58,
296  setFillRGBColor: 59,
297  setStrokeCMYKColor: 60,
298  setFillCMYKColor: 61,
299  shadingFill: 62,
300  beginInlineImage: 63,
301  beginImageData: 64,
302  endInlineImage: 65,
303  paintXObject: 66,
304  markPoint: 67,
305  markPointProps: 68,
306  beginMarkedContent: 69,
307  beginMarkedContentProps: 70,
308  endMarkedContent: 71,
309  beginCompat: 72,
310  endCompat: 73,
311  paintFormXObjectBegin: 74,
312  paintFormXObjectEnd: 75,
313  beginGroup: 76,
314  endGroup: 77,
315  beginAnnotation: 80,
316  endAnnotation: 81,
317  paintImageMaskXObject: 83,
318  paintImageMaskXObjectGroup: 84,
319  paintImageXObject: 85,
320  paintInlineImageXObject: 86,
321  paintInlineImageXObjectGroup: 87,
322  paintImageXObjectRepeat: 88,
323  paintImageMaskXObjectRepeat: 89,
324  paintSolidColorImageMask: 90,
325  constructPath: 91,
326  setStrokeTransparent: 92,
327  setFillTransparent: 93,
328  rawFillPath: 94
329};
330const DrawOPS = {
331  moveTo: 0,
332  lineTo: 1,
333  curveTo: 2,
334  quadraticCurveTo: 3,
335  closePath: 4
336};
337const PasswordResponses = {
338  NEED_PASSWORD: 1,
339  INCORRECT_PASSWORD: 2
340};
341let verbosity = VerbosityLevel.WARNINGS;
342function setVerbosityLevel(level) {
343  if (Number.isInteger(level)) {
344    verbosity = level;
345  }
346}
347function getVerbosityLevel() {
348  return verbosity;
349}
350function info(msg) {
351  if (verbosity >= VerbosityLevel.INFOS) {
352    console.info(`Info: ${msg}`);
353  }
354}
355function warn(msg) {
356  if (verbosity >= VerbosityLevel.WARNINGS) {
357    console.warn(`Warning: ${msg}`);
358  }
359}
360function unreachable(msg) {
361  throw new Error(msg);
362}
363function assert(cond, msg) {
364  if (!cond) {
365    unreachable(msg);
366  }
367}
368function _isValidProtocol(url) {
369  switch (url?.protocol) {
370    case "http:":
371    case "https:":
372    case "ftp:":
373    case "mailto:":
374    case "tel:":
375      return true;
376    default:
377      return false;
378  }
379}
380function createValidAbsoluteUrl(url, baseUrl = null, options = null) {
381  if (!url) {
382    return null;
383  }
384  if (options && typeof url === "string") {
385    if (options.addDefaultProtocol && url.startsWith("www.")) {
386      const dots = url.match(/\./g);
387      if (dots?.length >= 2) {
388        url = `http://${url}`;
389      }
390    }
391    if (options.tryConvertEncoding) {
392      try {
393        url = stringToUTF8String(url);
394      } catch {}
395    }
396  }
397  const absoluteUrl = baseUrl ? URL.parse(url, baseUrl) : URL.parse(url);
398  return _isValidProtocol(absoluteUrl) ? absoluteUrl : null;
399}
400function updateUrlHash(url, hash, allowRel = false) {
401  const res = URL.parse(url);
402  if (res) {
403    res.hash = hash;
404    return res.href;
405  }
406  if (allowRel && createValidAbsoluteUrl(url, "http://example.com")) {
407    return url.split("#", 1)[0] + `${hash ? `#${hash}` : ""}`;
408  }
409  return "";
410}
411function shadow(obj, prop, value, nonSerializable = false) {
412  Object.defineProperty(obj, prop, {
413    value,
414    enumerable: !nonSerializable,
415    configurable: true,
416    writable: false
417  });
418  return value;
419}
420const BaseException = function BaseExceptionClosure() {
421  function BaseException(message, name) {
422    this.message = message;
423    this.name = name;
424  }
425  BaseException.prototype = new Error();
426  BaseException.constructor = BaseException;
427  return BaseException;
428}();
429class PasswordException extends BaseException {
430  constructor(msg, code) {
431    super(msg, "PasswordException");
432    this.code = code;
433  }
434}
435class UnknownErrorException extends BaseException {
436  constructor(msg, details) {
437    super(msg, "UnknownErrorException");
438    this.details = details;
439  }
440}
441class InvalidPDFException extends BaseException {
442  constructor(msg) {
443    super(msg, "InvalidPDFException");
444  }
445}
446class ResponseException extends BaseException {
447  constructor(msg, status, missing) {
448    super(msg, "ResponseException");
449    this.status = status;
450    this.missing = missing;
451  }
452}
453class FormatError extends BaseException {
454  constructor(msg) {
455    super(msg, "FormatError");
456  }
457}
458class AbortException extends BaseException {
459  constructor(msg) {
460    super(msg, "AbortException");
461  }
462}
463function bytesToString(bytes) {
464  if (typeof bytes !== "object" || bytes?.length === undefined) {
465    unreachable("Invalid argument for bytesToString");
466  }
467  const length = bytes.length;
468  const MAX_ARGUMENT_COUNT = 8192;
469  if (length < MAX_ARGUMENT_COUNT) {
470    return String.fromCharCode.apply(null, bytes);
471  }
472  const strBuf = [];
473  for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
474    const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
475    const chunk = bytes.subarray(i, chunkEnd);
476    strBuf.push(String.fromCharCode.apply(null, chunk));
477  }
478  return strBuf.join("");
479}
480function stringToBytes(str) {
481  if (typeof str !== "string") {
482    unreachable("Invalid argument for stringToBytes");
483  }
484  const length = str.length;
485  const bytes = new Uint8Array(length);
486  for (let i = 0; i < length; ++i) {
487    bytes[i] = str.charCodeAt(i) & 0xff;
vendor: 10,311 bytes, lines 488-780
488  }
489  return bytes;
490}
491function string32(value) {
492  return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);
493}
494function objectSize(obj) {
495  return Object.keys(obj).length;
496}
497function isLittleEndian() {
498  const buffer8 = new Uint8Array(4);
499  buffer8[0] = 1;
500  const view32 = new Uint32Array(buffer8.buffer, 0, 1);
501  return view32[0] === 1;
502}
503function isEvalSupported() {
504  try {
505    new Function("");
506    return true;
507  } catch {
508    return false;
509  }
510}
511class util_FeatureTest {
512  static get isLittleEndian() {
513    return shadow(this, "isLittleEndian", isLittleEndian());
514  }
515  static get isEvalSupported() {
516    return shadow(this, "isEvalSupported", isEvalSupported());
517  }
518  static get isOffscreenCanvasSupported() {
519    return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined");
520  }
521  static get isImageDecoderSupported() {
522    return shadow(this, "isImageDecoderSupported", typeof ImageDecoder !== "undefined");
523  }
524  static get isFloat16ArraySupported() {
525    return shadow(this, "isFloat16ArraySupported", typeof Float16Array !== "undefined");
526  }
527  static get isSanitizerSupported() {
528    return shadow(this, "isSanitizerSupported", typeof Sanitizer !== "undefined");
529  }
530  static get platform() {
531    const {
532      platform,
533      userAgent
534    } = navigator;
535    return shadow(this, "platform", {
536      isAndroid: userAgent.includes("Android"),
537      isLinux: platform.includes("Linux"),
538      isMac: platform.includes("Mac"),
539      isWindows: platform.includes("Win"),
540      isFirefox: userAgent.includes("Firefox")
541    });
542  }
543  static get isCSSRoundSupported() {
544    return shadow(this, "isCSSRoundSupported", globalThis.CSS?.supports?.("width: round(1.5px, 1px)"));
545  }
546}
547const hexNumbers = Array.from(Array(256).keys(), n => n.toString(16).padStart(2, "0"));
548class Util {
549  static makeHexColor(r, g, b) {
550    return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`;
551  }
552  static domMatrixToTransform(dm) {
553    return [dm.a, dm.b, dm.c, dm.d, dm.e, dm.f];
554  }
555  static scaleMinMax(transform, minMax) {
556    let temp;
557    if (transform[0]) {
558      if (transform[0] < 0) {
559        temp = minMax[0];
560        minMax[0] = minMax[2];
561        minMax[2] = temp;
562      }
563      minMax[0] *= transform[0];
564      minMax[2] *= transform[0];
565      if (transform[3] < 0) {
566        temp = minMax[1];
567        minMax[1] = minMax[3];
568        minMax[3] = temp;
569      }
570      minMax[1] *= transform[3];
571      minMax[3] *= transform[3];
572    } else {
573      temp = minMax[0];
574      minMax[0] = minMax[1];
575      minMax[1] = temp;
576      temp = minMax[2];
577      minMax[2] = minMax[3];
578      minMax[3] = temp;
579      if (transform[1] < 0) {
580        temp = minMax[1];
581        minMax[1] = minMax[3];
582        minMax[3] = temp;
583      }
584      minMax[1] *= transform[1];
585      minMax[3] *= transform[1];
586      if (transform[2] < 0) {
587        temp = minMax[0];
588        minMax[0] = minMax[2];
589        minMax[2] = temp;
590      }
591      minMax[0] *= transform[2];
592      minMax[2] *= transform[2];
593    }
594    minMax[0] += transform[4];
595    minMax[1] += transform[5];
596    minMax[2] += transform[4];
597    minMax[3] += transform[5];
598  }
599  static transform(m1, m2) {
600    return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]];
601  }
602  static multiplyByDOMMatrix(m, md) {
603    return [m[0] * md.a + m[2] * md.b, m[1] * md.a + m[3] * md.b, m[0] * md.c + m[2] * md.d, m[1] * md.c + m[3] * md.d, m[0] * md.e + m[2] * md.f + m[4], m[1] * md.e + m[3] * md.f + m[5]];
604  }
605  static applyTransform(p, m, pos = 0) {
606    const p0 = p[pos];
607    const p1 = p[pos + 1];
608    p[pos] = p0 * m[0] + p1 * m[2] + m[4];
609    p[pos + 1] = p0 * m[1] + p1 * m[3] + m[5];
610  }
611  static applyTransformToBezier(p, transform, pos = 0) {
612    const m0 = transform[0];
613    const m1 = transform[1];
614    const m2 = transform[2];
615    const m3 = transform[3];
616    const m4 = transform[4];
617    const m5 = transform[5];
618    for (let i = 0; i < 6; i += 2) {
619      const pI = p[pos + i];
620      const pI1 = p[pos + i + 1];
621      p[pos + i] = pI * m0 + pI1 * m2 + m4;
622      p[pos + i + 1] = pI * m1 + pI1 * m3 + m5;
623    }
624  }
625  static applyInverseTransform(p, m) {
626    const p0 = p[0];
627    const p1 = p[1];
628    const d = m[0] * m[3] - m[1] * m[2];
629    p[0] = (p0 * m[3] - p1 * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
630    p[1] = (-p0 * m[1] + p1 * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
631  }
632  static axialAlignedBoundingBox(rect, transform, output) {
633    const m0 = transform[0];
634    const m1 = transform[1];
635    const m2 = transform[2];
636    const m3 = transform[3];
637    const m4 = transform[4];
638    const m5 = transform[5];
639    const r0 = rect[0];
640    const r1 = rect[1];
641    const r2 = rect[2];
642    const r3 = rect[3];
643    let a0 = m0 * r0 + m4;
644    let a2 = a0;
645    let a1 = m0 * r2 + m4;
646    let a3 = a1;
647    let b0 = m3 * r1 + m5;
648    let b2 = b0;
649    let b1 = m3 * r3 + m5;
650    let b3 = b1;
651    if (m1 !== 0 || m2 !== 0) {
652      const m1r0 = m1 * r0;
653      const m1r2 = m1 * r2;
654      const m2r1 = m2 * r1;
655      const m2r3 = m2 * r3;
656      a0 += m2r1;
657      a3 += m2r1;
658      a1 += m2r3;
659      a2 += m2r3;
660      b0 += m1r0;
661      b3 += m1r0;
662      b1 += m1r2;
663      b2 += m1r2;
664    }
665    output[0] = Math.min(output[0], a0, a1, a2, a3);
666    output[1] = Math.min(output[1], b0, b1, b2, b3);
667    output[2] = Math.max(output[2], a0, a1, a2, a3);
668    output[3] = Math.max(output[3], b0, b1, b2, b3);
669  }
670  static inverseTransform(m) {
671    const d = m[0] * m[3] - m[1] * m[2];
672    return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
673  }
674  static singularValueDecompose2dScale(matrix, output) {
675    const m0 = matrix[0];
676    const m1 = matrix[1];
677    const m2 = matrix[2];
678    const m3 = matrix[3];
679    const a = m0 ** 2 + m1 ** 2;
680    const b = m0 * m2 + m1 * m3;
681    const c = m2 ** 2 + m3 ** 2;
682    const first = (a + c) / 2;
683    const second = Math.sqrt(first ** 2 - (a * c - b ** 2));
684    output[0] = Math.sqrt(first + second || 1);
685    output[1] = Math.sqrt(first - second || 1);
686  }
687  static normalizeRect(rect) {
688    const r = rect.slice(0);
689    if (rect[0] > rect[2]) {
690      r[0] = rect[2];
691      r[2] = rect[0];
692    }
693    if (rect[1] > rect[3]) {
694      r[1] = rect[3];
695      r[3] = rect[1];
696    }
697    return r;
698  }
699  static intersect(rect1, rect2) {
700    const xLow = Math.max(Math.min(rect1[0], rect1[2]), Math.min(rect2[0], rect2[2]));
701    const xHigh = Math.min(Math.max(rect1[0], rect1[2]), Math.max(rect2[0], rect2[2]));
702    if (xLow > xHigh) {
703      return null;
704    }
705    const yLow = Math.max(Math.min(rect1[1], rect1[3]), Math.min(rect2[1], rect2[3]));
706    const yHigh = Math.min(Math.max(rect1[1], rect1[3]), Math.max(rect2[1], rect2[3]));
707    if (yLow > yHigh) {
708      return null;
709    }
710    return [xLow, yLow, xHigh, yHigh];
711  }
712  static pointBoundingBox(x, y, minMax) {
713    minMax[0] = Math.min(minMax[0], x);
714    minMax[1] = Math.min(minMax[1], y);
715    minMax[2] = Math.max(minMax[2], x);
716    minMax[3] = Math.max(minMax[3], y);
717  }
718  static rectBoundingBox(x0, y0, x1, y1, minMax) {
719    minMax[0] = Math.min(minMax[0], x0, x1);
720    minMax[1] = Math.min(minMax[1], y0, y1);
721    minMax[2] = Math.max(minMax[2], x0, x1);
722    minMax[3] = Math.max(minMax[3], y0, y1);
723  }
724  static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) {
725    if (t <= 0 || t >= 1) {
726      return;
727    }
728    const mt = 1 - t;
729    const tt = t * t;
730    const ttt = tt * t;
731    const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3;
732    const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3;
733    minMax[0] = Math.min(minMax[0], x);
734    minMax[1] = Math.min(minMax[1], y);
735    minMax[2] = Math.max(minMax[2], x);
736    minMax[3] = Math.max(minMax[3], y);
737  }
738  static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, minMax) {
739    if (Math.abs(a) < 1e-12) {
740      if (Math.abs(b) >= 1e-12) {
741        this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b, minMax);
742      }
743      return;
744    }
745    const delta = b ** 2 - 4 * c * a;
746    if (delta < 0) {
747      return;
748    }
749    const sqrtDelta = Math.sqrt(delta);
750    const a2 = 2 * a;
751    this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b + sqrtDelta) / a2, minMax);
752    this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b - sqrtDelta) / a2, minMax);
753  }
754  static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) {
755    minMax[0] = Math.min(minMax[0], x0, x3);
756    minMax[1] = Math.min(minMax[1], y0, y3);
757    minMax[2] = Math.max(minMax[2], x0, x3);
758    minMax[3] = Math.max(minMax[3], y0, y3);
759    this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax);
760    this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax);
761  }
762}
763const PDFStringTranslateTable = (/* unused pure expression or super */ null && ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac]));
764function stringToPDFString(str, keepEscapeSequence = false) {
765  if (str[0] >= "\xEF") {
766    let encoding;
767    if (str[0] === "\xFE" && str[1] === "\xFF") {
768      encoding = "utf-16be";
769      if (str.length % 2 === 1) {
770        str = str.slice(0, -1);
771      }
772    } else if (str[0] === "\xFF" && str[1] === "\xFE") {
773      encoding = "utf-16le";
774      if (str.length % 2 === 1) {
775        str = str.slice(0, -1);
776      }
777    } else if (str[0] === "\xEF" && str[1] === "\xBB" && str[2] === "\xBF") {
778      encoding = "utf-8";
779    }
780    if (encoding) {
vendor: 18,792 bytes, lines 781-1454
781      try {
782        const decoder = new TextDecoder(encoding, {
783          fatal: true
784        });
785        const buffer = stringToBytes(str);
786        const decoded = decoder.decode(buffer);
787        if (keepEscapeSequence || !decoded.includes("\x1b")) {
788          return decoded;
789        }
790        return decoded.replaceAll(/\x1b[^\x1b]*(?:\x1b|$)/g, "");
791      } catch (ex) {
792        warn(`stringToPDFString: "${ex}".`);
793      }
794    }
795  }
796  const strBuf = [];
797  for (let i = 0, ii = str.length; i < ii; i++) {
798    const charCode = str.charCodeAt(i);
799    if (!keepEscapeSequence && charCode === 0x1b) {
800      while (++i < ii && str.charCodeAt(i) !== 0x1b) {}
801      continue;
802    }
803    const code = PDFStringTranslateTable[charCode];
804    strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
805  }
806  return strBuf.join("");
807}
808function stringToUTF8String(str) {
809  return decodeURIComponent(escape(str));
810}
811function utf8StringToString(str) {
812  return unescape(encodeURIComponent(str));
813}
814function isArrayEqual(arr1, arr2) {
815  if (arr1.length !== arr2.length) {
816    return false;
817  }
818  for (let i = 0, ii = arr1.length; i < ii; i++) {
819    if (arr1[i] !== arr2[i]) {
820      return false;
821    }
822  }
823  return true;
824}
825function getModificationDate(date = new Date()) {
826  if (!(date instanceof Date)) {
827    date = new Date(date);
828  }
829  const buffer = [date.getUTCFullYear().toString(), (date.getUTCMonth() + 1).toString().padStart(2, "0"), date.getUTCDate().toString().padStart(2, "0"), date.getUTCHours().toString().padStart(2, "0"), date.getUTCMinutes().toString().padStart(2, "0"), date.getUTCSeconds().toString().padStart(2, "0")];
830  return buffer.join("");
831}
832let NormalizeRegex = null;
833let NormalizationMap = null;
834function normalizeUnicode(str) {
835  if (!NormalizeRegex) {
836    NormalizeRegex = /([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu;
837    NormalizationMap = new Map([["ſt", "ſt"]]);
838  }
839  return str.replaceAll(NormalizeRegex, (_, p1, p2) => p1 ? p1.normalize("NFKC") : NormalizationMap.get(p2));
840}
841function getUuid() {
842  if (typeof crypto.randomUUID === "function") {
843    return crypto.randomUUID();
844  }
845  const buf = new Uint8Array(32);
846  crypto.getRandomValues(buf);
847  return bytesToString(buf);
848}
849const AnnotationPrefix = "pdfjs_internal_id_";
850function _isValidExplicitDest(validRef, validName, dest) {
851  if (!Array.isArray(dest) || dest.length < 2) {
852    return false;
853  }
854  const [page, zoom, ...args] = dest;
855  if (!validRef(page) && !Number.isInteger(page)) {
856    return false;
857  }
858  if (!validName(zoom)) {
859    return false;
860  }
861  const argsLen = args.length;
862  let allowNull = true;
863  switch (zoom.name) {
864    case "XYZ":
865      if (argsLen < 2 || argsLen > 3) {
866        return false;
867      }
868      break;
869    case "Fit":
870    case "FitB":
871      return argsLen === 0;
872    case "FitH":
873    case "FitBH":
874    case "FitV":
875    case "FitBV":
876      if (argsLen > 1) {
877        return false;
878      }
879      break;
880    case "FitR":
881      if (argsLen !== 4) {
882        return false;
883      }
884      allowNull = false;
885      break;
886    default:
887      return false;
888  }
889  for (const arg of args) {
890    if (typeof arg === "number" || allowNull && arg === null) {
891      continue;
892    }
893    return false;
894  }
895  return true;
896}
897function MathClamp(v, min, max) {
898  return Math.min(Math.max(v, min), max);
899}
900if (typeof Math.sumPrecise !== "function") {
901  Math.sumPrecise = function (numbers) {
902    return numbers.reduce((a, b) => a + b, 0);
903  };
904}
905
906;// ./src/display/xfa_text.js
907class XfaText {
908  static textContent(xfa) {
909    const items = [];
910    const output = {
911      items,
912      styles: Object.create(null)
913    };
914    function walk(node) {
915      if (!node) {
916        return;
917      }
918      let str = null;
919      const name = node.name;
920      if (name === "#text") {
921        str = node.value;
922      } else if (!XfaText.shouldBuildText(name)) {
923        return;
924      } else if (node?.attributes?.textContent) {
925        str = node.attributes.textContent;
926      } else if (node.value) {
927        str = node.value;
928      }
929      if (str !== null) {
930        items.push({
931          str
932        });
933      }
934      if (!node.children) {
935        return;
936      }
937      for (const child of node.children) {
938        walk(child);
939      }
940    }
941    walk(xfa);
942    return output;
943  }
944  static shouldBuildText(name) {
945    return !(name === "textarea" || name === "input" || name === "option" || name === "select");
946  }
947}
948
949;// ./src/display/xfa_layer.js
950
951class XfaLayer {
952  static setupStorage(html, id, element, storage, intent) {
953    const storedData = storage.getValue(id, {
954      value: null
955    });
956    switch (element.name) {
957      case "textarea":
958        if (storedData.value !== null) {
959          html.textContent = storedData.value;
960        }
961        if (intent === "print") {
962          break;
963        }
964        html.addEventListener("input", event => {
965          storage.setValue(id, {
966            value: event.target.value
967          });
968        });
969        break;
970      case "input":
971        if (element.attributes.type === "radio" || element.attributes.type === "checkbox") {
972          if (storedData.value === element.attributes.xfaOn) {
973            html.setAttribute("checked", true);
974          } else if (storedData.value === element.attributes.xfaOff) {
975            html.removeAttribute("checked");
976          }
977          if (intent === "print") {
978            break;
979          }
980          html.addEventListener("change", event => {
981            storage.setValue(id, {
982              value: event.target.checked ? event.target.getAttribute("xfaOn") : event.target.getAttribute("xfaOff")
983            });
984          });
985        } else {
986          if (storedData.value !== null) {
987            html.setAttribute("value", storedData.value);
988          }
989          if (intent === "print") {
990            break;
991          }
992          html.addEventListener("input", event => {
993            storage.setValue(id, {
994              value: event.target.value
995            });
996          });
997        }
998        break;
999      case "select":
1000        if (storedData.value !== null) {
1001          html.setAttribute("value", storedData.value);
1002          for (const option of element.children) {
1003            if (option.attributes.value === storedData.value) {
1004              option.attributes.selected = true;
1005            } else if (option.attributes.hasOwnProperty("selected")) {
1006              delete option.attributes.selected;
1007            }
1008          }
1009        }
1010        html.addEventListener("input", event => {
1011          const options = event.target.options;
1012          const value = options.selectedIndex === -1 ? "" : options[options.selectedIndex].value;
1013          storage.setValue(id, {
1014            value
1015          });
1016        });
1017        break;
1018    }
1019  }
1020  static setAttributes({
1021    html,
1022    element,
1023    storage = null,
1024    intent,
1025    linkService
1026  }) {
1027    const {
1028      attributes
1029    } = element;
1030    const isHTMLAnchorElement = html instanceof HTMLAnchorElement;
1031    if (attributes.type === "radio") {
1032      attributes.name = `${attributes.name}-${intent}`;
1033    }
1034    for (const [key, value] of Object.entries(attributes)) {
1035      if (value === null || value === undefined) {
1036        continue;
1037      }
1038      switch (key) {
1039        case "class":
1040          if (value.length) {
1041            html.setAttribute(key, value.join(" "));
1042          }
1043          break;
1044        case "dataId":
1045          break;
1046        case "id":
1047          html.setAttribute("data-element-id", value);
1048          break;
1049        case "style":
1050          Object.assign(html.style, value);
1051          break;
1052        case "textContent":
1053          html.textContent = value;
1054          break;
1055        default:
1056          if (!isHTMLAnchorElement || key !== "href" && key !== "newWindow") {
1057            html.setAttribute(key, value);
1058          }
1059      }
1060    }
1061    if (isHTMLAnchorElement) {
1062      linkService.addLinkAttributes(html, attributes.href, attributes.newWindow);
1063    }
1064    if (storage && attributes.dataId) {
1065      this.setupStorage(html, attributes.dataId, element, storage);
1066    }
1067  }
1068  static render(parameters) {
1069    const storage = parameters.annotationStorage;
1070    const linkService = parameters.linkService;
1071    const root = parameters.xfaHtml;
1072    const intent = parameters.intent || "display";
1073    const rootHtml = document.createElement(root.name);
1074    if (root.attributes) {
1075      this.setAttributes({
1076        html: rootHtml,
1077        element: root,
1078        intent,
1079        linkService
1080      });
1081    }
1082    const isNotForRichText = intent !== "richText";
1083    const rootDiv = parameters.div;
1084    rootDiv.append(rootHtml);
1085    if (parameters.viewport) {
1086      const transform = `matrix(${parameters.viewport.transform.join(",")})`;
1087      rootDiv.style.transform = transform;
1088    }
1089    if (isNotForRichText) {
1090      rootDiv.setAttribute("class", "xfaLayer xfaFont");
1091    }
1092    const textDivs = [];
1093    if (root.children.length === 0) {
1094      if (root.value) {
1095        const node = document.createTextNode(root.value);
1096        rootHtml.append(node);
1097        if (isNotForRichText && XfaText.shouldBuildText(root.name)) {
1098          textDivs.push(node);
1099        }
1100      }
1101      return {
1102        textDivs
1103      };
1104    }
1105    const stack = [[root, -1, rootHtml]];
1106    while (stack.length > 0) {
1107      const [parent, i, html] = stack.at(-1);
1108      if (i + 1 === parent.children.length) {
1109        stack.pop();
1110        continue;
1111      }
1112      const child = parent.children[++stack.at(-1)[1]];
1113      if (child === null) {
1114        continue;
1115      }
1116      const {
1117        name
1118      } = child;
1119      if (name === "#text") {
1120        const node = document.createTextNode(child.value);
1121        textDivs.push(node);
1122        html.append(node);
1123        continue;
1124      }
1125      const childHtml = child?.attributes?.xmlns ? document.createElementNS(child.attributes.xmlns, name) : document.createElement(name);
1126      html.append(childHtml);
1127      if (child.attributes) {
1128        this.setAttributes({
1129          html: childHtml,
1130          element: child,
1131          storage,
1132          intent,
1133          linkService
1134        });
1135      }
1136      if (child.children?.length > 0) {
1137        stack.push([child, -1, childHtml]);
1138      } else if (child.value) {
1139        const node = document.createTextNode(child.value);
1140        if (isNotForRichText && XfaText.shouldBuildText(name)) {
1141          textDivs.push(node);
1142        }
1143        childHtml.append(node);
1144      }
1145    }
1146    for (const el of rootDiv.querySelectorAll(".xfaNonInteractive input, .xfaNonInteractive textarea")) {
1147      el.setAttribute("readOnly", true);
1148    }
1149    return {
1150      textDivs
1151    };
1152  }
1153  static update(parameters) {
1154    const transform = `matrix(${parameters.viewport.transform.join(",")})`;
1155    parameters.div.style.transform = transform;
1156    parameters.div.hidden = false;
1157  }
1158}
1159
1160;// ./src/display/display_utils.js
1161
1162
1163const SVG_NS = "http://www.w3.org/2000/svg";
1164class PixelsPerInch {
1165  static CSS = 96.0;
1166  static PDF = 72.0;
1167  static PDF_TO_CSS_UNITS = this.CSS / this.PDF;
1168}
1169async function fetchData(url, type = "text") {
1170  if (isValidFetchUrl(url, document.baseURI)) {
1171    const response = await fetch(url);
1172    if (!response.ok) {
1173      throw new Error(response.statusText);
1174    }
1175    switch (type) {
1176      case "arraybuffer":
1177        return response.arrayBuffer();
1178      case "blob":
1179        return response.blob();
1180      case "json":
1181        return response.json();
1182    }
1183    return response.text();
1184  }
1185  return new Promise((resolve, reject) => {
1186    const request = new XMLHttpRequest();
1187    request.open("GET", url, true);
1188    request.responseType = type;
1189    request.onreadystatechange = () => {
1190      if (request.readyState !== XMLHttpRequest.DONE) {
1191        return;
1192      }
1193      if (request.status === 200 || request.status === 0) {
1194        switch (type) {
1195          case "arraybuffer":
1196          case "blob":
1197          case "json":
1198            resolve(request.response);
1199            return;
1200        }
1201        resolve(request.responseText);
1202        return;
1203      }
1204      reject(new Error(request.statusText));
1205    };
1206    request.send(null);
1207  });
1208}
1209class PageViewport {
1210  constructor({
1211    viewBox,
1212    userUnit,
1213    scale,
1214    rotation,
1215    offsetX = 0,
1216    offsetY = 0,
1217    dontFlip = false
1218  }) {
1219    this.viewBox = viewBox;
1220    this.userUnit = userUnit;
1221    this.scale = scale;
1222    this.rotation = rotation;
1223    this.offsetX = offsetX;
1224    this.offsetY = offsetY;
1225    scale *= userUnit;
1226    const centerX = (viewBox[2] + viewBox[0]) / 2;
1227    const centerY = (viewBox[3] + viewBox[1]) / 2;
1228    let rotateA, rotateB, rotateC, rotateD;
1229    rotation %= 360;
1230    if (rotation < 0) {
1231      rotation += 360;
1232    }
1233    switch (rotation) {
1234      case 180:
1235        rotateA = -1;
1236        rotateB = 0;
1237        rotateC = 0;
1238        rotateD = 1;
1239        break;
1240      case 90:
1241        rotateA = 0;
1242        rotateB = 1;
1243        rotateC = 1;
1244        rotateD = 0;
1245        break;
1246      case 270:
1247        rotateA = 0;
1248        rotateB = -1;
1249        rotateC = -1;
1250        rotateD = 0;
1251        break;
1252      case 0:
1253        rotateA = 1;
1254        rotateB = 0;
1255        rotateC = 0;
1256        rotateD = -1;
1257        break;
1258      default:
1259        throw new Error("PageViewport: Invalid rotation, must be a multiple of 90 degrees.");
1260    }
1261    if (dontFlip) {
1262      rotateC = -rotateC;
1263      rotateD = -rotateD;
1264    }
1265    let offsetCanvasX, offsetCanvasY;
1266    let width, height;
1267    if (rotateA === 0) {
1268      offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
1269      offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
1270      width = (viewBox[3] - viewBox[1]) * scale;
1271      height = (viewBox[2] - viewBox[0]) * scale;
1272    } else {
1273      offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
1274      offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
1275      width = (viewBox[2] - viewBox[0]) * scale;
1276      height = (viewBox[3] - viewBox[1]) * scale;
1277    }
1278    this.transform = [rotateA * scale, rotateB * scale, rotateC * scale, rotateD * scale, offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY];
1279    this.width = width;
1280    this.height = height;
1281  }
1282  get rawDims() {
1283    const dims = this.viewBox;
1284    return shadow(this, "rawDims", {
1285      pageWidth: dims[2] - dims[0],
1286      pageHeight: dims[3] - dims[1],
1287      pageX: dims[0],
1288      pageY: dims[1]
1289    });
1290  }
1291  clone({
1292    scale = this.scale,
1293    rotation = this.rotation,
1294    offsetX = this.offsetX,
1295    offsetY = this.offsetY,
1296    dontFlip = false
1297  } = {}) {
1298    return new PageViewport({
1299      viewBox: this.viewBox.slice(),
1300      userUnit: this.userUnit,
1301      scale,
1302      rotation,
1303      offsetX,
1304      offsetY,
1305      dontFlip
1306    });
1307  }
1308  convertToViewportPoint(x, y) {
1309    const p = [x, y];
1310    Util.applyTransform(p, this.transform);
1311    return p;
1312  }
1313  convertToViewportRectangle(rect) {
1314    const topLeft = [rect[0], rect[1]];
1315    Util.applyTransform(topLeft, this.transform);
1316    const bottomRight = [rect[2], rect[3]];
1317    Util.applyTransform(bottomRight, this.transform);
1318    return [topLeft[0], topLeft[1], bottomRight[0], bottomRight[1]];
1319  }
1320  convertToPdfPoint(x, y) {
1321    const p = [x, y];
1322    Util.applyInverseTransform(p, this.transform);
1323    return p;
1324  }
1325}
1326class RenderingCancelledException extends BaseException {
1327  constructor(msg, extraDelay = 0) {
1328    super(msg, "RenderingCancelledException");
1329    this.extraDelay = extraDelay;
1330  }
1331}
1332function isDataScheme(url) {
1333  const ii = url.length;
1334  let i = 0;
1335  while (i < ii && url[i].trim() === "") {
1336    i++;
1337  }
1338  return url.substring(i, i + 5).toLowerCase() === "data:";
1339}
1340function isPdfFile(filename) {
1341  return typeof filename === "string" && /\.pdf$/i.test(filename);
1342}
1343function getFilenameFromUrl(url) {
1344  [url] = url.split(/[#?]/, 1);
1345  return url.substring(url.lastIndexOf("/") + 1);
1346}
1347function getPdfFilenameFromUrl(url, defaultFilename = "document.pdf") {
1348  if (typeof url !== "string") {
1349    return defaultFilename;
1350  }
1351  if (isDataScheme(url)) {
1352    warn('getPdfFilenameFromUrl: ignore "data:"-URL for performance reasons.');
1353    return defaultFilename;
1354  }
1355  const getURL = urlString => {
1356    try {
1357      return new URL(urlString);
1358    } catch {
1359      try {
1360        return new URL(decodeURIComponent(urlString));
1361      } catch {
1362        try {
1363          return new URL(urlString, "https://foo.bar");
1364        } catch {
1365          try {
1366            return new URL(decodeURIComponent(urlString), "https://foo.bar");
1367          } catch {
1368            return null;
1369          }
1370        }
1371      }
1372    }
1373  };
1374  const newURL = getURL(url);
1375  if (!newURL) {
1376    return defaultFilename;
1377  }
1378  const decode = name => {
1379    try {
1380      let decoded = decodeURIComponent(name);
1381      if (decoded.includes("/")) {
1382        decoded = decoded.split("/").at(-1);
1383        if (decoded.test(/^\.pdf$/i)) {
1384          return decoded;
1385        }
1386        return name;
1387      }
1388      return decoded;
1389    } catch {
1390      return name;
1391    }
1392  };
1393  const pdfRegex = /\.pdf$/i;
1394  const filename = newURL.pathname.split("/").at(-1);
1395  if (pdfRegex.test(filename)) {
1396    return decode(filename);
1397  }
1398  if (newURL.searchParams.size > 0) {
1399    const values = Array.from(newURL.searchParams.values()).reverse();
1400    for (const value of values) {
1401      if (pdfRegex.test(value)) {
1402        return decode(value);
1403      }
1404    }
1405    const keys = Array.from(newURL.searchParams.keys()).reverse();
1406    for (const key of keys) {
1407      if (pdfRegex.test(key)) {
1408        return decode(key);
1409      }
1410    }
1411  }
1412  if (newURL.hash) {
1413    const reFilename = /[^/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
1414    const hashFilename = reFilename.exec(newURL.hash);
1415    if (hashFilename) {
1416      return decode(hashFilename[0]);
1417    }
1418  }
1419  return defaultFilename;
1420}
1421class StatTimer {
1422  started = Object.create(null);
1423  times = [];
1424  time(name) {
1425    if (name in this.started) {
1426      warn(`Timer is already running for ${name}`);
1427    }
1428    this.started[name] = Date.now();
1429  }
1430  timeEnd(name) {
1431    if (!(name in this.started)) {
1432      warn(`Timer has not been started for ${name}`);
1433    }
1434    this.times.push({
1435      name,
1436      start: this.started[name],
1437      end: Date.now()
1438    });
1439    delete this.started[name];
1440  }
1441  toString() {
1442    const outBuf = [];
1443    let longest = 0;
1444    for (const {
1445      name
1446    } of this.times) {
1447      longest = Math.max(name.length, longest);
1448    }
1449    for (const {
1450      name,
1451      start,
1452      end
1453    } of this.times) {
1454      outBuf.push(`${name.padEnd(longest)} ${end - start}
1454ms\n`);
1455    }
1456    return outBuf.join("");
1457  }
1458}
1459function isValidFetchUrl(url, baseUrl) {
1460  const res = baseUrl ? URL.parse(url, baseUrl) : URL.parse(url);
1461  return res?.protocol === "http:" || res?.protocol === "https:";
1462}
1463function noContextMenu(e) {
1464  e.preventDefault();
1465}
1466function stopEvent(e) {
1467  e.preventDefault();
1468  e.stopPropagation();
1469}
1470function deprecated(details) {
1471  console.log("Deprecated API usage: " + details);
1472}
1473class PDFDateString {
1474  static #regex;
1475  static toDateObject(input) {
1476    if (input instanceof Date) {
1477      return input;
1478    }
1479    if (!input || typeof input !== "string") {
1480      return null;
1481    }
1482    this.#regex ||= new RegExp("^D:" + "(\\d{4})" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "([Z|+|-])?" + "(\\d{2})?" + "'?" + "(\\d{2})?" + "'?");
1483    const matches = this.#regex.exec(input);
1484    if (!matches) {
1485      return null;
1486    }
1487    const year = parseInt(matches[1], 10);
1488    let month = parseInt(matches[2], 10);
1489    month = month >= 1 && month <= 12 ? month - 1 : 0;
1490    let day = parseInt(matches[3], 10);
1491    day = day >= 1 && day <= 31 ? day : 1;
1492    let hour = parseInt(matches[4], 10);
1493    hour = hour >= 0 && hour <= 23 ? hour : 0;
1494    let minute = parseInt(matches[5], 10);
1495    minute = minute >= 0 && minute <= 59 ? minute : 0;
1496    let second = parseInt(matches[6], 10);
1497    second = second >= 0 && second <= 59 ? second : 0;
1498    const universalTimeRelation = matches[7] || "Z";
1499    let offsetHour = parseInt(matches[8], 10);
1500    offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0;
1501    let offsetMinute = parseInt(matches[9], 10) || 0;
1502    offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0;
1503    if (universalTimeRelation === "-") {
1504      hour += offsetHour;
1505      minute += offsetMinute;
1506    } else if (universalTimeRelation === "+") {
1507      hour -= offsetHour;
1508      minute -= offsetMinute;
1509    }
1510    return new Date(Date.UTC(year, month, day, hour, minute, second));
1511  }
1512}
1513function getXfaPageViewport(xfaPage, {
1514  scale = 1,
1515  rotation = 0
1516}) {
1517  const {
1518    width,
1519    height
1520  } = xfaPage.attributes.style;
1521  const viewBox = [0, 0, parseInt(width), parseInt(height)];
1522  return new PageViewport({
1523    viewBox,
1524    userUnit: 1,
1525    scale,
1526    rotation
1527  });
1528}
1529function getRGB(color) {
1530  if (color.startsWith("#")) {
1531    const colorRGB = parseInt(color.slice(1), 16);
1532    return [(colorRGB & 0xff0000) >> 16, (colorRGB & 0x00ff00) >> 8, colorRGB & 0x0000ff];
1533  }
1534  if (color.startsWith("rgb(")) {
1535    return color.slice(4, -1).split(",").map(x => parseInt(x));
1536  }
1537  if (color.startsWith("rgba(")) {
1538    return color.slice(5, -1).split(",").map(x => parseInt(x)).slice(0, 3);
1539  }
1540  warn(`Not a valid color format: "${color}"`);
1541  return [0, 0, 0];
1542}
1543function getColorValues(colors) {
1544  const span = document.createElement("span");
1545  span.style.visibility = "hidden";
1546  span.style.colorScheme = "only light";
1547  document.body.append(span);
1548  for (const name of colors.keys()) {
1549    span.style.color = name;
1550    const computedColor = window.getComputedStyle(span).color;
1551    colors.set(name, getRGB(computedColor));
1552  }
1553  span.remove();
1554}
1555function getCurrentTransform(ctx) {
1556  const {
1557    a,
1558    b,
1559    c,
1560    d,
1561    e,
1562    f
1563  } = ctx.getTransform();
1564  return [a, b, c, d, e, f];
1565}
1566function getCurrentTransformInverse(ctx) {
1567  const {
1568    a,
1569    b,
1570    c,
1571    d,
1572    e,
1573    f
1574  } = ctx.getTransform().invertSelf();
1575  return [a, b, c, d, e, f];
1576}
1577function setLayerDimensions(div, viewport, mustFlip = false, mustRotate = true) {
1578  if (viewport instanceof PageViewport) {
1579    const {
1580      pageWidth,
1581      pageHeight
1582    } = viewport.rawDims;
1583    const {
1584      style
1585    } = div;
1586    const useRound = util_FeatureTest.isCSSRoundSupported;
1587    const w = `var(--total-scale-factor) * ${pageWidth}px`,
1588      h = `var(--total-scale-factor) * ${pageHeight}px`;
1589    const widthStr = useRound ? `round(down, ${w}, var(--scale-round-x))` : `calc(${w})`,
1590      heightStr = useRound ? `round(down, ${h}, var(--scale-round-y))` : `calc(${h})`;
1591    if (!mustFlip || viewport.rotation % 180 === 0) {
1592      style.width = widthStr;
1593      style.height = heightStr;
1594    } else {
1595      style.width = heightStr;
1596      style.height = widthStr;
1597    }
1598  }
1599  if (mustRotate) {
1600    div.setAttribute("data-main-rotation", viewport.rotation);
1601  }
1602}
1603class OutputScale {
1604  constructor() {
1605    const {
1606      pixelRatio
1607    } = OutputScale;
1608    this.sx = pixelRatio;
1609    this.sy = pixelRatio;
1610  }
1611  get scaled() {
1612    return this.sx !== 1 || this.sy !== 1;
1613  }
1614  get symmetric() {
1615    return this.sx === this.sy;
1616  }
1617  limitCanvas(width, height, maxPixels, maxDim, capAreaFactor = -1) {
1618    let maxAreaScale = Infinity,
1619      maxWidthScale = Infinity,
1620      maxHeightScale = Infinity;
1621    maxPixels = OutputScale.capPixels(maxPixels, capAreaFactor);
1622    if (maxPixels > 0) {
1623      maxAreaScale = Math.sqrt(maxPixels / (width * height));
1624    }
1625    if (maxDim !== -1) {
1626      maxWidthScale = maxDim / width;
1627      maxHeightScale = maxDim / height;
1628    }
1629    const maxScale = Math.min(maxAreaScale, maxWidthScale, maxHeightScale);
1630    if (this.sx > maxScale || this.sy > maxScale) {
1631      this.sx = maxScale;
1632      this.sy = maxScale;
1633      return true;
1634    }
1635    return false;
vendor: 6,348 bytes, lines 1636-1847
1636  }
1637  static get pixelRatio() {
1638    return globalThis.devicePixelRatio || 1;
1639  }
1640  static capPixels(maxPixels, capAreaFactor) {
1641    if (capAreaFactor >= 0) {
1642      const winPixels = Math.ceil(window.screen.availWidth * window.screen.availHeight * this.pixelRatio ** 2 * (1 + capAreaFactor / 100));
1643      return maxPixels > 0 ? Math.min(maxPixels, winPixels) : winPixels;
1644    }
1645    return maxPixels;
1646  }
1647}
1648const SupportedImageMimeTypes = ["image/apng", "image/avif", "image/bmp", "image/gif", "image/jpeg", "image/png", "image/svg+xml", "image/webp", "image/x-icon"];
1649class ColorScheme {
1650  static get isDarkMode() {
1651    return shadow(this, "isDarkMode", !!window?.matchMedia?.("(prefers-color-scheme: dark)").matches);
1652  }
1653}
1654class CSSConstants {
1655  static get commentForegroundColor() {
1656    const element = document.createElement("span");
1657    element.classList.add("comment", "sidebar");
1658    const {
1659      style
1660    } = element;
1661    style.width = style.height = "0";
1662    style.display = "none";
1663    style.color = "var(--comment-fg-color)";
1664    document.body.append(element);
1665    const {
1666      color
1667    } = window.getComputedStyle(element);
1668    element.remove();
1669    return shadow(this, "commentForegroundColor", getRGB(color));
1670  }
1671}
1672function applyOpacity(r, g, b, opacity) {
1673  opacity = Math.min(Math.max(opacity ?? 1, 0), 1);
1674  const white = 255 * (1 - opacity);
1675  r = Math.round(r * opacity + white);
1676  g = Math.round(g * opacity + white);
1677  b = Math.round(b * opacity + white);
1678  return [r, g, b];
1679}
1680function RGBToHSL(rgb, output) {
1681  const r = rgb[0] / 255;
1682  const g = rgb[1] / 255;
1683  const b = rgb[2] / 255;
1684  const max = Math.max(r, g, b);
1685  const min = Math.min(r, g, b);
1686  const l = (max + min) / 2;
1687  if (max === min) {
1688    output[0] = output[1] = 0;
1689  } else {
1690    const d = max - min;
1691    output[1] = l < 0.5 ? d / (max + min) : d / (2 - max - min);
1692    switch (max) {
1693      case r:
1694        output[0] = ((g - b) / d + (g < b ? 6 : 0)) * 60;
1695        break;
1696      case g:
1697        output[0] = ((b - r) / d + 2) * 60;
1698        break;
1699      case b:
1700        output[0] = ((r - g) / d + 4) * 60;
1701        break;
1702    }
1703  }
1704  output[2] = l;
1705}
1706function HSLToRGB(hsl, output) {
1707  const h = hsl[0];
1708  const s = hsl[1];
1709  const l = hsl[2];
1710  const c = (1 - Math.abs(2 * l - 1)) * s;
1711  const x = c * (1 - Math.abs(h / 60 % 2 - 1));
1712  const m = l - c / 2;
1713  switch (Math.floor(h / 60)) {
1714    case 0:
1715      output[0] = c + m;
1716      output[1] = x + m;
1717      output[2] = m;
1718      break;
1719    case 1:
1720      output[0] = x + m;
1721      output[1] = c + m;
1722      output[2] = m;
1723      break;
1724    case 2:
1725      output[0] = m;
1726      output[1] = c + m;
1727      output[2] = x + m;
1728      break;
1729    case 3:
1730      output[0] = m;
1731      output[1] = x + m;
1732      output[2] = c + m;
1733      break;
1734    case 4:
1735      output[0] = x + m;
1736      output[1] = m;
1737      output[2] = c + m;
1738      break;
1739    case 5:
1740    case 6:
1741      output[0] = c + m;
1742      output[1] = m;
1743      output[2] = x + m;
1744      break;
1745  }
1746}
1747function computeLuminance(x) {
1748  return x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4;
1749}
1750function contrastRatio(hsl1, hsl2, output) {
1751  HSLToRGB(hsl1, output);
1752  output.map(computeLuminance);
1753  const lum1 = 0.2126 * output[0] + 0.7152 * output[1] + 0.0722 * output[2];
1754  HSLToRGB(hsl2, output);
1755  output.map(computeLuminance);
1756  const lum2 = 0.2126 * output[0] + 0.7152 * output[1] + 0.0722 * output[2];
1757  return lum1 > lum2 ? (lum1 + 0.05) / (lum2 + 0.05) : (lum2 + 0.05) / (lum1 + 0.05);
1758}
1759const contrastCache = new Map();
1760function findContrastColor(baseColor, fixedColor) {
1761  const key = baseColor[0] + baseColor[1] * 0x100 + baseColor[2] * 0x10000 + fixedColor[0] * 0x1000000 + fixedColor[1] * 0x100000000 + fixedColor[2] * 0x10000000000;
1762  let cachedValue = contrastCache.get(key);
1763  if (cachedValue) {
1764    return cachedValue;
1765  }
1766  const array = new Float32Array(9);
1767  const output = array.subarray(0, 3);
1768  const baseHSL = array.subarray(3, 6);
1769  RGBToHSL(baseColor, baseHSL);
1770  const fixedHSL = array.subarray(6, 9);
1771  RGBToHSL(fixedColor, fixedHSL);
1772  const isFixedColorDark = fixedHSL[2] < 0.5;
1773  const minContrast = isFixedColorDark ? 12 : 4.5;
1774  baseHSL[2] = isFixedColorDark ? Math.sqrt(baseHSL[2]) : 1 - Math.sqrt(1 - baseHSL[2]);
1775  if (contrastRatio(baseHSL, fixedHSL, output) < minContrast) {
1776    let start, end;
1777    if (isFixedColorDark) {
1778      start = baseHSL[2];
1779      end = 1;
1780    } else {
1781      start = 0;
1782      end = baseHSL[2];
1783    }
1784    const PRECISION = 0.005;
1785    while (end - start > PRECISION) {
1786      const mid = baseHSL[2] = (start + end) / 2;
1787      if (isFixedColorDark === contrastRatio(baseHSL, fixedHSL, output) < minContrast) {
1788        start = mid;
1789      } else {
1790        end = mid;
1791      }
1792    }
1793    baseHSL[2] = isFixedColorDark ? end : start;
1794  }
1795  HSLToRGB(baseHSL, output);
1796  cachedValue = Util.makeHexColor(Math.round(output[0] * 255), Math.round(output[1] * 255), Math.round(output[2] * 255));
1797  contrastCache.set(key, cachedValue);
1798  return cachedValue;
1799}
1800function renderRichText({
1801  html,
1802  dir,
1803  className
1804}, container) {
1805  const fragment = document.createDocumentFragment();
1806  if (typeof html === "string") {
1807    const p = document.createElement("p");
1808    p.dir = dir || "auto";
1809    const lines = html.split(/(?:\r\n?|\n)/);
1810    for (let i = 0, ii = lines.length; i < ii; ++i) {
1811      const line = lines[i];
1812      p.append(document.createTextNode(line));
1813      if (i < ii - 1) {
1814        p.append(document.createElement("br"));
1815      }
1816    }
1817    fragment.append(p);
1818  } else {
1819    XfaLayer.render({
1820      xfaHtml: html,
1821      div: fragment,
1822      intent: "richText"
1823    });
1824  }
1825  fragment.firstElementChild.classList.add("richText", className);
1826  container.append(fragment);
1827}
1828function makePathFromDrawOPS(data) {
1829  const path = new Path2D();
1830  if (!data) {
1831    return path;
1832  }
1833  for (let i = 0, ii = data.length; i < ii;) {
1834    switch (data[i++]) {
1835      case DrawOPS.moveTo:
1836        path.moveTo(data[i++], data[i++]);
1837        break;
1838      case DrawOPS.lineTo:
1839        path.lineTo(data[i++], data[i++]);
1840        break;
1841      case DrawOPS.curveTo:
1842        path.bezierCurveTo(data[i++], data[i++], data[i++], data[i++], data[i++], data[i++]);
1843        break;
1844      case DrawOPS.quadraticCurveTo:
1845        path.quadraticCurveTo(data[i++], data[i++], data[i++], data[i++]);
1846        break;
1847      case DrawOPS.closePath:
1848        path.closePath();
1849        break;
1850      default:
1851        warn(`Unrecognized drawing path operator: ${data[i - 1]}`);
1852        break;
1853    }
1854  }
1855  return path;
1856}
1857class PagesMapper {
1858  static #idToPageNumber = null;
1859  static #pageNumberToId = null;
1860  static #prevIdToPageNumber = null;
1861  static #pagesNumber = 0;
1862  static #listeners = [];
1863  get pagesNumber() {
1864    return PagesMapper.#pagesNumber;
1865  }
1866  set pagesNumber(n) {
1867    if (PagesMapper.#pagesNumber === n) {
1868      return;
1869    }
1870    PagesMapper.#pagesNumber = n;
1871    if (n === 0) {
1872      PagesMapper.#pageNumberToId = null;
1873      PagesMapper.#idToPageNumber = null;
1874    }
1875  }
1876  addListener(listener) {
1877    PagesMapper.#listeners.push(listener);
1878  }
1879  removeListener(listener) {
1880    const index = PagesMapper.#listeners.indexOf(listener);
1881    if (index >= 0) {
1882      PagesMapper.#listeners.splice(index, 1);
1883    }
1884  }
1885  #updateListeners() {
1886    for (const listener of PagesMapper.#listeners) {
1887      listener();
1888    }
1889  }
1890  #init(mustInit) {
1891    if (PagesMapper.#pageNumberToId) {
1892      return;
1893    }
1894    const n = PagesMapper.#pagesNumber;
1895    const array = new Uint32Array(3 * n);
1896    const pageNumberToId = PagesMapper.#pageNumberToId = array.subarray(0, n);
1897    const idToPageNumber = PagesMapper.#idToPageNumber = array.subarray(n, 2 * n);
1898    if (mustInit) {
1899      for (let i = 0; i < n; i++) {
1900        pageNumberToId[i] = idToPageNumber[i] = i + 1;
1901      }
1902    }
1903    PagesMapper.#prevIdToPageNumber = array.subarray(2 * n);
1904  }
1905  movePages(selectedPages, pagesToMove, index) {
1906    this.#init(true);
1907    const pageNumberToId = PagesMapper.#pageNumberToId;
1908    const idToPageNumber = PagesMapper.#idToPageNumber;
1909    PagesMapper.#prevIdToPageNumber.set(idToPageNumber);
1910    const movedCount = pagesToMove.length;
1911    const mappedPagesToMove = new Uint32Array(movedCount);
1912    let removedBeforeTarget = 0;
1913    for (let i = 0; i < movedCount; i++) {
1914      const pageIndex = pagesToMove[i] - 1;
1915      mappedPagesToMove[i] = pageNumberToId[pageIndex];
1916      if (pageIndex < index) {
1917        removedBeforeTarget += 1;
1918      }
1919    }
1920    const pagesNumber = PagesMapper.#pagesNumber;
1921    let adjustedTarget = index - removedBeforeTarget;
1922    const remainingLen = pagesNumber - movedCount;
1923    adjustedTarget = MathClamp(adjustedTarget, 0, remainingLen);
1924    for (let i = 0, r = 0; i < pagesNumber; i++) {
1925      if (!selectedPages.has(i + 1)) {
1926        pageNumberToId[r++] = pageNumberToId[i];
1927      }
1928    }
1929    pageNumberToId.copyWithin(adjustedTarget + movedCount, adjustedTarget, remainingLen);
1930    pageNumberToId.set(mappedPagesToMove, adjustedTarget);
1931    let hasChanged = false;
1932    for (let i = 0, ii = pagesNumber; i < ii; i++) {
1933      const id = pageNumberToId[i];
1934      hasChanged ||= id !== i + 1;
1935      idToPageNumber[id - 1] = i + 1;
1936    }
1937    this.#updateListeners();
1938    if (!hasChanged) {
1939      this.pagesNumber = 0;
1940    }
1941  }
1942  hasBeenAltered() {
1943    return PagesMapper.#pageNumberToId !== null;
1944  }
1945  getPageMappingForSaving() {
1946    return {
1947      pageIndices: PagesMapper.#idToPageNumber ? PagesMapper.#idToPageNumber.map(x => x - 1) : null
1948    };
1949  }
1950  getPrevPageNumber(pageNumber) {
1951    return PagesMapper.#prevIdToPageNumber[PagesMapper.#pageNumberToId[pageNumber - 1] - 1];
1952  }
1953  getPageNumber(id) {
1954    return PagesMapper.#idToPageNumber?.[id - 1] ?? id;
1955  }
1956  getPageId(pageNumber) {
1957    return PagesMapper.#pageNumberToId?.[pageNumber - 1] ?? pageNumber;
1958  }
1959  static get instance() {
1960    return shadow(this, "instance", new PagesMapper());
1961  }
1962  getMapping() {
1963    return PagesMapper.#pageNumberToId.subarray(0, this.pagesNumber);
1964  }
1965}
1966
1967;// ./src/display/editor/toolbar.js
1968
1969class EditorToolbar {
1970  #toolbar = null;
1971  #colorPicker = null;
1972  #editor;
1973  #buttons = null;
1974  #altText = null;
1975  #comment = null;
1976  #commentButtonDivider = null;
1977  #signatureDescriptionButton = null;
1978  static #l10nRemove = null;
1979  constructor(editor) {
1980    this.#editor = editor;
1981    EditorToolbar.#l10nRemove ||= Object.freeze({
1982      freetext: "pdfjs-editor-remove-freetext-button",
1983      highlight: "pdfjs-editor-remove-highlight-button",
1984      ink: "pdfjs-editor-remove-ink-button",
1985      stamp: "pdfjs-editor-remove-stamp-button",
1986      signature: "pdfjs-editor-remove-signature-button"
1987    });
1988  }
1989  render() {
1990    const editToolbar = this.#toolbar = document.createElement("div");
1991    editToolbar.classList.add("editToolbar", "hidden");
1992    editToolbar.setAttribute("role", "toolbar");
1993    const signal = this.#editor._uiManager._signal;
1994    if (signal instanceof AbortSignal && !signal.aborted) {
1995      editToolbar.addEventListener("contextmenu", noContextMenu, {
1996        signal
1997      });
1998      editToolbar.addEventListener("pointerdown", EditorToolbar.#pointerDown, {
vendor: 14,026 bytes, lines 1999-2499
1999        signal
2000      });
2001    }
2002    const buttons = this.#buttons = document.createElement("div");
2003    buttons.className = "buttons";
2004    editToolbar.append(buttons);
2005    const position = this.#editor.toolbarPosition;
2006    if (position) {
2007      const {
2008        style
2009      } = editToolbar;
2010      const x = this.#editor._uiManager.direction === "ltr" ? 1 - position[0] : position[0];
2011      style.insetInlineEnd = `${100 * x}%`;
2012      style.top = `calc(${100 * position[1]}% + var(--editor-toolbar-vert-offset))`;
2013    }
2014    return editToolbar;
2015  }
2016  get div() {
2017    return this.#toolbar;
2018  }
2019  static #pointerDown(e) {
2020    e.stopPropagation();
2021  }
2022  #focusIn(e) {
2023    this.#editor._focusEventsAllowed = false;
2024    stopEvent(e);
2025  }
2026  #focusOut(e) {
2027    this.#editor._focusEventsAllowed = true;
2028    stopEvent(e);
2029  }
2030  #addListenersToElement(element) {
2031    const signal = this.#editor._uiManager._signal;
2032    if (!(signal instanceof AbortSignal) || signal.aborted) {
2033      return false;
2034    }
2035    element.addEventListener("focusin", this.#focusIn.bind(this), {
2036      capture: true,
2037      signal
2038    });
2039    element.addEventListener("focusout", this.#focusOut.bind(this), {
2040      capture: true,
2041      signal
2042    });
2043    element.addEventListener("contextmenu", noContextMenu, {
2044      signal
2045    });
2046    return true;
2047  }
2048  hide() {
2049    this.#toolbar.classList.add("hidden");
2050    this.#colorPicker?.hideDropdown();
2051  }
2052  show() {
2053    this.#toolbar.classList.remove("hidden");
2054    this.#altText?.shown();
2055    this.#comment?.shown();
2056  }
2057  addDeleteButton() {
2058    const {
2059      editorType,
2060      _uiManager
2061    } = this.#editor;
2062    const button = document.createElement("button");
2063    button.classList.add("basic", "deleteButton");
2064    button.tabIndex = 0;
2065    button.setAttribute("data-l10n-id", EditorToolbar.#l10nRemove[editorType]);
2066    if (this.#addListenersToElement(button)) {
2067      button.addEventListener("click", e => {
2068        _uiManager.delete();
2069      }, {
2070        signal: _uiManager._signal
2071      });
2072    }
2073    this.#buttons.append(button);
2074  }
2075  get #divider() {
2076    const divider = document.createElement("div");
2077    divider.className = "divider";
2078    return divider;
2079  }
2080  async addAltText(altText) {
2081    const button = await altText.render();
2082    this.#addListenersToElement(button);
2083    this.#buttons.append(button, this.#divider);
2084    this.#altText = altText;
2085  }
2086  addComment(comment, beforeElement = null) {
2087    if (this.#comment) {
2088      return;
2089    }
2090    const button = comment.renderForToolbar();
2091    if (!button) {
2092      return;
2093    }
2094    this.#addListenersToElement(button);
2095    const divider = this.#commentButtonDivider = this.#divider;
2096    if (!beforeElement) {
2097      this.#buttons.append(button, divider);
2098    } else {
2099      this.#buttons.insertBefore(button, beforeElement);
2100      this.#buttons.insertBefore(divider, beforeElement);
2101    }
2102    this.#comment = comment;
2103    comment.toolbar = this;
2104  }
2105  addColorPicker(colorPicker) {
2106    if (this.#colorPicker) {
2107      return;
2108    }
2109    this.#colorPicker = colorPicker;
2110    const button = colorPicker.renderButton();
2111    this.#addListenersToElement(button);
2112    this.#buttons.append(button, this.#divider);
2113  }
2114  async addEditSignatureButton(signatureManager) {
2115    const button = this.#signatureDescriptionButton = await signatureManager.renderEditButton(this.#editor);
2116    this.#addListenersToElement(button);
2117    this.#buttons.append(button, this.#divider);
2118  }
2119  removeButton(name) {
2120    switch (name) {
2121      case "comment":
2122        this.#comment?.removeToolbarCommentButton();
2123        this.#comment = null;
2124        this.#commentButtonDivider?.remove();
2125        this.#commentButtonDivider = null;
2126        break;
2127    }
2128  }
2129  async addButton(name, tool) {
2130    switch (name) {
2131      case "colorPicker":
2132        if (tool) {
2133          this.addColorPicker(tool);
2134        }
2135        break;
2136      case "altText":
2137        if (tool) {
2138          await this.addAltText(tool);
2139        }
2140        break;
2141      case "editSignature":
2142        if (tool) {
2143          await this.addEditSignatureButton(tool);
2144        }
2145        break;
2146      case "delete":
2147        this.addDeleteButton();
2148        break;
2149      case "comment":
2150        if (tool) {
2151          this.addComment(tool);
2152        }
2153        break;
2154    }
2155  }
2156  async addButtonBefore(name, tool, beforeSelector) {
2157    if (!tool && name === "comment") {
2158      return;
2159    }
2160    const beforeElement = this.#buttons.querySelector(beforeSelector);
2161    if (!beforeElement) {
2162      return;
2163    }
2164    if (name === "comment") {
2165      this.addComment(tool, beforeElement);
2166    }
2167  }
2168  updateEditSignatureButton(description) {
2169    if (this.#signatureDescriptionButton) {
2170      this.#signatureDescriptionButton.title = description;
2171    }
2172  }
2173  remove() {
2174    this.#toolbar.remove();
2175    this.#colorPicker?.destroy();
2176    this.#colorPicker = null;
2177  }
2178}
2179class FloatingToolbar {
2180  #buttons = null;
2181  #toolbar = null;
2182  #uiManager;
2183  constructor(uiManager) {
2184    this.#uiManager = uiManager;
2185  }
2186  #render() {
2187    const editToolbar = this.#toolbar = document.createElement("div");
2188    editToolbar.className = "editToolbar";
2189    editToolbar.setAttribute("role", "toolbar");
2190    const signal = this.#uiManager._signal;
2191    if (signal instanceof AbortSignal && !signal.aborted) {
2192      editToolbar.addEventListener("contextmenu", noContextMenu, {
2193        signal
2194      });
2195    }
2196    const buttons = this.#buttons = document.createElement("div");
2197    buttons.className = "buttons";
2198    editToolbar.append(buttons);
2199    if (this.#uiManager.hasCommentManager()) {
2200      this.#makeButton("commentButton", `pdfjs-comment-floating-button`, "pdfjs-comment-floating-button-label", () => {
2201        this.#uiManager.commentSelection("floating_button");
2202      });
2203    }
2204    this.#makeButton("highlightButton", `pdfjs-highlight-floating-button1`, "pdfjs-highlight-floating-button-label", () => {
2205      this.#uiManager.highlightSelection("floating_button");
2206    });
2207    return editToolbar;
2208  }
2209  #getLastPoint(boxes, isLTR) {
2210    let lastY = 0;
2211    let lastX = 0;
2212    for (const box of boxes) {
2213      const y = box.y + box.height;
2214      if (y < lastY) {
2215        continue;
2216      }
2217      const x = box.x + (isLTR ? box.width : 0);
2218      if (y > lastY) {
2219        lastX = x;
2220        lastY = y;
2221        continue;
2222      }
2223      if (isLTR) {
2224        if (x > lastX) {
2225          lastX = x;
2226        }
2227      } else if (x < lastX) {
2228        lastX = x;
2229      }
2230    }
2231    return [isLTR ? 1 - lastX : lastX, lastY];
2232  }
2233  show(parent, boxes, isLTR) {
2234    const [x, y] = this.#getLastPoint(boxes, isLTR);
2235    const {
2236      style
2237    } = this.#toolbar ||= this.#render();
2238    parent.append(this.#toolbar);
2239    style.insetInlineEnd = `${100 * x}%`;
2240    style.top = `calc(${100 * y}% + var(--editor-toolbar-vert-offset))`;
2241  }
2242  hide() {
2243    this.#toolbar.remove();
2244  }
2245  #makeButton(buttonClass, l10nId, labelL10nId, clickHandler) {
2246    const button = document.createElement("button");
2247    button.classList.add("basic", buttonClass);
2248    button.tabIndex = 0;
2249    button.setAttribute("data-l10n-id", l10nId);
2250    const span = document.createElement("span");
2251    button.append(span);
2252    span.className = "visuallyHidden";
2253    span.setAttribute("data-l10n-id", labelL10nId);
2254    const signal = this.#uiManager._signal;
2255    if (signal instanceof AbortSignal && !signal.aborted) {
2256      button.addEventListener("contextmenu", noContextMenu, {
2257        signal
2258      });
2259      button.addEventListener("click", clickHandler, {
2260        signal
2261      });
2262    }
2263    this.#buttons.append(button);
2264  }
2265}
2266
2267;// ./src/display/editor/tools.js
2268
2269
2270
2271function bindEvents(obj, element, names) {
2272  for (const name of names) {
2273    element.addEventListener(name, obj[name].bind(obj));
2274  }
2275}
2276class CurrentPointers {
2277  static #pointerId = NaN;
2278  static #pointerIds = null;
2279  static #moveTimestamp = NaN;
2280  static #pointerType = null;
2281  static initializeAndAddPointerId(pointerId) {
2282    (CurrentPointers.#pointerIds ||= new Set()).add(pointerId);
2283  }
2284  static setPointer(pointerType, pointerId) {
2285    CurrentPointers.#pointerId ||= pointerId;
2286    CurrentPointers.#pointerType ??= pointerType;
2287  }
2288  static setTimeStamp(timeStamp) {
2289    CurrentPointers.#moveTimestamp = timeStamp;
2290  }
2291  static isSamePointerId(pointerId) {
2292    return CurrentPointers.#pointerId === pointerId;
2293  }
2294  static isSamePointerIdOrRemove(pointerId) {
2295    if (CurrentPointers.#pointerId === pointerId) {
2296      return true;
2297    }
2298    CurrentPointers.#pointerIds?.delete(pointerId);
2299    return false;
2300  }
2301  static isSamePointerType(pointerType) {
2302    return CurrentPointers.#pointerType === pointerType;
2303  }
2304  static isInitializedAndDifferentPointerType(pointerType) {
2305    return CurrentPointers.#pointerType !== null && !CurrentPointers.isSamePointerType(pointerType);
2306  }
2307  static isSameTimeStamp(timeStamp) {
2308    return CurrentPointers.#moveTimestamp === timeStamp;
2309  }
2310  static isUsingMultiplePointers() {
2311    return CurrentPointers.#pointerIds?.size >= 1;
2312  }
2313  static clearPointerType() {
2314    CurrentPointers.#pointerType = null;
2315  }
2316  static clearPointerIds() {
2317    CurrentPointers.#pointerId = NaN;
2318    CurrentPointers.#pointerIds = null;
2319  }
2320  static clearTimeStamp() {
2321    CurrentPointers.#moveTimestamp = NaN;
2322  }
2323}
2324class IdManager {
2325  #id = 0;
2326  get id() {
2327    return `${AnnotationEditorPrefix}${this.#id++}`;
2328  }
2329}
2330class ImageManager {
2331  #baseId = getUuid();
2332  #id = 0;
2333  #cache = null;
2334  static get _isSVGFittingCanvas() {
2335    const svg = `data:image/svg+xml;charset=UTF-8,<svg viewBox="0 0 1 1" width="1" height="1" xmlns="http://www.w3.org/2000/svg"><rect width="1" height="1" style="fill:red;"/></svg>`;
2336    const canvas = new OffscreenCanvas(1, 3);
2337    const ctx = canvas.getContext("2d", {
2338      willReadFrequently: true
2339    });
2340    const image = new Image();
2341    image.src = svg;
2342    const promise = image.decode().then(() => {
2343      ctx.drawImage(image, 0, 0, 1, 1, 0, 0, 1, 3);
2344      return new Uint32Array(ctx.getImageData(0, 0, 1, 1).data.buffer)[0] === 0;
2345    });
2346    return shadow(this, "_isSVGFittingCanvas", promise);
2347  }
2348  async #get(key, rawData) {
2349    this.#cache ||= new Map();
2350    let data = this.#cache.get(key);
2351    if (data === null) {
2352      return null;
2353    }
2354    if (data?.bitmap) {
2355      data.refCounter += 1;
2356      return data;
2357    }
2358    try {
2359      data ||= {
2360        bitmap: null,
2361        id: `image_${this.#baseId}_${this.#id++}`,
2362        refCounter: 0,
2363        isSvg: false
2364      };
2365      let image;
2366      if (typeof rawData === "string") {
2367        data.url = rawData;
2368        image = await fetchData(rawData, "blob");
2369      } else if (rawData instanceof File) {
2370        image = data.file = rawData;
2371      } else if (rawData instanceof Blob) {
2372        image = rawData;
2373      }
2374      if (image.type === "image/svg+xml") {
2375        const mustRemoveAspectRatioPromise = ImageManager._isSVGFittingCanvas;
2376        const fileReader = new FileReader();
2377        const imageElement = new Image();
2378        const imagePromise = new Promise((resolve, reject) => {
2379          imageElement.onload = () => {
2380            data.bitmap = imageElement;
2381            data.isSvg = true;
2382            resolve();
2383          };
2384          fileReader.onload = async () => {
2385            const url = data.svgUrl = fileReader.result;
2386            imageElement.src = (await mustRemoveAspectRatioPromise) ? `${url}#svgView(preserveAspectRatio(none))` : url;
2387          };
2388          imageElement.onerror = fileReader.onerror = reject;
2389        });
2390        fileReader.readAsDataURL(image);
2391        await imagePromise;
2392      } else {
2393        data.bitmap = await createImageBitmap(image);
2394      }
2395      data.refCounter = 1;
2396    } catch (e) {
2397      warn(e);
2398      data = null;
2399    }
2400    this.#cache.set(key, data);
2401    if (data) {
2402      this.#cache.set(data.id, data);
2403    }
2404    return data;
2405  }
2406  async getFromFile(file) {
2407    const {
2408      lastModified,
2409      name,
2410      size,
2411      type
2412    } = file;
2413    return this.#get(`${lastModified}_${name}_${size}_${type}`, file);
2414  }
2415  async getFromUrl(url) {
2416    return this.#get(url, url);
2417  }
2418  async getFromBlob(id, blobPromise) {
2419    const blob = await blobPromise;
2420    return this.#get(id, blob);
2421  }
2422  async getFromId(id) {
2423    this.#cache ||= new Map();
2424    const data = this.#cache.get(id);
2425    if (!data) {
2426      return null;
2427    }
2428    if (data.bitmap) {
2429      data.refCounter += 1;
2430      return data;
2431    }
2432    if (data.file) {
2433      return this.getFromFile(data.file);
2434    }
2435    if (data.blobPromise) {
2436      const {
2437        blobPromise
2438      } = data;
2439      delete data.blobPromise;
2440      return this.getFromBlob(data.id, blobPromise);
2441    }
2442    return this.getFromUrl(data.url);
2443  }
2444  getFromCanvas(id, canvas) {
2445    this.#cache ||= new Map();
2446    let data = this.#cache.get(id);
2447    if (data?.bitmap) {
2448      data.refCounter += 1;
2449      return data;
2450    }
2451    const offscreen = new OffscreenCanvas(canvas.width, canvas.height);
2452    const ctx = offscreen.getContext("2d");
2453    ctx.drawImage(canvas, 0, 0);
2454    data = {
2455      bitmap: offscreen.transferToImageBitmap(),
2456      id: `image_${this.#baseId}_${this.#id++}`,
2457      refCounter: 1,
2458      isSvg: false
2459    };
2460    this.#cache.set(id, data);
2461    this.#cache.set(data.id, data);
2462    return data;
2463  }
2464  getSvgUrl(id) {
2465    const data = this.#cache.get(id);
2466    if (!data?.isSvg) {
2467      return null;
2468    }
2469    return data.svgUrl;
2470  }
2471  deleteId(id) {
2472    this.#cache ||= new Map();
2473    const data = this.#cache.get(id);
2474    if (!data) {
2475      return;
2476    }
2477    data.refCounter -= 1;
2478    if (data.refCounter !== 0) {
2479      return;
2480    }
2481    const {
2482      bitmap
2483    } = data;
2484    if (!data.url && !data.file) {
2485      const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
2486      const ctx = canvas.getContext("bitmaprenderer");
2487      ctx.transferFromImageBitmap(bitmap);
2488      data.blobPromise = canvas.convertToBlob();
2489    }
2490    bitmap.close?.();
2491    data.bitmap = null;
2492  }
2493  isValidId(id) {
2494    return id.startsWith(`image_${this.#baseId}_`);
2495  }
2496}
2497class CommandManager {
2498  #commands = [];
2499  #locked = false;
vendor: 10,298 bytes, lines 2500-2851
2500  #maxSize;
2501  #position = -1;
2502  constructor(maxSize = 128) {
2503    this.#maxSize = maxSize;
2504  }
2505  add({
2506    cmd,
2507    undo,
2508    post,
2509    mustExec,
2510    type = NaN,
2511    overwriteIfSameType = false,
2512    keepUndo = false
2513  }) {
2514    if (mustExec) {
2515      cmd();
2516    }
2517    if (this.#locked) {
2518      return;
2519    }
2520    const save = {
2521      cmd,
2522      undo,
2523      post,
2524      type
2525    };
2526    if (this.#position === -1) {
2527      if (this.#commands.length > 0) {
2528        this.#commands.length = 0;
2529      }
2530      this.#position = 0;
2531      this.#commands.push(save);
2532      return;
2533    }
2534    if (overwriteIfSameType && this.#commands[this.#position].type === type) {
2535      if (keepUndo) {
2536        save.undo = this.#commands[this.#position].undo;
2537      }
2538      this.#commands[this.#position] = save;
2539      return;
2540    }
2541    const next = this.#position + 1;
2542    if (next === this.#maxSize) {
2543      this.#commands.splice(0, 1);
2544    } else {
2545      this.#position = next;
2546      if (next < this.#commands.length) {
2547        this.#commands.splice(next);
2548      }
2549    }
2550    this.#commands.push(save);
2551  }
2552  undo() {
2553    if (this.#position === -1) {
2554      return;
2555    }
2556    this.#locked = true;
2557    const {
2558      undo,
2559      post
2560    } = this.#commands[this.#position];
2561    undo();
2562    post?.();
2563    this.#locked = false;
2564    this.#position -= 1;
2565  }
2566  redo() {
2567    if (this.#position < this.#commands.length - 1) {
2568      this.#position += 1;
2569      this.#locked = true;
2570      const {
2571        cmd,
2572        post
2573      } = this.#commands[this.#position];
2574      cmd();
2575      post?.();
2576      this.#locked = false;
2577    }
2578  }
2579  hasSomethingToUndo() {
2580    return this.#position !== -1;
2581  }
2582  hasSomethingToRedo() {
2583    return this.#position < this.#commands.length - 1;
2584  }
2585  cleanType(type) {
2586    if (this.#position === -1) {
2587      return;
2588    }
2589    for (let i = this.#position; i >= 0; i--) {
2590      if (this.#commands[i].type !== type) {
2591        this.#commands.splice(i + 1, this.#position - i);
2592        this.#position = i;
2593        return;
2594      }
2595    }
2596    this.#commands.length = 0;
2597    this.#position = -1;
2598  }
2599  destroy() {
2600    this.#commands = null;
2601  }
2602}
2603class KeyboardManager {
2604  constructor(callbacks) {
2605    this.buffer = [];
2606    this.callbacks = new Map();
2607    this.allKeys = new Set();
2608    const {
2609      isMac
2610    } = util_FeatureTest.platform;
2611    for (const [keys, callback, options = {}] of callbacks) {
2612      for (const key of keys) {
2613        const isMacKey = key.startsWith("mac+");
2614        if (isMac && isMacKey) {
2615          this.callbacks.set(key.slice(4), {
2616            callback,
2617            options
2618          });
2619          this.allKeys.add(key.split("+").at(-1));
2620        } else if (!isMac && !isMacKey) {
2621          this.callbacks.set(key, {
2622            callback,
2623            options
2624          });
2625          this.allKeys.add(key.split("+").at(-1));
2626        }
2627      }
2628    }
2629  }
2630  #serialize(event) {
2631    if (event.altKey) {
2632      this.buffer.push("alt");
2633    }
2634    if (event.ctrlKey) {
2635      this.buffer.push("ctrl");
2636    }
2637    if (event.metaKey) {
2638      this.buffer.push("meta");
2639    }
2640    if (event.shiftKey) {
2641      this.buffer.push("shift");
2642    }
2643    this.buffer.push(event.key);
2644    const str = this.buffer.join("+");
2645    this.buffer.length = 0;
2646    return str;
2647  }
2648  exec(self, event) {
2649    if (!this.allKeys.has(event.key)) {
2650      return;
2651    }
2652    const info = this.callbacks.get(this.#serialize(event));
2653    if (!info) {
2654      return;
2655    }
2656    const {
2657      callback,
2658      options: {
2659        bubbles = false,
2660        args = [],
2661        checker = null
2662      }
2663    } = info;
2664    if (checker && !checker(self, event)) {
2665      return;
2666    }
2667    callback.bind(self, ...args, event)();
2668    if (!bubbles) {
2669      stopEvent(event);
2670    }
2671  }
2672}
2673class ColorManager {
2674  static _colorsMapping = new Map([["CanvasText", [0, 0, 0]], ["Canvas", [255, 255, 255]]]);
2675  get _colors() {
2676    const colors = new Map([["CanvasText", null], ["Canvas", null]]);
2677    getColorValues(colors);
2678    return shadow(this, "_colors", colors);
2679  }
2680  convert(color) {
2681    const rgb = getRGB(color);
2682    if (!window.matchMedia("(forced-colors: active)").matches) {
2683      return rgb;
2684    }
2685    for (const [name, RGB] of this._colors) {
2686      if (RGB.every((x, i) => x === rgb[i])) {
2687        return ColorManager._colorsMapping.get(name);
2688      }
2689    }
2690    return rgb;
2691  }
2692  getHexCode(name) {
2693    const rgb = this._colors.get(name);
2694    if (!rgb) {
2695      return name;
2696    }
2697    return Util.makeHexColor(...rgb);
2698  }
2699}
2700class AnnotationEditorUIManager {
2701  #abortController = new AbortController();
2702  #activeEditor = null;
2703  #allEditableAnnotations = null;
2704  #allEditors = new Map();
2705  #allLayers = new Map();
2706  #altTextManager = null;
2707  #annotationStorage = null;
2708  #changedExistingAnnotations = null;
2709  #commandManager = new CommandManager();
2710  #commentManager = null;
2711  #copyPasteAC = null;
2712  #currentDrawingSession = null;
2713  #currentPageIndex = 0;
2714  #deletedAnnotationsElementIds = new Set();
2715  #draggingEditors = null;
2716  #editorTypes = null;
2717  #editorsToRescale = new Set();
2718  _editorUndoBar = null;
2719  #enableHighlightFloatingButton = false;
2720  #enableUpdatedAddImage = false;
2721  #enableNewAltTextWhenAddingImage = false;
2722  #filterFactory = null;
2723  #focusMainContainerTimeoutId = null;
2724  #focusManagerAC = null;
2725  #highlightColors = null;
2726  #highlightWhenShiftUp = false;
2727  #floatingToolbar = null;
2728  #idManager = new IdManager();
2729  #isEnabled = false;
2730  #isPointerDown = false;
2731  #isWaiting = false;
2732  #keyboardManagerAC = null;
2733  #lastActiveElement = null;
2734  #mainHighlightColorPicker = null;
2735  #missingCanvases = null;
2736  #mlManager = null;
2737  #mode = AnnotationEditorType.NONE;
2738  #selectedEditors = new Set();
2739  #selectedTextNode = null;
2740  #signatureManager = null;
2741  #pageColors = null;
2742  #showAllStates = null;
2743  #pdfDocument = null;
2744  #previousStates = {
2745    isEditing: false,
2746    isEmpty: true,
2747    hasSomethingToUndo: false,
2748    hasSomethingToRedo: false,
2749    hasSelectedEditor: false,
2750    hasSelectedText: false
2751  };
2752  #translation = [0, 0];
2753  #translationTimeoutId = null;
2754  #container = null;
2755  #viewer = null;
2756  #viewerAlert = null;
2757  #updateModeCapability = null;
2758  static TRANSLATE_SMALL = 1;
2759  static TRANSLATE_BIG = 10;
2760  static get _keyboardManager() {
2761    const proto = AnnotationEditorUIManager.prototype;
2762    const arrowChecker = self => self.#container.contains(document.activeElement) && document.activeElement.tagName !== "BUTTON" && self.hasSomethingToControl();
2763    const textInputChecker = (_self, {
2764      target: el
2765    }) => {
2766      if (el instanceof HTMLInputElement) {
2767        const {
2768          type
2769        } = el;
2770        return type !== "text" && type !== "number";
2771      }
2772      return true;
2773    };
2774    const small = this.TRANSLATE_SMALL;
2775    const big = this.TRANSLATE_BIG;
2776    return shadow(this, "_keyboardManager", new KeyboardManager([[["ctrl+a", "mac+meta+a"], proto.selectAll, {
2777      checker: textInputChecker
2778    }], [["ctrl+z", "mac+meta+z"], proto.undo, {
2779      checker: textInputChecker
2780    }], [["ctrl+y", "ctrl+shift+z", "mac+meta+shift+z", "ctrl+shift+Z", "mac+meta+shift+Z"], proto.redo, {
2781      checker: textInputChecker
2782    }], [["Backspace", "alt+Backspace", "ctrl+Backspace", "shift+Backspace", "mac+Backspace", "mac+alt+Backspace", "mac+ctrl+Backspace", "Delete", "ctrl+Delete", "shift+Delete", "mac+Delete"], proto.delete, {
2783      checker: textInputChecker
2784    }], [["Enter", "mac+Enter"], proto.addNewEditorFromKeyboard, {
2785      checker: (self, {
2786        target: el
2787      }) => !(el instanceof HTMLButtonElement) && self.#container.contains(el) && !self.isEnterHandled
2788    }], [[" ", "mac+ "], proto.addNewEditorFromKeyboard, {
2789      checker: (self, {
2790        target: el
2791      }) => !(el instanceof HTMLButtonElement) && self.#container.contains(document.activeElement)
2792    }], [["Escape", "mac+Escape"], proto.unselectAll], [["ArrowLeft", "mac+ArrowLeft"], proto.translateSelectedEditors, {
2793      args: [-small, 0],
2794      checker: arrowChecker
2795    }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], proto.translateSelectedEditors, {
2796      args: [-big, 0],
2797      checker: arrowChecker
2798    }], [["ArrowRight", "mac+ArrowRight"], proto.translateSelectedEditors, {
2799      args: [small, 0],
2800      checker: arrowChecker
2801    }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], proto.translateSelectedEditors, {
2802      args: [big, 0],
2803      checker: arrowChecker
2804    }], [["ArrowUp", "mac+ArrowUp"], proto.translateSelectedEditors, {
2805      args: [0, -small],
2806      checker: arrowChecker
2807    }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], proto.translateSelectedEditors, {
2808      args: [0, -big],
2809      checker: arrowChecker
2810    }], [["ArrowDown", "mac+ArrowDown"], proto.translateSelectedEditors, {
2811      args: [0, small],
2812      checker: arrowChecker
2813    }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], proto.translateSelectedEditors, {
2814      args: [0, big],
2815      checker: arrowChecker
2816    }]]));
2817  }
2818  constructor(container, viewer, viewerAlert, altTextManager, commentManager, signatureManager, eventBus, pdfDocument, pageColors, highlightColors, enableHighlightFloatingButton, enableUpdatedAddImage, enableNewAltTextWhenAddingImage, mlManager, editorUndoBar, supportsPinchToZoom) {
2819    const signal = this._signal = this.#abortController.signal;
2820    this.#container = container;
2821    this.#viewer = viewer;
2822    this.#viewerAlert = viewerAlert;
2823    this.#altTextManager = altTextManager;
2824    this.#commentManager = commentManager;
2825    this.#signatureManager = signatureManager;
2826    this.#pdfDocument = pdfDocument;
2827    this._eventBus = eventBus;
2828    eventBus._on("editingaction", this.onEditingAction.bind(this), {
2829      signal
2830    });
2831    eventBus._on("pagechanging", this.onPageChanging.bind(this), {
2832      signal
2833    });
2834    eventBus._on("scalechanging", this.onScaleChanging.bind(this), {
2835      signal
2836    });
2837    eventBus._on("rotationchanging", this.onRotationChanging.bind(this), {
2838      signal
2839    });
2840    eventBus._on("setpreference", this.onSetPreference.bind(this), {
2841      signal
2842    });
2843    eventBus._on("switchannotationeditorparams", evt => this.updateParams(evt.type, evt.value), {
2844      signal
2845    });
2846    eventBus._on("pagesedited", this.onPagesEdited.bind(this), {
2847      signal
2848    });
2849    window.addEventListener("pointerdown", () => {
2850      this.#isPointerDown = true;
2851    }, {
vendor: 10,609 bytes, lines 2852-3219
2852      capture: true,
2853      signal
2854    });
2855    window.addEventListener("pointerup", () => {
2856      this.#isPointerDown = false;
2857    }, {
2858      capture: true,
2859      signal
2860    });
2861    this.#addSelectionListener();
2862    this.#addDragAndDropListeners();
2863    this.#addKeyboardManager();
2864    this.#annotationStorage = pdfDocument.annotationStorage;
2865    this.#filterFactory = pdfDocument.filterFactory;
2866    this.#pageColors = pageColors;
2867    this.#highlightColors = highlightColors || null;
2868    this.#enableHighlightFloatingButton = enableHighlightFloatingButton;
2869    this.#enableUpdatedAddImage = enableUpdatedAddImage;
2870    this.#enableNewAltTextWhenAddingImage = enableNewAltTextWhenAddingImage;
2871    this.#mlManager = mlManager || null;
2872    this.viewParameters = {
2873      realScale: PixelsPerInch.PDF_TO_CSS_UNITS,
2874      rotation: 0
2875    };
2876    this.isShiftKeyDown = false;
2877    this._editorUndoBar = editorUndoBar || null;
2878    this._supportsPinchToZoom = supportsPinchToZoom !== false;
2879    commentManager?.setSidebarUiManager(this);
2880  }
2881  destroy() {
2882    this.#updateModeCapability?.resolve();
2883    this.#updateModeCapability = null;
2884    this.#abortController?.abort();
2885    this.#abortController = null;
2886    this._signal = null;
2887    for (const layer of this.#allLayers.values()) {
2888      layer.destroy();
2889    }
2890    this.#allLayers.clear();
2891    this.#allEditors.clear();
2892    this.#editorsToRescale.clear();
2893    this.#missingCanvases?.clear();
2894    this.#activeEditor = null;
2895    this.#selectedEditors.clear();
2896    this.#commandManager.destroy();
2897    this.#altTextManager?.destroy();
2898    this.#commentManager?.destroy();
2899    this.#signatureManager?.destroy();
2900    this.#floatingToolbar?.hide();
2901    this.#floatingToolbar = null;
2902    this.#mainHighlightColorPicker?.destroy();
2903    this.#mainHighlightColorPicker = null;
2904    this.#allEditableAnnotations = null;
2905    if (this.#focusMainContainerTimeoutId) {
2906      clearTimeout(this.#focusMainContainerTimeoutId);
2907      this.#focusMainContainerTimeoutId = null;
2908    }
2909    if (this.#translationTimeoutId) {
2910      clearTimeout(this.#translationTimeoutId);
2911      this.#translationTimeoutId = null;
2912    }
2913    this._editorUndoBar?.destroy();
2914    this.#pdfDocument = null;
2915  }
2916  combinedSignal(ac) {
2917    return AbortSignal.any([this._signal, ac.signal]);
2918  }
2919  get mlManager() {
2920    return this.#mlManager;
2921  }
2922  get useNewAltTextFlow() {
2923    return this.#enableUpdatedAddImage;
2924  }
2925  get useNewAltTextWhenAddingImage() {
2926    return this.#enableNewAltTextWhenAddingImage;
2927  }
2928  get hcmFilter() {
2929    return shadow(this, "hcmFilter", this.#pageColors ? this.#filterFactory.addHCMFilter(this.#pageColors.foreground, this.#pageColors.background) : "none");
2930  }
2931  get direction() {
2932    return shadow(this, "direction", getComputedStyle(this.#container).direction);
2933  }
2934  get _highlightColors() {
2935    return shadow(this, "_highlightColors", this.#highlightColors ? new Map(this.#highlightColors.split(",").map(pair => {
2936      pair = pair.split("=").map(x => x.trim());
2937      pair[1] = pair[1].toUpperCase();
2938      return pair;
2939    })) : null);
2940  }
2941  get highlightColors() {
2942    const {
2943      _highlightColors
2944    } = this;
2945    if (!_highlightColors) {
2946      return shadow(this, "highlightColors", null);
2947    }
2948    const map = new Map();
2949    const hasHCM = !!this.#pageColors;
2950    for (const [name, color] of _highlightColors) {
2951      const isNameForHCM = name.endsWith("_HCM");
2952      if (hasHCM && isNameForHCM) {
2953        map.set(name.replace("_HCM", ""), color);
2954        continue;
2955      }
2956      if (!hasHCM && !isNameForHCM) {
2957        map.set(name, color);
2958      }
2959    }
2960    return shadow(this, "highlightColors", map);
2961  }
2962  get highlightColorNames() {
2963    return shadow(this, "highlightColorNames", this.highlightColors ? new Map(Array.from(this.highlightColors, e => e.reverse())) : null);
2964  }
2965  getNonHCMColor(color) {
2966    if (!this._highlightColors) {
2967      return color;
2968    }
2969    const colorName = this.highlightColorNames.get(color);
2970    return this._highlightColors.get(colorName) || color;
2971  }
2972  getNonHCMColorName(color) {
2973    return this.highlightColorNames.get(color) || color;
2974  }
2975  setCurrentDrawingSession(layer) {
2976    if (layer) {
2977      this.unselectAll();
2978      this.disableUserSelect(true);
2979    } else {
2980      this.disableUserSelect(false);
2981    }
2982    this.#currentDrawingSession = layer;
2983  }
2984  setMainHighlightColorPicker(colorPicker) {
2985    this.#mainHighlightColorPicker = colorPicker;
2986  }
2987  editAltText(editor, firstTime = false) {
2988    this.#altTextManager?.editAltText(this, editor, firstTime);
2989  }
2990  hasCommentManager() {
2991    return !!this.#commentManager;
2992  }
2993  editComment(editor, posX, posY, options) {
2994    this.#commentManager?.showDialog(this, editor, posX, posY, options);
2995  }
2996  selectComment(pageIndex, uid) {
2997    const layer = this.#allLayers.get(pageIndex);
2998    const editor = layer?.getEditorByUID(uid);
2999    editor?.toggleComment(true, true);
3000  }
3001  updateComment(editor) {
3002    this.#commentManager?.updateComment(editor.getData());
3003  }
3004  updatePopupColor(editor) {
3005    this.#commentManager?.updatePopupColor(editor);
3006  }
3007  removeComment(editor) {
3008    this.#commentManager?.removeComments([editor.uid]);
3009  }
3010  deleteComment(editor, savedData) {
3011    const undo = () => {
3012      editor.comment = savedData;
3013    };
3014    const cmd = () => {
3015      this._editorUndoBar?.show(undo, "comment");
3016      this.toggleComment(null);
3017      editor.comment = null;
3018    };
3019    this.addCommands({
3020      cmd,
3021      undo,
3022      mustExec: true
3023    });
3024  }
3025  toggleComment(editor, isSelected, visibility = undefined) {
3026    this.#commentManager?.toggleCommentPopup(editor, isSelected, visibility);
3027  }
3028  makeCommentColor(color, opacity) {
3029    return color && this.#commentManager?.makeCommentColor(color, opacity) || null;
3030  }
3031  getCommentDialogElement() {
3032    return this.#commentManager?.dialogElement || null;
3033  }
3034  async waitForEditorsRendered(pageNumber) {
3035    if (this.#allLayers.has(pageNumber - 1)) {
3036      return;
3037    }
3038    const {
3039      resolve,
3040      promise
3041    } = Promise.withResolvers();
3042    const onEditorsRendered = evt => {
3043      if (evt.pageNumber === pageNumber) {
3044        this._eventBus._off("editorsrendered", onEditorsRendered);
3045        resolve();
3046      }
3047    };
3048    this._eventBus.on("editorsrendered", onEditorsRendered);
3049    await promise;
3050  }
3051  getSignature(editor) {
3052    this.#signatureManager?.getSignature({
3053      uiManager: this,
3054      editor
3055    });
3056  }
3057  get signatureManager() {
3058    return this.#signatureManager;
3059  }
3060  switchToMode(mode, callback) {
3061    this._eventBus.on("annotationeditormodechanged", callback, {
3062      once: true,
3063      signal: this._signal
3064    });
3065    this._eventBus.dispatch("showannotationeditorui", {
3066      source: this,
3067      mode
3068    });
3069  }
3070  setPreference(name, value) {
3071    this._eventBus.dispatch("setpreference", {
3072      source: this,
3073      name,
3074      value
3075    });
3076  }
3077  onSetPreference({
3078    name,
3079    value
3080  }) {
3081    switch (name) {
3082      case "enableNewAltTextWhenAddingImage":
3083        this.#enableNewAltTextWhenAddingImage = value;
3084        break;
3085    }
3086  }
3087  onPagesEdited({
3088    pagesMapper
3089  }) {
3090    for (const editor of this.#allEditors.values()) {
3091      editor.updatePageIndex(pagesMapper.getPrevPageNumber(editor.pageIndex + 1) - 1);
3092    }
3093    const allLayers = this.#allLayers;
3094    const newAllLayers = this.#allLayers = new Map();
3095    for (const [pageIndex, layer] of allLayers) {
3096      const prevPageIndex = pagesMapper.getPrevPageNumber(pageIndex + 1) - 1;
3097      if (prevPageIndex === -1) {
3098        layer.destroy();
3099        continue;
3100      }
3101      newAllLayers.set(prevPageIndex, layer);
3102      layer.updatePageIndex(prevPageIndex);
3103    }
3104  }
3105  onPageChanging({
3106    pageNumber
3107  }) {
3108    this.#currentPageIndex = pageNumber - 1;
3109  }
3110  focusMainContainer() {
3111    this.#container.focus();
3112  }
3113  findParent(x, y) {
3114    for (const layer of this.#allLayers.values()) {
3115      const {
3116        x: layerX,
3117        y: layerY,
3118        width,
3119        height
3120      } = layer.div.getBoundingClientRect();
3121      if (x >= layerX && x <= layerX + width && y >= layerY && y <= layerY + height) {
3122        return layer;
3123      }
3124    }
3125    return null;
3126  }
3127  disableUserSelect(value = false) {
3128    this.#viewer.classList.toggle("noUserSelect", value);
3129  }
3130  addShouldRescale(editor) {
3131    this.#editorsToRescale.add(editor);
3132  }
3133  removeShouldRescale(editor) {
3134    this.#editorsToRescale.delete(editor);
3135  }
3136  onScaleChanging({
3137    scale
3138  }) {
3139    this.commitOrRemove();
3140    this.viewParameters.realScale = scale * PixelsPerInch.PDF_TO_CSS_UNITS;
3141    for (const editor of this.#editorsToRescale) {
3142      editor.onScaleChanging();
3143    }
3144    this.#currentDrawingSession?.onScaleChanging();
3145  }
3146  onRotationChanging({
3147    pagesRotation
3148  }) {
3149    this.commitOrRemove();
3150    this.viewParameters.rotation = pagesRotation;
3151  }
3152  #getAnchorElementForSelection({
3153    anchorNode
3154  }) {
3155    return anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode;
3156  }
3157  #getLayerForTextLayer(textLayer) {
3158    const {
3159      currentLayer
3160    } = this;
3161    if (currentLayer.hasTextLayer(textLayer)) {
3162      return currentLayer;
3163    }
3164    for (const layer of this.#allLayers.values()) {
3165      if (layer.hasTextLayer(textLayer)) {
3166        return layer;
3167      }
3168    }
3169    return null;
3170  }
3171  highlightSelection(methodOfCreation = "", comment = false) {
3172    const selection = document.getSelection();
3173    if (!selection || selection.isCollapsed) {
3174      return;
3175    }
3176    const {
3177      anchorNode,
3178      anchorOffset,
3179      focusNode,
3180      focusOffset
3181    } = selection;
3182    const text = selection.toString();
3183    const anchorElement = this.#getAnchorElementForSelection(selection);
3184    const textLayer = anchorElement.closest(".textLayer");
3185    const boxes = this.getSelectionBoxes(textLayer);
3186    if (!boxes) {
3187      return;
3188    }
3189    selection.empty();
3190    const layer = this.#getLayerForTextLayer(textLayer);
3191    const isNoneMode = this.#mode === AnnotationEditorType.NONE;
3192    const callback = () => {
3193      const editor = layer?.createAndAddNewEditor({
3194        x: 0,
3195        y: 0
3196      }, false, {
3197        methodOfCreation,
3198        boxes,
3199        anchorNode,
3200        anchorOffset,
3201        focusNode,
3202        focusOffset,
3203        text
3204      });
3205      if (isNoneMode) {
3206        this.showAllEditors("highlight", true, true);
3207      }
3208      if (comment) {
3209        editor?.editComment();
3210      }
3211    };
3212    if (isNoneMode) {
3213      this.switchToMode(AnnotationEditorType.HIGHLIGHT, callback);
3214      return;
3215    }
3216    callback();
3217  }
3218  commentSelection(methodOfCreation = "") {
3219    this.highlightSelection(methodOfCreation, tru
vendor: 10,203 bytes, lines 3219-3588
3219e);
3220  }
3221  #displayFloatingToolbar() {
3222    const selection = document.getSelection();
3223    if (!selection || selection.isCollapsed) {
3224      return;
3225    }
3226    const anchorElement = this.#getAnchorElementForSelection(selection);
3227    const textLayer = anchorElement.closest(".textLayer");
3228    const boxes = this.getSelectionBoxes(textLayer);
3229    if (!boxes) {
3230      return;
3231    }
3232    this.#floatingToolbar ||= new FloatingToolbar(this);
3233    this.#floatingToolbar.show(textLayer, boxes, this.direction === "ltr");
3234  }
3235  getAndRemoveDataFromAnnotationStorage(annotationId) {
3236    if (!this.#annotationStorage) {
3237      return null;
3238    }
3239    const key = `${AnnotationEditorPrefix}${annotationId}`;
3240    const storedValue = this.#annotationStorage.getRawValue(key);
3241    if (storedValue) {
3242      this.#annotationStorage.remove(key);
3243    }
3244    return storedValue;
3245  }
3246  addToAnnotationStorage(editor) {
3247    if (!editor.isEmpty() && this.#annotationStorage && !this.#annotationStorage.has(editor.id)) {
3248      this.#annotationStorage.setValue(editor.id, editor);
3249    }
3250  }
3251  a11yAlert(messageId, args = null) {
3252    const viewerAlert = this.#viewerAlert;
3253    if (!viewerAlert) {
3254      return;
3255    }
3256    viewerAlert.setAttribute("data-l10n-id", messageId);
3257    if (args) {
3258      viewerAlert.setAttribute("data-l10n-args", JSON.stringify(args));
3259    } else {
3260      viewerAlert.removeAttribute("data-l10n-args");
3261    }
3262  }
3263  #selectionChange() {
3264    const selection = document.getSelection();
3265    if (!selection || selection.isCollapsed) {
3266      if (this.#selectedTextNode) {
3267        this.#floatingToolbar?.hide();
3268        this.#selectedTextNode = null;
3269        this.#dispatchUpdateStates({
3270          hasSelectedText: false
3271        });
3272      }
3273      return;
3274    }
3275    const {
3276      anchorNode
3277    } = selection;
3278    if (anchorNode === this.#selectedTextNode) {
3279      return;
3280    }
3281    const anchorElement = this.#getAnchorElementForSelection(selection);
3282    const textLayer = anchorElement.closest(".textLayer");
3283    if (!textLayer) {
3284      if (this.#selectedTextNode) {
3285        this.#floatingToolbar?.hide();
3286        this.#selectedTextNode = null;
3287        this.#dispatchUpdateStates({
3288          hasSelectedText: false
3289        });
3290      }
3291      return;
3292    }
3293    this.#floatingToolbar?.hide();
3294    this.#selectedTextNode = anchorNode;
3295    this.#dispatchUpdateStates({
3296      hasSelectedText: true
3297    });
3298    if (this.#mode !== AnnotationEditorType.HIGHLIGHT && this.#mode !== AnnotationEditorType.NONE) {
3299      return;
3300    }
3301    if (this.#mode === AnnotationEditorType.HIGHLIGHT) {
3302      this.showAllEditors("highlight", true, true);
3303    }
3304    this.#highlightWhenShiftUp = this.isShiftKeyDown;
3305    if (!this.isShiftKeyDown) {
3306      const activeLayer = this.#mode === AnnotationEditorType.HIGHLIGHT ? this.#getLayerForTextLayer(textLayer) : null;
3307      activeLayer?.toggleDrawing();
3308      if (this.#isPointerDown) {
3309        const ac = new AbortController();
3310        const signal = this.combinedSignal(ac);
3311        const pointerup = e => {
3312          if (e.type === "pointerup" && e.button !== 0) {
3313            return;
3314          }
3315          ac.abort();
3316          activeLayer?.toggleDrawing(true);
3317          if (e.type === "pointerup") {
3318            this.#onSelectEnd("main_toolbar");
3319          }
3320        };
3321        window.addEventListener("pointerup", pointerup, {
3322          signal
3323        });
3324        window.addEventListener("blur", pointerup, {
3325          signal
3326        });
3327      } else {
3328        activeLayer?.toggleDrawing(true);
3329        this.#onSelectEnd("main_toolbar");
3330      }
3331    }
3332  }
3333  #onSelectEnd(methodOfCreation = "") {
3334    if (this.#mode === AnnotationEditorType.HIGHLIGHT) {
3335      this.highlightSelection(methodOfCreation);
3336    } else if (this.#enableHighlightFloatingButton) {
3337      this.#displayFloatingToolbar();
3338    }
3339  }
3340  #addSelectionListener() {
3341    document.addEventListener("selectionchange", this.#selectionChange.bind(this), {
3342      signal: this._signal
3343    });
3344  }
3345  #addFocusManager() {
3346    if (this.#focusManagerAC) {
3347      return;
3348    }
3349    this.#focusManagerAC = new AbortController();
3350    const signal = this.combinedSignal(this.#focusManagerAC);
3351    window.addEventListener("focus", this.focus.bind(this), {
3352      signal
3353    });
3354    window.addEventListener("blur", this.blur.bind(this), {
3355      signal
3356    });
3357  }
3358  #removeFocusManager() {
3359    this.#focusManagerAC?.abort();
3360    this.#focusManagerAC = null;
3361  }
3362  blur() {
3363    this.isShiftKeyDown = false;
3364    if (this.#highlightWhenShiftUp) {
3365      this.#highlightWhenShiftUp = false;
3366      this.#onSelectEnd("main_toolbar");
3367    }
3368    if (!this.hasSelection) {
3369      return;
3370    }
3371    const {
3372      activeElement
3373    } = document;
3374    for (const editor of this.#selectedEditors) {
3375      if (editor.div.contains(activeElement)) {
3376        this.#lastActiveElement = [editor, activeElement];
3377        editor._focusEventsAllowed = false;
3378        break;
3379      }
3380    }
3381  }
3382  focus() {
3383    if (!this.#lastActiveElement) {
3384      return;
3385    }
3386    const [lastEditor, lastActiveElement] = this.#lastActiveElement;
3387    this.#lastActiveElement = null;
3388    lastActiveElement.addEventListener("focusin", () => {
3389      lastEditor._focusEventsAllowed = true;
3390    }, {
3391      once: true,
3392      signal: this._signal
3393    });
3394    lastActiveElement.focus();
3395  }
3396  #addKeyboardManager() {
3397    if (this.#keyboardManagerAC) {
3398      return;
3399    }
3400    this.#keyboardManagerAC = new AbortController();
3401    const signal = this.combinedSignal(this.#keyboardManagerAC);
3402    window.addEventListener("keydown", this.keydown.bind(this), {
3403      signal
3404    });
3405    window.addEventListener("keyup", this.keyup.bind(this), {
3406      signal
3407    });
3408  }
3409  #removeKeyboardManager() {
3410    this.#keyboardManagerAC?.abort();
3411    this.#keyboardManagerAC = null;
3412  }
3413  #addCopyPasteListeners() {
3414    if (this.#copyPasteAC) {
3415      return;
3416    }
3417    this.#copyPasteAC = new AbortController();
3418    const signal = this.combinedSignal(this.#copyPasteAC);
3419    document.addEventListener("copy", this.copy.bind(this), {
3420      signal
3421    });
3422    document.addEventListener("cut", this.cut.bind(this), {
3423      signal
3424    });
3425    document.addEventListener("paste", this.paste.bind(this), {
3426      signal
3427    });
3428  }
3429  #removeCopyPasteListeners() {
3430    this.#copyPasteAC?.abort();
3431    this.#copyPasteAC = null;
3432  }
3433  #addDragAndDropListeners() {
3434    const signal = this._signal;
3435    document.addEventListener("dragover", this.dragOver.bind(this), {
3436      signal
3437    });
3438    document.addEventListener("drop", this.drop.bind(this), {
3439      signal
3440    });
3441  }
3442  addEditListeners() {
3443    this.#addKeyboardManager();
3444    this.setEditingState(true);
3445  }
3446  removeEditListeners() {
3447    this.#removeKeyboardManager();
3448    this.setEditingState(false);
3449  }
3450  dragOver(event) {
3451    for (const {
3452      type
3453    } of event.dataTransfer.items) {
3454      for (const editorType of this.#editorTypes) {
3455        if (editorType.isHandlingMimeForPasting(type)) {
3456          event.dataTransfer.dropEffect = "copy";
3457          event.preventDefault();
3458          return;
3459        }
3460      }
3461    }
3462  }
3463  drop(event) {
3464    for (const item of event.dataTransfer.items) {
3465      for (const editorType of this.#editorTypes) {
3466        if (editorType.isHandlingMimeForPasting(item.type)) {
3467          editorType.paste(item, this.currentLayer);
3468          event.preventDefault();
3469          return;
3470        }
3471      }
3472    }
3473  }
3474  copy(event) {
3475    event.preventDefault();
3476    this.#activeEditor?.commitOrRemove();
3477    if (!this.hasSelection) {
3478      return;
3479    }
3480    const editors = [];
3481    for (const editor of this.#selectedEditors) {
3482      const serialized = editor.serialize(true);
3483      if (serialized) {
3484        editors.push(serialized);
3485      }
3486    }
3487    if (editors.length === 0) {
3488      return;
3489    }
3490    event.clipboardData.setData("application/pdfjs", JSON.stringify(editors));
3491  }
3492  cut(event) {
3493    this.copy(event);
3494    this.delete();
3495  }
3496  async paste(event) {
3497    event.preventDefault();
3498    const {
3499      clipboardData
3500    } = event;
3501    for (const item of clipboardData.items) {
3502      for (const editorType of this.#editorTypes) {
3503        if (editorType.isHandlingMimeForPasting(item.type)) {
3504          editorType.paste(item, this.currentLayer);
3505          return;
3506        }
3507      }
3508    }
3509    let data = clipboardData.getData("application/pdfjs");
3510    if (!data) {
3511      return;
3512    }
3513    try {
3514      data = JSON.parse(data);
3515    } catch (ex) {
3516      warn(`paste: "${ex.message}".`);
3517      return;
3518    }
3519    if (!Array.isArray(data)) {
3520      return;
3521    }
3522    this.unselectAll();
3523    const layer = this.currentLayer;
3524    try {
3525      const newEditors = [];
3526      for (const editor of data) {
3527        const deserializedEditor = await layer.deserialize(editor);
3528        if (!deserializedEditor) {
3529          return;
3530        }
3531        newEditors.push(deserializedEditor);
3532      }
3533      const cmd = () => {
3534        for (const editor of newEditors) {
3535          this.#addEditorToLayer(editor);
3536        }
3537        this.#selectEditors(newEditors);
3538      };
3539      const undo = () => {
3540        for (const editor of newEditors) {
3541          editor.remove();
3542        }
3543      };
3544      this.addCommands({
3545        cmd,
3546        undo,
3547        mustExec: true
3548      });
3549    } catch (ex) {
3550      warn(`paste: "${ex.message}".`);
3551    }
3552  }
3553  keydown(event) {
3554    if (!this.isShiftKeyDown && event.key === "Shift") {
3555      this.isShiftKeyDown = true;
3556    }
3557    if (this.#mode !== AnnotationEditorType.NONE && !this.isEditorHandlingKeyboard) {
3558      AnnotationEditorUIManager._keyboardManager.exec(this, event);
3559    }
3560  }
3561  keyup(event) {
3562    if (this.isShiftKeyDown && event.key === "Shift") {
3563      this.isShiftKeyDown = false;
3564      if (this.#highlightWhenShiftUp) {
3565        this.#highlightWhenShiftUp = false;
3566        this.#onSelectEnd("main_toolbar");
3567      }
3568    }
3569  }
3570  onEditingAction({
3571    name
3572  }) {
3573    switch (name) {
3574      case "undo":
3575      case "redo":
3576      case "delete":
3577      case "selectAll":
3578        this[name]();
3579        break;
3580      case "highlightSelection":
3581        this.highlightSelection("context_menu");
3582        break;
3583      case "commentSelection":
3584        this.commentSelection("context_menu");
3585        break;
3586    }
3587  }
3588  
vendor: 7,533 bytes, lines 3588-3841
3588#dispatchUpdateStates(details) {
3589    const hasChanged = Object.entries(details).some(([key, value]) => this.#previousStates[key] !== value);
3590    if (hasChanged) {
3591      this._eventBus.dispatch("annotationeditorstateschanged", {
3592        source: this,
3593        details: Object.assign(this.#previousStates, details)
3594      });
3595      if (this.#mode === AnnotationEditorType.HIGHLIGHT && details.hasSelectedEditor === false) {
3596        this.#dispatchUpdateUI([[AnnotationEditorParamsType.HIGHLIGHT_FREE, true]]);
3597      }
3598    }
3599  }
3600  #dispatchUpdateUI(details) {
3601    this._eventBus.dispatch("annotationeditorparamschanged", {
3602      source: this,
3603      details
3604    });
3605  }
3606  setEditingState(isEditing) {
3607    if (isEditing) {
3608      this.#addFocusManager();
3609      this.#addCopyPasteListeners();
3610      this.#dispatchUpdateStates({
3611        isEditing: this.#mode !== AnnotationEditorType.NONE,
3612        isEmpty: this.#isEmpty(),
3613        hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(),
3614        hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(),
3615        hasSelectedEditor: false
3616      });
3617    } else {
3618      this.#removeFocusManager();
3619      this.#removeCopyPasteListeners();
3620      this.#dispatchUpdateStates({
3621        isEditing: false
3622      });
3623      this.disableUserSelect(false);
3624    }
3625  }
3626  registerEditorTypes(types) {
3627    if (this.#editorTypes) {
3628      return;
3629    }
3630    this.#editorTypes = types;
3631    for (const editorType of this.#editorTypes) {
3632      this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate);
3633    }
3634  }
3635  getId() {
3636    return this.#idManager.id;
3637  }
3638  get currentLayer() {
3639    return this.#allLayers.get(this.#currentPageIndex);
3640  }
3641  getLayer(pageIndex) {
3642    return this.#allLayers.get(pageIndex);
3643  }
3644  get currentPageIndex() {
3645    return this.#currentPageIndex;
3646  }
3647  addLayer(layer) {
3648    this.#allLayers.set(layer.pageIndex, layer);
3649    if (this.#isEnabled) {
3650      layer.enable();
3651    } else {
3652      layer.disable();
3653    }
3654  }
3655  removeLayer(layer) {
3656    this.#allLayers.delete(layer.pageIndex);
3657  }
3658  async updateMode(mode, editId = null, isFromUser = false, isFromKeyboard = false, mustEnterInEditMode = false, editComment = false) {
3659    if (this.#mode === mode) {
3660      return;
3661    }
3662    if (this.#updateModeCapability) {
3663      await this.#updateModeCapability.promise;
3664      if (!this.#updateModeCapability) {
3665        return;
3666      }
3667    }
3668    this.#updateModeCapability = Promise.withResolvers();
3669    this.#currentDrawingSession?.commitOrRemove();
3670    if (this.#mode === AnnotationEditorType.POPUP) {
3671      this.#commentManager?.hideSidebar();
3672    }
3673    this.#commentManager?.destroyPopup();
3674    this.#mode = mode;
3675    if (mode === AnnotationEditorType.NONE) {
3676      this.setEditingState(false);
3677      this.#disableAll();
3678      for (const editor of this.#allEditors.values()) {
3679        editor.hideStandaloneCommentButton();
3680      }
3681      this._editorUndoBar?.hide();
3682      this.toggleComment(null);
3683      this.#updateModeCapability.resolve();
3684      return;
3685    }
3686    for (const editor of this.#allEditors.values()) {
3687      editor.addStandaloneCommentButton();
3688    }
3689    if (mode === AnnotationEditorType.SIGNATURE) {
3690      await this.#signatureManager?.loadSignatures();
3691    }
3692    if (isFromUser) {
3693      CurrentPointers.clearPointerType();
3694    }
3695    this.setEditingState(true);
3696    await this.#enableAll();
3697    this.unselectAll();
3698    for (const layer of this.#allLayers.values()) {
3699      layer.updateMode(mode);
3700    }
3701    if (mode === AnnotationEditorType.POPUP) {
3702      this.#allEditableAnnotations ||= await this.#pdfDocument.getAnnotationsByType(new Set(this.#editorTypes.map(editorClass => editorClass._editorType)));
3703      const elementIds = new Set();
3704      const allComments = [];
3705      for (const editor of this.#allEditors.values()) {
3706        const {
3707          annotationElementId,
3708          hasComment,
3709          deleted
3710        } = editor;
3711        if (annotationElementId) {
3712          elementIds.add(annotationElementId);
3713        }
3714        if (hasComment && !deleted) {
3715          allComments.push(editor.getData());
3716        }
3717      }
3718      for (const annotation of this.#allEditableAnnotations) {
3719        const {
3720          id,
3721          popupRef,
3722          contentsObj
3723        } = annotation;
3724        if (popupRef && contentsObj?.str && !elementIds.has(id) && !this.#deletedAnnotationsElementIds.has(id)) {
3725          allComments.push(annotation);
3726        }
3727      }
3728      this.#commentManager?.showSidebar(allComments);
3729    }
3730    if (!editId) {
3731      if (isFromKeyboard) {
3732        this.addNewEditorFromKeyboard();
3733      }
3734      this.#updateModeCapability.resolve();
3735      return;
3736    }
3737    for (const editor of this.#allEditors.values()) {
3738      if (editor.uid === editId) {
3739        this.setSelected(editor);
3740        if (editComment) {
3741          editor.editComment();
3742        } else if (mustEnterInEditMode) {
3743          editor.enterInEditMode();
3744        } else {
3745          editor.focus();
3746        }
3747      } else {
3748        editor.unselect();
3749      }
3750    }
3751    this.#updateModeCapability.resolve();
3752  }
3753  addNewEditorFromKeyboard() {
3754    if (this.currentLayer.canCreateNewEmptyEditor()) {
3755      this.currentLayer.addNewEditor();
3756    }
3757  }
3758  updateToolbar(options) {
3759    if (options.mode === this.#mode) {
3760      return;
3761    }
3762    this._eventBus.dispatch("switchannotationeditormode", {
3763      source: this,
3764      ...options
3765    });
3766  }
3767  updateParams(type, value) {
3768    if (!this.#editorTypes) {
3769      return;
3770    }
3771    switch (type) {
3772      case AnnotationEditorParamsType.CREATE:
3773        this.currentLayer.addNewEditor(value);
3774        return;
3775      case AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL:
3776        this._eventBus.dispatch("reporttelemetry", {
3777          source: this,
3778          details: {
3779            type: "editing",
3780            data: {
3781              type: "highlight",
3782              action: "toggle_visibility"
3783            }
3784          }
3785        });
3786        (this.#showAllStates ||= new Map()).set(type, value);
3787        this.showAllEditors("highlight", value);
3788        break;
3789    }
3790    if (this.hasSelection) {
3791      for (const editor of this.#selectedEditors) {
3792        editor.updateParams(type, value);
3793      }
3794    } else {
3795      for (const editorType of this.#editorTypes) {
3796        editorType.updateDefaultParams(type, value);
3797      }
3798    }
3799  }
3800  showAllEditors(type, visible, updateButton = false) {
3801    for (const editor of this.#allEditors.values()) {
3802      if (editor.editorType === type) {
3803        editor.show(visible);
3804      }
3805    }
3806    const state = this.#showAllStates?.get(AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL) ?? true;
3807    if (state !== visible) {
3808      this.#dispatchUpdateUI([[AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL, visible]]);
3809    }
3810  }
3811  enableWaiting(mustWait = false) {
3812    if (this.#isWaiting === mustWait) {
3813      return;
3814    }
3815    this.#isWaiting = mustWait;
3816    for (const layer of this.#allLayers.values()) {
3817      if (mustWait) {
3818        layer.disableClick();
3819      } else {
3820        layer.enableClick();
3821      }
3822      layer.div.classList.toggle("waiting", mustWait);
3823    }
3824  }
3825  async #enableAll() {
3826    if (!this.#isEnabled) {
3827      this.#isEnabled = true;
3828      const promises = [];
3829      for (const layer of this.#allLayers.values()) {
3830        promises.push(layer.enable());
3831      }
3832      await Promise.all(promises);
3833      for (const editor of this.#allEditors.values()) {
3834        editor.enable();
3835      }
3836    }
3837  }
3838  #disableAll() {
3839    this.unselectAll();
3840    if (this.#isEnabled) {
3841      this.#isEnabled = false;
vendor: 4,951 bytes, lines 3842-4017
3842      for (const layer of this.#allLayers.values()) {
3843        layer.disable();
3844      }
3845      for (const editor of this.#allEditors.values()) {
3846        editor.disable();
3847      }
3848    }
3849  }
3850  *getEditors(pageIndex) {
3851    for (const editor of this.#allEditors.values()) {
3852      if (editor.pageIndex === pageIndex) {
3853        yield editor;
3854      }
3855    }
3856  }
3857  getEditor(id) {
3858    return this.#allEditors.get(id);
3859  }
3860  addEditor(editor) {
3861    this.#allEditors.set(editor.id, editor);
3862  }
3863  removeEditor(editor) {
3864    if (editor.div.contains(document.activeElement)) {
3865      if (this.#focusMainContainerTimeoutId) {
3866        clearTimeout(this.#focusMainContainerTimeoutId);
3867      }
3868      this.#focusMainContainerTimeoutId = setTimeout(() => {
3869        this.focusMainContainer();
3870        this.#focusMainContainerTimeoutId = null;
3871      }, 0);
3872    }
3873    this.#allEditors.delete(editor.id);
3874    if (editor.annotationElementId) {
3875      this.#missingCanvases?.delete(editor.annotationElementId);
3876    }
3877    this.unselect(editor);
3878    if (!editor.annotationElementId || !this.#deletedAnnotationsElementIds.has(editor.annotationElementId)) {
3879      this.#annotationStorage?.remove(editor.id);
3880    }
3881  }
3882  addDeletedAnnotationElement(editor) {
3883    this.#deletedAnnotationsElementIds.add(editor.annotationElementId);
3884    this.addChangedExistingAnnotation(editor);
3885    editor.deleted = true;
3886  }
3887  isDeletedAnnotationElement(annotationElementId) {
3888    return this.#deletedAnnotationsElementIds.has(annotationElementId);
3889  }
3890  removeDeletedAnnotationElement(editor) {
3891    this.#deletedAnnotationsElementIds.delete(editor.annotationElementId);
3892    this.removeChangedExistingAnnotation(editor);
3893    editor.deleted = false;
3894  }
3895  #addEditorToLayer(editor) {
3896    const layer = this.#allLayers.get(editor.pageIndex);
3897    if (layer) {
3898      layer.addOrRebuild(editor);
3899    } else {
3900      this.addEditor(editor);
3901      this.addToAnnotationStorage(editor);
3902    }
3903  }
3904  setActiveEditor(editor) {
3905    if (this.#activeEditor === editor) {
3906      return;
3907    }
3908    this.#activeEditor = editor;
3909    if (editor) {
3910      this.#dispatchUpdateUI(editor.propertiesToUpdate);
3911    }
3912  }
3913  get #lastSelectedEditor() {
3914    let ed = null;
3915    for (ed of this.#selectedEditors) {}
3916    return ed;
3917  }
3918  updateUI(editor) {
3919    if (this.#lastSelectedEditor === editor) {
3920      this.#dispatchUpdateUI(editor.propertiesToUpdate);
3921    }
3922  }
3923  updateUIForDefaultProperties(editorType) {
3924    this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate);
3925  }
3926  toggleSelected(editor) {
3927    if (this.#selectedEditors.has(editor)) {
3928      this.#selectedEditors.delete(editor);
3929      editor.unselect();
3930      this.#dispatchUpdateStates({
3931        hasSelectedEditor: this.hasSelection
3932      });
3933      return;
3934    }
3935    this.#selectedEditors.add(editor);
3936    editor.select();
3937    this.#dispatchUpdateUI(editor.propertiesToUpdate);
3938    this.#dispatchUpdateStates({
3939      hasSelectedEditor: true
3940    });
3941  }
3942  setSelected(editor) {
3943    this.updateToolbar({
3944      mode: editor.mode,
3945      editId: editor.uid
3946    });
3947    this.#currentDrawingSession?.commitOrRemove();
3948    for (const ed of this.#selectedEditors) {
3949      if (ed !== editor) {
3950        ed.unselect();
3951      }
3952    }
3953    this.#selectedEditors.clear();
3954    this.#selectedEditors.add(editor);
3955    editor.select();
3956    this.#dispatchUpdateUI(editor.propertiesToUpdate);
3957    this.#dispatchUpdateStates({
3958      hasSelectedEditor: true
3959    });
3960  }
3961  isSelected(editor) {
3962    return this.#selectedEditors.has(editor);
3963  }
3964  get firstSelectedEditor() {
3965    return this.#selectedEditors.values().next().value;
3966  }
3967  unselect(editor) {
3968    editor.unselect();
3969    this.#selectedEditors.delete(editor);
3970    this.#dispatchUpdateStates({
3971      hasSelectedEditor: this.hasSelection
3972    });
3973  }
3974  get hasSelection() {
3975    return this.#selectedEditors.size !== 0;
3976  }
3977  get isEnterHandled() {
3978    return this.#selectedEditors.size === 1 && this.firstSelectedEditor.isEnterHandled;
3979  }
3980  undo() {
3981    this.#commandManager.undo();
3982    this.#dispatchUpdateStates({
3983      hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(),
3984      hasSomethingToRedo: true,
3985      isEmpty: this.#isEmpty()
3986    });
3987    this._editorUndoBar?.hide();
3988  }
3989  redo() {
3990    this.#commandManager.redo();
3991    this.#dispatchUpdateStates({
3992      hasSomethingToUndo: true,
3993      hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(),
3994      isEmpty: this.#isEmpty()
3995    });
3996  }
3997  addCommands(params) {
3998    this.#commandManager.add(params);
3999    this.#dispatchUpdateStates({
4000      hasSomethingToUndo: true,
4001      hasSomethingToRedo: false,
4002      isEmpty: this.#isEmpty()
4003    });
4004  }
4005  cleanUndoStack(type) {
4006    this.#commandManager.cleanType(type);
4007  }
4008  #isEmpty() {
4009    if (this.#allEditors.size === 0) {
4010      return true;
4011    }
4012    if (this.#allEditors.size === 1) {
4013      for (const editor of this.#allEditors.values()) {
4014        return editor.isEmpty();
4015      }
4016    }
4017    return false;
vendor: 1,612 bytes, lines 4018-4080
4018  }
4019  delete() {
4020    this.commitOrRemove();
4021    const drawingEditor = this.currentLayer?.endDrawingSession(true);
4022    if (!this.hasSelection && !drawingEditor) {
4023      return;
4024    }
4025    const editors = drawingEditor ? [drawingEditor] : [...this.#selectedEditors];
4026    const cmd = () => {
4027      this._editorUndoBar?.show(undo, editors.length === 1 ? editors[0].editorType : editors.length);
4028      for (const editor of editors) {
4029        editor.remove();
4030      }
4031    };
4032    const undo = () => {
4033      for (const editor of editors) {
4034        this.#addEditorToLayer(editor);
4035      }
4036    };
4037    this.addCommands({
4038      cmd,
4039      undo,
4040      mustExec: true
4041    });
4042  }
4043  commitOrRemove() {
4044    this.#activeEditor?.commitOrRemove();
4045  }
4046  hasSomethingToControl() {
4047    return this.#activeEditor || this.hasSelection;
4048  }
4049  #selectEditors(editors) {
4050    for (const editor of this.#selectedEditors) {
4051      editor.unselect();
4052    }
4053    this.#selectedEditors.clear();
4054    for (const editor of editors) {
4055      if (editor.isEmpty()) {
4056        continue;
4057      }
4058      this.#selectedEditors.add(editor);
4059      editor.select();
4060    }
4061    this.#dispatchUpdateStates({
4062      hasSelectedEditor: this.hasSelection
4063    });
4064  }
4065  selectAll() {
4066    for (const editor of this.#selectedEditors) {
4067      editor.commit();
4068    }
4069    this.#selectEditors(this.#allEditors.values());
4070  }
4071  unselectAll() {
4072    if (this.#activeEditor) {
4073      this.#activeEditor.commitOrRemove();
4074      if (this.#mode !== AnnotationEditorType.NONE) {
4075        return;
4076      }
4077    }
4078    if (this.#currentDrawingSession?.commitOrRemove()) {
4079      return;
4080    }
vendor: 10,497 bytes, lines 4080-4451
4080
4081    if (!this.hasSelection) {
4082      return;
4083    }
4084    for (const editor of this.#selectedEditors) {
4085      editor.unselect();
4086    }
4087    this.#selectedEditors.clear();
4088    this.#dispatchUpdateStates({
4089      hasSelectedEditor: false
4090    });
4091  }
4092  translateSelectedEditors(x, y, noCommit = false) {
4093    if (!noCommit) {
4094      this.commitOrRemove();
4095    }
4096    if (!this.hasSelection) {
4097      return;
4098    }
4099    this.#translation[0] += x;
4100    this.#translation[1] += y;
4101    const [totalX, totalY] = this.#translation;
4102    const editors = [...this.#selectedEditors];
4103    const TIME_TO_WAIT = 1000;
4104    if (this.#translationTimeoutId) {
4105      clearTimeout(this.#translationTimeoutId);
4106    }
4107    this.#translationTimeoutId = setTimeout(() => {
4108      this.#translationTimeoutId = null;
4109      this.#translation[0] = this.#translation[1] = 0;
4110      this.addCommands({
4111        cmd: () => {
4112          for (const editor of editors) {
4113            if (this.#allEditors.has(editor.id)) {
4114              editor.translateInPage(totalX, totalY);
4115              editor.translationDone();
4116            }
4117          }
4118        },
4119        undo: () => {
4120          for (const editor of editors) {
4121            if (this.#allEditors.has(editor.id)) {
4122              editor.translateInPage(-totalX, -totalY);
4123              editor.translationDone();
4124            }
4125          }
4126        },
4127        mustExec: false
4128      });
4129    }, TIME_TO_WAIT);
4130    for (const editor of editors) {
4131      editor.translateInPage(x, y);
4132      editor.translationDone();
4133    }
4134  }
4135  setUpDragSession() {
4136    if (!this.hasSelection) {
4137      return;
4138    }
4139    this.disableUserSelect(true);
4140    this.#draggingEditors = new Map();
4141    for (const editor of this.#selectedEditors) {
4142      this.#draggingEditors.set(editor, {
4143        savedX: editor.x,
4144        savedY: editor.y,
4145        savedPageIndex: editor.pageIndex,
4146        newX: 0,
4147        newY: 0,
4148        newPageIndex: -1
4149      });
4150    }
4151  }
4152  endDragSession() {
4153    if (!this.#draggingEditors) {
4154      return false;
4155    }
4156    this.disableUserSelect(false);
4157    const map = this.#draggingEditors;
4158    this.#draggingEditors = null;
4159    let mustBeAddedInUndoStack = false;
4160    for (const [{
4161      x,
4162      y,
4163      pageIndex
4164    }, value] of map) {
4165      value.newX = x;
4166      value.newY = y;
4167      value.newPageIndex = pageIndex;
4168      mustBeAddedInUndoStack ||= x !== value.savedX || y !== value.savedY || pageIndex !== value.savedPageIndex;
4169    }
4170    if (!mustBeAddedInUndoStack) {
4171      return false;
4172    }
4173    const move = (editor, x, y, pageIndex) => {
4174      if (this.#allEditors.has(editor.id)) {
4175        const parent = this.#allLayers.get(pageIndex);
4176        if (parent) {
4177          editor._setParentAndPosition(parent, x, y);
4178        } else {
4179          editor.pageIndex = pageIndex;
4180          editor.x = x;
4181          editor.y = y;
4182        }
4183      }
4184    };
4185    this.addCommands({
4186      cmd: () => {
4187        for (const [editor, {
4188          newX,
4189          newY,
4190          newPageIndex
4191        }] of map) {
4192          move(editor, newX, newY, newPageIndex);
4193        }
4194      },
4195      undo: () => {
4196        for (const [editor, {
4197          savedX,
4198          savedY,
4199          savedPageIndex
4200        }] of map) {
4201          move(editor, savedX, savedY, savedPageIndex);
4202        }
4203      },
4204      mustExec: true
4205    });
4206    return true;
4207  }
4208  dragSelectedEditors(tx, ty) {
4209    if (!this.#draggingEditors) {
4210      return;
4211    }
4212    for (const editor of this.#draggingEditors.keys()) {
4213      editor.drag(tx, ty);
4214    }
4215  }
4216  rebuild(editor) {
4217    if (editor.parent === null) {
4218      const parent = this.getLayer(editor.pageIndex);
4219      if (parent) {
4220        parent.changeParent(editor);
4221        parent.addOrRebuild(editor);
4222      } else {
4223        this.addEditor(editor);
4224        this.addToAnnotationStorage(editor);
4225        editor.rebuild();
4226      }
4227    } else {
4228      editor.parent.addOrRebuild(editor);
4229    }
4230  }
4231  get isEditorHandlingKeyboard() {
4232    return this.getActive()?.shouldGetKeyboardEvents() || this.#selectedEditors.size === 1 && this.firstSelectedEditor.shouldGetKeyboardEvents();
4233  }
4234  isActive(editor) {
4235    return this.#activeEditor === editor;
4236  }
4237  getActive() {
4238    return this.#activeEditor;
4239  }
4240  getMode() {
4241    return this.#mode;
4242  }
4243  isEditingMode() {
4244    return this.#mode !== AnnotationEditorType.NONE;
4245  }
4246  get imageManager() {
4247    return shadow(this, "imageManager", new ImageManager());
4248  }
4249  getSelectionBoxes(textLayer) {
4250    if (!textLayer) {
4251      return null;
4252    }
4253    const selection = document.getSelection();
4254    for (let i = 0, ii = selection.rangeCount; i < ii; i++) {
4255      if (!textLayer.contains(selection.getRangeAt(i).commonAncestorContainer)) {
4256        return null;
4257      }
4258    }
4259    const {
4260      x: layerX,
4261      y: layerY,
4262      width: parentWidth,
4263      height: parentHeight
4264    } = textLayer.getBoundingClientRect();
4265    let rotator;
4266    switch (textLayer.getAttribute("data-main-rotation")) {
4267      case "90":
4268        rotator = (x, y, w, h) => ({
4269          x: (y - layerY) / parentHeight,
4270          y: 1 - (x + w - layerX) / parentWidth,
4271          width: h / parentHeight,
4272          height: w / parentWidth
4273        });
4274        break;
4275      case "180":
4276        rotator = (x, y, w, h) => ({
4277          x: 1 - (x + w - layerX) / parentWidth,
4278          y: 1 - (y + h - layerY) / parentHeight,
4279          width: w / parentWidth,
4280          height: h / parentHeight
4281        });
4282        break;
4283      case "270":
4284        rotator = (x, y, w, h) => ({
4285          x: 1 - (y + h - layerY) / parentHeight,
4286          y: (x - layerX) / parentWidth,
4287          width: h / parentHeight,
4288          height: w / parentWidth
4289        });
4290        break;
4291      default:
4292        rotator = (x, y, w, h) => ({
4293          x: (x - layerX) / parentWidth,
4294          y: (y - layerY) / parentHeight,
4295          width: w / parentWidth,
4296          height: h / parentHeight
4297        });
4298        break;
4299    }
4300    const boxes = [];
4301    for (let i = 0, ii = selection.rangeCount; i < ii; i++) {
4302      const range = selection.getRangeAt(i);
4303      if (range.collapsed) {
4304        continue;
4305      }
4306      for (const {
4307        x,
4308        y,
4309        width,
4310        height
4311      } of range.getClientRects()) {
4312        if (width === 0 || height === 0) {
4313          continue;
4314        }
4315        boxes.push(rotator(x, y, width, height));
4316      }
4317    }
4318    return boxes.length === 0 ? null : boxes;
4319  }
4320  addChangedExistingAnnotation({
4321    annotationElementId,
4322    id
4323  }) {
4324    (this.#changedExistingAnnotations ||= new Map()).set(annotationElementId, id);
4325  }
4326  removeChangedExistingAnnotation({
4327    annotationElementId
4328  }) {
4329    this.#changedExistingAnnotations?.delete(annotationElementId);
4330  }
4331  renderAnnotationElement(annotation) {
4332    const editorId = this.#changedExistingAnnotations?.get(annotation.data.id);
4333    if (!editorId) {
4334      return;
4335    }
4336    const editor = this.#annotationStorage.getRawValue(editorId);
4337    if (!editor) {
4338      return;
4339    }
4340    if (this.#mode === AnnotationEditorType.NONE && !editor.hasBeenModified) {
4341      return;
4342    }
4343    editor.renderAnnotationElement(annotation);
4344  }
4345  setMissingCanvas(annotationId, annotationElementId, canvas) {
4346    const editor = this.#missingCanvases?.get(annotationId);
4347    if (!editor) {
4348      return;
4349    }
4350    editor.setCanvas(annotationElementId, canvas);
4351    this.#missingCanvases.delete(annotationId);
4352  }
4353  addMissingCanvas(annotationId, editor) {
4354    (this.#missingCanvases ||= new Map()).set(annotationId, editor);
4355  }
4356}
4357
4358;// ./src/display/editor/alt_text.js
4359
4360class AltText {
4361  #altText = null;
4362  #altTextDecorative = false;
4363  #altTextButton = null;
4364  #altTextButtonLabel = null;
4365  #altTextTooltip = null;
4366  #altTextTooltipTimeout = null;
4367  #altTextWasFromKeyBoard = false;
4368  #badge = null;
4369  #editor = null;
4370  #guessedText = null;
4371  #textWithDisclaimer = null;
4372  #useNewAltTextFlow = false;
4373  static #l10nNewButton = null;
4374  static _l10n = null;
4375  constructor(editor) {
4376    this.#editor = editor;
4377    this.#useNewAltTextFlow = editor._uiManager.useNewAltTextFlow;
4378    AltText.#l10nNewButton ||= Object.freeze({
4379      added: "pdfjs-editor-new-alt-text-added-button",
4380      "added-label": "pdfjs-editor-new-alt-text-added-button-label",
4381      missing: "pdfjs-editor-new-alt-text-missing-button",
4382      "missing-label": "pdfjs-editor-new-alt-text-missing-button-label",
4383      review: "pdfjs-editor-new-alt-text-to-review-button",
4384      "review-label": "pdfjs-editor-new-alt-text-to-review-button-label"
4385    });
4386  }
4387  static initialize(l10n) {
4388    AltText._l10n ??= l10n;
4389  }
4390  async render() {
4391    const altText = this.#altTextButton = document.createElement("button");
4392    altText.className = "altText";
4393    altText.tabIndex = "0";
4394    const label = this.#altTextButtonLabel = document.createElement("span");
4395    altText.append(label);
4396    if (this.#useNewAltTextFlow) {
4397      altText.classList.add("new");
4398      altText.setAttribute("data-l10n-id", AltText.#l10nNewButton.missing);
4399      label.setAttribute("data-l10n-id", AltText.#l10nNewButton["missing-label"]);
4400    } else {
4401      altText.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-button");
4402      label.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-button-label");
4403    }
4404    const signal = this.#editor._uiManager._signal;
4405    altText.addEventListener("contextmenu", noContextMenu, {
4406      signal
4407    });
4408    altText.addEventListener("pointerdown", event => event.stopPropagation(), {
4409      signal
4410    });
4411    const onClick = event => {
4412      event.preventDefault();
4413      this.#editor._uiManager.editAltText(this.#editor);
4414      if (this.#useNewAltTextFlow) {
4415        this.#editor._reportTelemetry({
4416          action: "pdfjs.image.alt_text.image_status_label_clicked",
4417          data: {
4418            label: this.#label
4419          }
4420        });
4421      }
4422    };
4423    altText.addEventListener("click", onClick, {
4424      capture: true,
4425      signal
4426    });
4427    altText.addEventListener("keydown", event => {
4428      if (event.target === altText && event.key === "Enter") {
4429        this.#altTextWasFromKeyBoard = true;
4430        onClick(event);
4431      }
4432    }, {
4433      signal
4434    });
4435    await this.#setState();
4436    return altText;
4437  }
4438  get #label() {
4439    return this.#altText && "added" || this.#altText === null && this.guessedText && "review" || "missing";
4440  }
4441  finish() {
4442    if (!this.#altTextButton) {
4443      return;
4444    }
4445    this.#altTextButton.focus({
4446      focusVisible: this.#altTextWasFromKeyBoard
4447    });
4448    this.#altTextWasFromKeyBoard = false;
4449  }
4450  isEmpty() {
4451    
4451if (this.#useNewAltTextFlow) {
4452      return this.#altText === null;
4453    }
4454    return !this.#altText && !this.#altTextDecorative;
4455  }
4456  hasData() {
4457    if (this.#useNewAltTextFlow) {
4458      return this.#altText !== null || !!this.#guessedText;
4459    }
4460    return
vendor: 12,118 bytes, lines 4460-4896
4460 this.isEmpty();
4461  }
4462  get guessedText() {
4463    return this.#guessedText;
4464  }
4465  async setGuessedText(guessedText) {
4466    if (this.#altText !== null) {
4467      return;
4468    }
4469    this.#guessedText = guessedText;
4470    this.#textWithDisclaimer = await AltText._l10n.get("pdfjs-editor-new-alt-text-generated-alt-text-with-disclaimer", {
4471      generatedAltText: guessedText
4472    });
4473    this.#setState();
4474  }
4475  toggleAltTextBadge(visibility = false) {
4476    if (!this.#useNewAltTextFlow || this.#altText) {
4477      this.#badge?.remove();
4478      this.#badge = null;
4479      return;
4480    }
4481    if (!this.#badge) {
4482      const badge = this.#badge = document.createElement("div");
4483      badge.className = "noAltTextBadge";
4484      this.#editor.div.append(badge);
4485    }
4486    this.#badge.classList.toggle("hidden", !visibility);
4487  }
4488  serialize(isForCopying) {
4489    let altText = this.#altText;
4490    if (!isForCopying && this.#guessedText === altText) {
4491      altText = this.#textWithDisclaimer;
4492    }
4493    return {
4494      altText,
4495      decorative: this.#altTextDecorative,
4496      guessedText: this.#guessedText,
4497      textWithDisclaimer: this.#textWithDisclaimer
4498    };
4499  }
4500  get data() {
4501    return {
4502      altText: this.#altText,
4503      decorative: this.#altTextDecorative
4504    };
4505  }
4506  set data({
4507    altText,
4508    decorative,
4509    guessedText,
4510    textWithDisclaimer,
4511    cancel = false
4512  }) {
4513    if (guessedText) {
4514      this.#guessedText = guessedText;
4515      this.#textWithDisclaimer = textWithDisclaimer;
4516    }
4517    if (this.#altText === altText && this.#altTextDecorative === decorative) {
4518      return;
4519    }
4520    if (!cancel) {
4521      this.#altText = altText;
4522      this.#altTextDecorative = decorative;
4523    }
4524    this.#setState();
4525  }
4526  toggle(enabled = false) {
4527    if (!this.#altTextButton) {
4528      return;
4529    }
4530    if (!enabled && this.#altTextTooltipTimeout) {
4531      clearTimeout(this.#altTextTooltipTimeout);
4532      this.#altTextTooltipTimeout = null;
4533    }
4534    this.#altTextButton.disabled = !enabled;
4535  }
4536  shown() {
4537    this.#editor._reportTelemetry({
4538      action: "pdfjs.image.alt_text.image_status_label_displayed",
4539      data: {
4540        label: this.#label
4541      }
4542    });
4543  }
4544  destroy() {
4545    this.#altTextButton?.remove();
4546    this.#altTextButton = null;
4547    this.#altTextButtonLabel = null;
4548    this.#altTextTooltip = null;
4549    this.#badge?.remove();
4550    this.#badge = null;
4551  }
4552  async #setState() {
4553    const button = this.#altTextButton;
4554    if (!button) {
4555      return;
4556    }
4557    if (this.#useNewAltTextFlow) {
4558      button.classList.toggle("done", !!this.#altText);
4559      button.setAttribute("data-l10n-id", AltText.#l10nNewButton[this.#label]);
4560      this.#altTextButtonLabel?.setAttribute("data-l10n-id", AltText.#l10nNewButton[`${this.#label}-label`]);
4561      if (!this.#altText) {
4562        this.#altTextTooltip?.remove();
4563        return;
4564      }
4565    } else {
4566      if (!this.#altText && !this.#altTextDecorative) {
4567        button.classList.remove("done");
4568        this.#altTextTooltip?.remove();
4569        return;
4570      }
4571      button.classList.add("done");
4572      button.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-edit-button");
4573    }
4574    let tooltip = this.#altTextTooltip;
4575    if (!tooltip) {
4576      this.#altTextTooltip = tooltip = document.createElement("span");
4577      tooltip.className = "tooltip";
4578      tooltip.setAttribute("role", "tooltip");
4579      tooltip.id = `alt-text-tooltip-${this.#editor.id}`;
4580      const DELAY_TO_SHOW_TOOLTIP = 100;
4581      const signal = this.#editor._uiManager._signal;
4582      signal.addEventListener("abort", () => {
4583        clearTimeout(this.#altTextTooltipTimeout);
4584        this.#altTextTooltipTimeout = null;
4585      }, {
4586        once: true
4587      });
4588      button.addEventListener("mouseenter", () => {
4589        this.#altTextTooltipTimeout = setTimeout(() => {
4590          this.#altTextTooltipTimeout = null;
4591          this.#altTextTooltip.classList.add("show");
4592          this.#editor._reportTelemetry({
4593            action: "alt_text_tooltip"
4594          });
4595        }, DELAY_TO_SHOW_TOOLTIP);
4596      }, {
4597        signal
4598      });
4599      button.addEventListener("mouseleave", () => {
4600        if (this.#altTextTooltipTimeout) {
4601          clearTimeout(this.#altTextTooltipTimeout);
4602          this.#altTextTooltipTimeout = null;
4603        }
4604        this.#altTextTooltip?.classList.remove("show");
4605      }, {
4606        signal
4607      });
4608    }
4609    if (this.#altTextDecorative) {
4610      tooltip.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-decorative-tooltip");
4611    } else {
4612      tooltip.removeAttribute("data-l10n-id");
4613      tooltip.textContent = this.#altText;
4614    }
4615    if (!tooltip.parentNode) {
4616      button.append(tooltip);
4617    }
4618    const element = this.#editor.getElementForAltText();
4619    element?.setAttribute("aria-describedby", tooltip.id);
4620  }
4621}
4622
4623;// ./src/display/editor/comment.js
4624
4625class Comment {
4626  #commentStandaloneButton = null;
4627  #commentToolbarButton = null;
4628  #commentWasFromKeyBoard = false;
4629  #editor = null;
4630  #initialText = null;
4631  #richText = null;
4632  #text = null;
4633  #date = null;
4634  #deleted = false;
4635  #popupPosition = null;
4636  constructor(editor) {
4637    this.#editor = editor;
4638  }
4639  renderForToolbar() {
4640    const button = this.#commentToolbarButton = document.createElement("button");
4641    button.className = "comment";
4642    return this.#render(button, false);
4643  }
4644  renderForStandalone() {
4645    const button = this.#commentStandaloneButton = document.createElement("button");
4646    button.className = "annotationCommentButton";
4647    const position = this.#editor.commentButtonPosition;
4648    if (position) {
4649      const {
4650        style
4651      } = button;
4652      style.insetInlineEnd = `calc(${100 * (this.#editor._uiManager.direction === "ltr" ? 1 - position[0] : position[0])}% - var(--comment-button-dim))`;
4653      style.top = `calc(${100 * position[1]}% - var(--comment-button-dim))`;
4654      const color = this.#editor.commentButtonColor;
4655      if (color) {
4656        style.backgroundColor = color;
4657      }
4658    }
4659    return this.#render(button, true);
4660  }
4661  focusButton() {
4662    setTimeout(() => {
4663      (this.#commentStandaloneButton ?? this.#commentToolbarButton)?.focus();
4664    }, 0);
4665  }
4666  onUpdatedColor() {
4667    if (!this.#commentStandaloneButton) {
4668      return;
4669    }
4670    const color = this.#editor.commentButtonColor;
4671    if (color) {
4672      this.#commentStandaloneButton.style.backgroundColor = color;
4673    }
4674    this.#editor._uiManager.updatePopupColor(this.#editor);
4675  }
4676  get commentButtonWidth() {
4677    return (this.#commentStandaloneButton?.getBoundingClientRect().width ?? 0) / this.#editor.parent.boundingClientRect.width;
4678  }
4679  get commentPopupPositionInLayer() {
4680    if (this.#popupPosition) {
4681      return this.#popupPosition;
4682    }
4683    if (!this.#commentStandaloneButton) {
4684      return null;
4685    }
4686    const {
4687      x,
4688      y,
4689      height
4690    } = this.#commentStandaloneButton.getBoundingClientRect();
4691    const {
4692      x: parentX,
4693      y: parentY,
4694      width: parentWidth,
4695      height: parentHeight
4696    } = this.#editor.parent.boundingClientRect;
4697    return [(x - parentX) / parentWidth, (y + height - parentY) / parentHeight];
4698  }
4699  set commentPopupPositionInLayer(pos) {
4700    this.#popupPosition = pos;
4701  }
4702  hasDefaultPopupPosition() {
4703    return this.#popupPosition === null;
4704  }
4705  removeStandaloneCommentButton() {
4706    this.#commentStandaloneButton?.remove();
4707    this.#commentStandaloneButton = null;
4708  }
4709  removeToolbarCommentButton() {
4710    this.#commentToolbarButton?.remove();
4711    this.#commentToolbarButton = null;
4712  }
4713  setCommentButtonStates({
4714    selected,
4715    hasPopup
4716  }) {
4717    if (!this.#commentStandaloneButton) {
4718      return;
4719    }
4720    this.#commentStandaloneButton.classList.toggle("selected", selected);
4721    this.#commentStandaloneButton.ariaExpanded = hasPopup;
4722  }
4723  #render(comment, isStandalone) {
4724    if (!this.#editor._uiManager.hasCommentManager()) {
4725      return null;
4726    }
4727    comment.tabIndex = "0";
4728    comment.ariaHasPopup = "dialog";
4729    if (isStandalone) {
4730      comment.ariaControls = "commentPopup";
4731      comment.setAttribute("data-l10n-id", "pdfjs-show-comment-button");
4732    } else {
4733      comment.ariaControlsElements = [this.#editor._uiManager.getCommentDialogElement()];
4734      comment.setAttribute("data-l10n-id", "pdfjs-editor-add-comment-button");
4735    }
4736    const signal = this.#editor._uiManager._signal;
4737    if (!(signal instanceof AbortSignal) || signal.aborted) {
4738      return comment;
4739    }
4740    comment.addEventListener("contextmenu", noContextMenu, {
4741      signal
4742    });
4743    if (isStandalone) {
4744      comment.addEventListener("focusin", e => {
4745        this.#editor._focusEventsAllowed = false;
4746        stopEvent(e);
4747      }, {
4748        capture: true,
4749        signal
4750      });
4751      comment.addEventListener("focusout", e => {
4752        this.#editor._focusEventsAllowed = true;
4753        stopEvent(e);
4754      }, {
4755        capture: true,
4756        signal
4757      });
4758    }
4759    comment.addEventListener("pointerdown", event => event.stopPropagation(), {
4760      signal
4761    });
4762    const onClick = event => {
4763      event.preventDefault();
4764      if (comment === this.#commentToolbarButton) {
4765        this.edit();
4766      } else {
4767        this.#editor.toggleComment(true);
4768      }
4769    };
4770    comment.addEventListener("click", onClick, {
4771      capture: true,
4772      signal
4773    });
4774    comment.addEventListener("keydown", event => {
4775      if (event.target === comment && event.key === "Enter") {
4776        this.#commentWasFromKeyBoard = true;
4777        onClick(event);
4778      }
4779    }, {
4780      signal
4781    });
4782    comment.addEventListener("pointerenter", () => {
4783      this.#editor.toggleComment(false, true);
4784    }, {
4785      signal
4786    });
4787    comment.addEventListener("pointerleave", () => {
4788      this.#editor.toggleComment(false, false);
4789    }, {
4790      signal
4791    });
4792    return comment;
4793  }
4794  edit(options) {
4795    const position = this.commentPopupPositionInLayer;
4796    let posX, posY;
4797    if (position) {
4798      [posX, posY] = position;
4799    } else {
4800      [posX, posY] = this.#editor.commentButtonPosition;
4801      const {
4802        width,
4803        height,
4804        x,
4805        y
4806      } = this.#editor;
4807      posX = x + posX * width;
4808      posY = y + posY * height;
4809    }
4810    const parentDimensions = this.#editor.parent.boundingClientRect;
4811    const {
4812      x: parentX,
4813      y: parentY,
4814      width: parentWidth,
4815      height: parentHeight
4816    } = parentDimensions;
4817    this.#editor._uiManager.editComment(this.#editor, parentX + posX * parentWidth, parentY + posY * parentHeight, {
4818      ...options,
4819      parentDimensions
4820    });
4821  }
4822  finish() {
4823    if (!this.#commentToolbarButton) {
4824      return;
4825    }
4826    this.#commentToolbarButton.focus({
4827      focusVisible: this.#commentWasFromKeyBoard
4828    });
4829    this.#commentWasFromKeyBoard = false;
4830  }
4831  isDeleted() {
4832    return this.#deleted || this.#text === "";
4833  }
4834  isEmpty() {
4835    return this.#text === null;
4836  }
4837  hasBeenEdited() {
4838    return this.isDeleted() || this.#text !== this.#initialText;
4839  }
4840  serialize() {
4841    return this.data;
4842  }
4843  get data() {
4844    return {
4845      text: this.#text,
4846      richText: this.#richText,
4847      date: this.#date,
4848      deleted: this.isDeleted()
4849    };
4850  }
4851  set data(text) {
4852    if (text !== this.#text) {
4853      this.#richText = null;
4854    }
4855    if (text === null) {
4856      this.#text = "";
4857      this.#deleted = true;
4858      return;
4859    }
4860    this.#text = text;
4861    this.#date = new Date();
4862    this.#deleted = false;
4863  }
4864  restoreData({
4865    text,
4866    richText,
4867    date
4868  }) {
4869    this.#text = text;
4870    this.#richText = richText;
4871    this.#date = date;
4872    this.#deleted = false;
4873  }
4874  setInitialText(text, richText = null) {
4875    this.#initialText = text;
4876    this.data = text;
4877    this.#date = null;
4878    this.#richText = richText;
4879  }
4880  shown() {}
4881  destroy() {
4882    this.#commentToolbarButton?.remove();
4883    this.#commentToolbarButton = null;
4884    this.#commentStandaloneButton?.remove();
4885    this.#commentStandaloneButton = null;
4886    this.#text = "";
4887    this.#richText = null;
4888    this.#date = null;
4889    this.#editor = null;
4890    this.#commentWasFromKeyBoard = false;
4891    this.#deleted = false;
4892  }
4893}
4894
4895;// ./src/display/touch_manager.js
4896
vendor: 8,488 bytes, lines 4897-5174
4897class TouchManager {
4898  #container;
4899  #isPinching = false;
4900  #isPinchingStopped = null;
4901  #isPinchingDisabled;
4902  #onPinchStart;
4903  #onPinching;
4904  #onPinchEnd;
4905  #pointerDownAC = null;
4906  #signal;
4907  #touchInfo = null;
4908  #touchManagerAC;
4909  #touchMoveAC = null;
4910  constructor({
4911    container,
4912    isPinchingDisabled = null,
4913    isPinchingStopped = null,
4914    onPinchStart = null,
4915    onPinching = null,
4916    onPinchEnd = null,
4917    signal
4918  }) {
4919    this.#container = container;
4920    this.#isPinchingStopped = isPinchingStopped;
4921    this.#isPinchingDisabled = isPinchingDisabled;
4922    this.#onPinchStart = onPinchStart;
4923    this.#onPinching = onPinching;
4924    this.#onPinchEnd = onPinchEnd;
4925    this.#touchManagerAC = new AbortController();
4926    this.#signal = AbortSignal.any([signal, this.#touchManagerAC.signal]);
4927    container.addEventListener("touchstart", this.#onTouchStart.bind(this), {
4928      passive: false,
4929      signal: this.#signal
4930    });
4931  }
4932  get MIN_TOUCH_DISTANCE_TO_PINCH() {
4933    return 35 / OutputScale.pixelRatio;
4934  }
4935  #onTouchStart(evt) {
4936    if (this.#isPinchingDisabled?.()) {
4937      return;
4938    }
4939    if (evt.touches.length === 1) {
4940      if (this.#pointerDownAC) {
4941        return;
4942      }
4943      const pointerDownAC = this.#pointerDownAC = new AbortController();
4944      const signal = AbortSignal.any([this.#signal, pointerDownAC.signal]);
4945      const container = this.#container;
4946      const opts = {
4947        capture: true,
4948        signal,
4949        passive: false
4950      };
4951      const cancelPointerDown = e => {
4952        if (e.pointerType === "touch") {
4953          this.#pointerDownAC?.abort();
4954          this.#pointerDownAC = null;
4955        }
4956      };
4957      container.addEventListener("pointerdown", e => {
4958        if (e.pointerType === "touch") {
4959          stopEvent(e);
4960          cancelPointerDown(e);
4961        }
4962      }, opts);
4963      container.addEventListener("pointerup", cancelPointerDown, opts);
4964      container.addEventListener("pointercancel", cancelPointerDown, opts);
4965      return;
4966    }
4967    if (!this.#touchMoveAC) {
4968      this.#touchMoveAC = new AbortController();
4969      const signal = AbortSignal.any([this.#signal, this.#touchMoveAC.signal]);
4970      const container = this.#container;
4971      const opt = {
4972        signal,
4973        capture: false,
4974        passive: false
4975      };
4976      container.addEventListener("touchmove", this.#onTouchMove.bind(this), opt);
4977      const onTouchEnd = this.#onTouchEnd.bind(this);
4978      container.addEventListener("touchend", onTouchEnd, opt);
4979      container.addEventListener("touchcancel", onTouchEnd, opt);
4980      opt.capture = true;
4981      container.addEventListener("pointerdown", stopEvent, opt);
4982      container.addEventListener("pointermove", stopEvent, opt);
4983      container.addEventListener("pointercancel", stopEvent, opt);
4984      container.addEventListener("pointerup", stopEvent, opt);
4985      this.#onPinchStart?.();
4986    }
4987    stopEvent(evt);
4988    if (evt.touches.length !== 2 || this.#isPinchingStopped?.()) {
4989      this.#touchInfo = null;
4990      return;
4991    }
4992    let [touch0, touch1] = evt.touches;
4993    if (touch0.identifier > touch1.identifier) {
4994      [touch0, touch1] = [touch1, touch0];
4995    }
4996    this.#touchInfo = {
4997      touch0X: touch0.screenX,
4998      touch0Y: touch0.screenY,
4999      touch1X: touch1.screenX,
5000      touch1Y: touch1.screenY
5001    };
5002  }
5003  #onTouchMove(evt) {
5004    if (!this.#touchInfo || evt.touches.length !== 2) {
5005      return;
5006    }
5007    stopEvent(evt);
5008    let [touch0, touch1] = evt.touches;
5009    if (touch0.identifier > touch1.identifier) {
5010      [touch0, touch1] = [touch1, touch0];
5011    }
5012    const {
5013      screenX: screen0X,
5014      screenY: screen0Y
5015    } = touch0;
5016    const {
5017      screenX: screen1X,
5018      screenY: screen1Y
5019    } = touch1;
5020    const touchInfo = this.#touchInfo;
5021    const {
5022      touch0X: pTouch0X,
5023      touch0Y: pTouch0Y,
5024      touch1X: pTouch1X,
5025      touch1Y: pTouch1Y
5026    } = touchInfo;
5027    const prevGapX = pTouch1X - pTouch0X;
5028    const prevGapY = pTouch1Y - pTouch0Y;
5029    const currGapX = screen1X - screen0X;
5030    const currGapY = screen1Y - screen0Y;
5031    const distance = Math.hypot(currGapX, currGapY) || 1;
5032    const pDistance = Math.hypot(prevGapX, prevGapY) || 1;
5033    if (!this.#isPinching && Math.abs(pDistance - distance) <= TouchManager.MIN_TOUCH_DISTANCE_TO_PINCH) {
5034      return;
5035    }
5036    touchInfo.touch0X = screen0X;
5037    touchInfo.touch0Y = screen0Y;
5038    touchInfo.touch1X = screen1X;
5039    touchInfo.touch1Y = screen1Y;
5040    if (!this.#isPinching) {
5041      this.#isPinching = true;
5042      return;
5043    }
5044    const origin = [(screen0X + screen1X) / 2, (screen0Y + screen1Y) / 2];
5045    this.#onPinching?.(origin, pDistance, distance);
5046  }
5047  #onTouchEnd(evt) {
5048    if (evt.touches.length >= 2) {
5049      return;
5050    }
5051    if (this.#touchMoveAC) {
5052      this.#touchMoveAC.abort();
5053      this.#touchMoveAC = null;
5054      this.#onPinchEnd?.();
5055    }
5056    if (!this.#touchInfo) {
5057      return;
5058    }
5059    stopEvent(evt);
5060    this.#touchInfo = null;
5061    this.#isPinching = false;
5062  }
5063  destroy() {
5064    this.#touchManagerAC?.abort();
5065    this.#touchManagerAC = null;
5066    this.#pointerDownAC?.abort();
5067    this.#pointerDownAC = null;
5068  }
5069}
5070
5071;// ./src/display/editor/editor.js
5072
5073
5074
5075
5076
5077
5078
5079class AnnotationEditor {
5080  #accessibilityData = null;
5081  #allResizerDivs = null;
5082  #altText = null;
5083  #comment = null;
5084  #commentStandaloneButton = null;
5085  #disabled = false;
5086  #dragPointerId = null;
5087  #dragPointerType = "";
5088  #resizersDiv = null;
5089  #lastPointerCoords = null;
5090  #savedDimensions = null;
5091  #fakeAnnotation = null;
5092  #focusAC = null;
5093  #focusedResizerName = "";
5094  #hasBeenClicked = false;
5095  #initialRect = null;
5096  #isEditing = false;
5097  #isInEditMode = false;
5098  #isResizerEnabledForKeyboard = false;
5099  #moveInDOMTimeout = null;
5100  #prevDragX = 0;
5101  #prevDragY = 0;
5102  #telemetryTimeouts = null;
5103  #touchManager = null;
5104  isSelected = false;
5105  _isCopy = false;
5106  _editToolbar = null;
5107  _initialOptions = Object.create(null);
5108  _initialData = null;
5109  _isVisible = true;
5110  _uiManager = null;
5111  _focusEventsAllowed = true;
5112  static _l10n = null;
5113  static _l10nResizer = null;
5114  #isDraggable = false;
5115  #zIndex = AnnotationEditor._zIndex++;
5116  static _borderLineWidth = -1;
5117  static _colorManager = new ColorManager();
5118  static _zIndex = 1;
5119  static _telemetryTimeout = 1000;
5120  static get _resizerKeyboardManager() {
5121    const resize = AnnotationEditor.prototype._resizeWithKeyboard;
5122    const small = AnnotationEditorUIManager.TRANSLATE_SMALL;
5123    const big = AnnotationEditorUIManager.TRANSLATE_BIG;
5124    return shadow(this, "_resizerKeyboardManager", new KeyboardManager([[["ArrowLeft", "mac+ArrowLeft"], resize, {
5125      args: [-small, 0]
5126    }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], resize, {
5127      args: [-big, 0]
5128    }], [["ArrowRight", "mac+ArrowRight"], resize, {
5129      args: [small, 0]
5130    }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], resize, {
5131      args: [big, 0]
5132    }], [["ArrowUp", "mac+ArrowUp"], resize, {
5133      args: [0, -small]
5134    }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], resize, {
5135      args: [0, -big]
5136    }], [["ArrowDown", "mac+ArrowDown"], resize, {
5137      args: [0, small]
5138    }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], resize, {
5139      args: [0, big]
5140    }], [["Escape", "mac+Escape"], AnnotationEditor.prototype._stopResizingWithKeyboard]]));
5141  }
5142  constructor(parameters) {
5143    this.parent = parameters.parent;
5144    this.id = parameters.id;
5145    this.width = this.height = null;
5146    this.pageIndex = parameters.parent.pageIndex;
5147    this.name = parameters.name;
5148    this.div = null;
5149    this._uiManager = parameters.uiManager;
5150    this.annotationElementId = null;
5151    this._willKeepAspectRatio = false;
5152    this._initialOptions.isCentered = parameters.isCentered;
5153    this._structTreeParentId = null;
5154    this.annotationElementId = parameters.annotationElementId || null;
5155    this.creationDate = parameters.creationDate || new Date();
5156    this.modificationDate = parameters.modificationDate || null;
5157    this.canAddComment = true;
5158    const {
5159      rotation,
5160      rawDims: {
5161        pageWidth,
5162        pageHeight,
5163        pageX,
5164        pageY
5165      }
5166    } = this.parent.viewport;
5167    this.rotation = rotation;
5168    this.pageRotation = (360 + rotation - this._uiManager.viewParameters.rotation) % 360;
5169    this.pageDimensions = [pageWidth, pageHeight];
5170    this.pageTranslation = [pageX, pageY];
5171    const [width, height] = this.parentDimensions;
5172    this.x = parameters.x / width;
5173    this.y = parameters.y / height;
5174    this.isAttachedToDOM = false;
vendor: 35,507 bytes, lines 5175-6378
5175    this.deleted = false;
5176  }
5177  updatePageIndex(newPageIndex) {
5178    this.pageIndex = newPageIndex;
5179  }
5180  get editorType() {
5181    return Object.getPrototypeOf(this).constructor._type;
5182  }
5183  get mode() {
5184    return Object.getPrototypeOf(this).constructor._editorType;
5185  }
5186  static get isDrawer() {
5187    return false;
5188  }
5189  static get _defaultLineColor() {
5190    return shadow(this, "_defaultLineColor", this._colorManager.getHexCode("CanvasText"));
5191  }
5192  static deleteAnnotationElement(editor) {
5193    const fakeEditor = new FakeEditor({
5194      id: editor.parent.getNextId(),
5195      parent: editor.parent,
5196      uiManager: editor._uiManager
5197    });
5198    fakeEditor.annotationElementId = editor.annotationElementId;
5199    fakeEditor.deleted = true;
5200    fakeEditor._uiManager.addToAnnotationStorage(fakeEditor);
5201  }
5202  static initialize(l10n, _uiManager) {
5203    AnnotationEditor._l10n ??= l10n;
5204    AnnotationEditor._l10nResizer ||= Object.freeze({
5205      topLeft: "pdfjs-editor-resizer-top-left",
5206      topMiddle: "pdfjs-editor-resizer-top-middle",
5207      topRight: "pdfjs-editor-resizer-top-right",
5208      middleRight: "pdfjs-editor-resizer-middle-right",
5209      bottomRight: "pdfjs-editor-resizer-bottom-right",
5210      bottomMiddle: "pdfjs-editor-resizer-bottom-middle",
5211      bottomLeft: "pdfjs-editor-resizer-bottom-left",
5212      middleLeft: "pdfjs-editor-resizer-middle-left"
5213    });
5214    if (AnnotationEditor._borderLineWidth !== -1) {
5215      return;
5216    }
5217    const style = getComputedStyle(document.documentElement);
5218    AnnotationEditor._borderLineWidth = parseFloat(style.getPropertyValue("--outline-width")) || 0;
5219  }
5220  static updateDefaultParams(_type, _value) {}
5221  static get defaultPropertiesToUpdate() {
5222    return [];
5223  }
5224  static isHandlingMimeForPasting(mime) {
5225    return false;
5226  }
5227  static paste(item, parent) {
5228    unreachable("Not implemented");
5229  }
5230  get propertiesToUpdate() {
5231    return [];
5232  }
5233  get _isDraggable() {
5234    return this.#isDraggable;
5235  }
5236  set _isDraggable(value) {
5237    this.#isDraggable = value;
5238    this.div?.classList.toggle("draggable", value);
5239  }
5240  get uid() {
5241    return this.annotationElementId || this.id;
5242  }
5243  get isEnterHandled() {
5244    return true;
5245  }
5246  center() {
5247    const [pageWidth, pageHeight] = this.pageDimensions;
5248    switch (this.parentRotation) {
5249      case 90:
5250        this.x -= this.height * pageHeight / (pageWidth * 2);
5251        this.y += this.width * pageWidth / (pageHeight * 2);
5252        break;
5253      case 180:
5254        this.x += this.width / 2;
5255        this.y += this.height / 2;
5256        break;
5257      case 270:
5258        this.x += this.height * pageHeight / (pageWidth * 2);
5259        this.y -= this.width * pageWidth / (pageHeight * 2);
5260        break;
5261      default:
5262        this.x -= this.width / 2;
5263        this.y -= this.height / 2;
5264        break;
5265    }
5266    this.fixAndSetPosition();
5267  }
5268  addCommands(params) {
5269    this._uiManager.addCommands(params);
5270  }
5271  get currentLayer() {
5272    return this._uiManager.currentLayer;
5273  }
5274  setInBackground() {
5275    this.div.style.zIndex = 0;
5276  }
5277  setInForeground() {
5278    this.div.style.zIndex = this.#zIndex;
5279  }
5280  setParent(parent) {
5281    if (parent !== null) {
5282      this.pageIndex = parent.pageIndex;
5283      this.pageDimensions = parent.pageDimensions;
5284    } else {
5285      this.#stopResizing();
5286      this.#fakeAnnotation?.remove();
5287      this.#fakeAnnotation = null;
5288    }
5289    this.parent = parent;
5290  }
5291  focusin(event) {
5292    if (!this._focusEventsAllowed) {
5293      return;
5294    }
5295    if (!this.#hasBeenClicked) {
5296      this.parent.setSelected(this);
5297    } else {
5298      this.#hasBeenClicked = false;
5299    }
5300  }
5301  focusout(event) {
5302    if (!this._focusEventsAllowed) {
5303      return;
5304    }
5305    if (!this.isAttachedToDOM) {
5306      return;
5307    }
5308    const target = event.relatedTarget;
5309    if (target?.closest(`#${this.id}`)) {
5310      return;
5311    }
5312    event.preventDefault();
5313    if (!this.parent?.isMultipleSelection) {
5314      this.commitOrRemove();
5315    }
5316  }
5317  commitOrRemove() {
5318    if (this.isEmpty()) {
5319      this.remove();
5320    } else {
5321      this.commit();
5322    }
5323  }
5324  commit() {
5325    if (!this.isInEditMode()) {
5326      return;
5327    }
5328    this.addToAnnotationStorage();
5329  }
5330  addToAnnotationStorage() {
5331    this._uiManager.addToAnnotationStorage(this);
5332  }
5333  setAt(x, y, tx, ty) {
5334    const [width, height] = this.parentDimensions;
5335    [tx, ty] = this.screenToPageTranslation(tx, ty);
5336    this.x = (x + tx) / width;
5337    this.y = (y + ty) / height;
5338    this.fixAndSetPosition();
5339  }
5340  _moveAfterPaste(baseX, baseY) {
5341    const [parentWidth, parentHeight] = this.parentDimensions;
5342    this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight);
5343    this._onTranslated();
5344  }
5345  #translate([width, height], x, y) {
5346    [x, y] = this.screenToPageTranslation(x, y);
5347    this.x += x / width;
5348    this.y += y / height;
5349    this._onTranslating(this.x, this.y);
5350    this.fixAndSetPosition();
5351  }
5352  translate(x, y) {
5353    this.#translate(this.parentDimensions, x, y);
5354  }
5355  translateInPage(x, y) {
5356    this.#initialRect ||= [this.x, this.y, this.width, this.height];
5357    this.#translate(this.pageDimensions, x, y);
5358    this.div.scrollIntoView({
5359      block: "nearest"
5360    });
5361  }
5362  translationDone() {
5363    this._onTranslated(this.x, this.y);
5364  }
5365  drag(tx, ty) {
5366    this.#initialRect ||= [this.x, this.y, this.width, this.height];
5367    const {
5368      div,
5369      parentDimensions: [parentWidth, parentHeight]
5370    } = this;
5371    this.x += tx / parentWidth;
5372    this.y += ty / parentHeight;
5373    if (this.parent && (this.x < 0 || this.x > 1 || this.y < 0 || this.y > 1)) {
5374      const {
5375        x,
5376        y
5377      } = this.div.getBoundingClientRect();
5378      if (this.parent.findNewParent(this, x, y)) {
5379        this.x -= Math.floor(this.x);
5380        this.y -= Math.floor(this.y);
5381      }
5382    }
5383    let {
5384      x,
5385      y
5386    } = this;
5387    const [bx, by] = this.getBaseTranslation();
5388    x += bx;
5389    y += by;
5390    const {
5391      style
5392    } = div;
5393    style.left = `${(100 * x).toFixed(2)}%`;
5394    style.top = `${(100 * y).toFixed(2)}%`;
5395    this._onTranslating(x, y);
5396    div.scrollIntoView({
5397      block: "nearest"
5398    });
5399  }
5400  _onTranslating(x, y) {}
5401  _onTranslated(x, y) {}
5402  get _hasBeenMoved() {
5403    return !!this.#initialRect && (this.#initialRect[0] !== this.x || this.#initialRect[1] !== this.y);
5404  }
5405  get _hasBeenResized() {
5406    return !!this.#initialRect && (this.#initialRect[2] !== this.width || this.#initialRect[3] !== this.height);
5407  }
5408  getBaseTranslation() {
5409    const [parentWidth, parentHeight] = this.parentDimensions;
5410    const {
5411      _borderLineWidth
5412    } = AnnotationEditor;
5413    const x = _borderLineWidth / parentWidth;
5414    const y = _borderLineWidth / parentHeight;
5415    switch (this.rotation) {
5416      case 90:
5417        return [-x, y];
5418      case 180:
5419        return [x, y];
5420      case 270:
5421        return [x, -y];
5422      default:
5423        return [-x, -y];
5424    }
5425  }
5426  get _mustFixPosition() {
5427    return true;
5428  }
5429  fixAndSetPosition(rotation = this.rotation) {
5430    const {
5431      div: {
5432        style
5433      },
5434      pageDimensions: [pageWidth, pageHeight]
5435    } = this;
5436    let {
5437      x,
5438      y,
5439      width,
5440      height
5441    } = this;
5442    width *= pageWidth;
5443    height *= pageHeight;
5444    x *= pageWidth;
5445    y *= pageHeight;
5446    if (this._mustFixPosition) {
5447      switch (rotation) {
5448        case 0:
5449          x = MathClamp(x, 0, pageWidth - width);
5450          y = MathClamp(y, 0, pageHeight - height);
5451          break;
5452        case 90:
5453          x = MathClamp(x, 0, pageWidth - height);
5454          y = MathClamp(y, width, pageHeight);
5455          break;
5456        case 180:
5457          x = MathClamp(x, width, pageWidth);
5458          y = MathClamp(y, height, pageHeight);
5459          break;
5460        case 270:
5461          x = MathClamp(x, height, pageWidth);
5462          y = MathClamp(y, 0, pageHeight - width);
5463          break;
5464      }
5465    }
5466    this.x = x /= pageWidth;
5467    this.y = y /= pageHeight;
5468    const [bx, by] = this.getBaseTranslation();
5469    x += bx;
5470    y += by;
5471    style.left = `${(100 * x).toFixed(2)}%`;
5472    style.top = `${(100 * y).toFixed(2)}%`;
5473    this.moveInDOM();
5474  }
5475  static #rotatePoint(x, y, angle) {
5476    switch (angle) {
5477      case 90:
5478        return [y, -x];
5479      case 180:
5480        return [-x, -y];
5481      case 270:
5482        return [-y, x];
5483      default:
5484        return [x, y];
5485    }
5486  }
5487  screenToPageTranslation(x, y) {
5488    return AnnotationEditor.#rotatePoint(x, y, this.parentRotation);
5489  }
5490  pageTranslationToScreen(x, y) {
5491    return AnnotationEditor.#rotatePoint(x, y, 360 - this.parentRotation);
5492  }
5493  #getRotationMatrix(rotation) {
5494    switch (rotation) {
5495      case 90:
5496        {
5497          const [pageWidth, pageHeight] = this.pageDimensions;
5498          return [0, -pageWidth / pageHeight, pageHeight / pageWidth, 0];
5499        }
5500      case 180:
5501        return [-1, 0, 0, -1];
5502      case 270:
5503        {
5504          const [pageWidth, pageHeight] = this.pageDimensions;
5505          return [0, pageWidth / pageHeight, -pageHeight / pageWidth, 0];
5506        }
5507      default:
5508        return [1, 0, 0, 1];
5509    }
5510  }
5511  get parentScale() {
5512    return this._uiManager.viewParameters.realScale;
5513  }
5514  get parentRotation() {
5515    return (this._uiManager.viewParameters.rotation + this.pageRotation) % 360;
5516  }
5517  get parentDimensions() {
5518    const {
5519      parentScale,
5520      pageDimensions: [pageWidth, pageHeight]
5521    } = this;
5522    return [pageWidth * parentScale, pageHeight * parentScale];
5523  }
5524  setDims() {
5525    const {
5526      div: {
5527        style
5528      },
5529      width,
5530      height
5531    } = this;
5532    style.width = `${(100 * width).toFixed(2)}%`;
5533    style.height = `${(100 * height).toFixed(2)}%`;
5534  }
5535  getInitialTranslation() {
5536    return [0, 0];
5537  }
5538  #createResizers() {
5539    if (this.#resizersDiv) {
5540      return;
5541    }
5542    this.#resizersDiv = document.createElement("div");
5543    this.#resizersDiv.classList.add("resizers");
5544    const classes = this._willKeepAspectRatio ? ["topLeft", "topRight", "bottomRight", "bottomLeft"] : ["topLeft", "topMiddle", "topRight", "middleRight", "bottomRight", "bottomMiddle", "bottomLeft", "middleLeft"];
5545    const signal = this._uiManager._signal;
5546    for (const name of classes) {
5547      const div = document.createElement("div");
5548      this.#resizersDiv.append(div);
5549      div.classList.add("resizer", name);
5550      div.setAttribute("data-resizer-name", name);
5551      div.addEventListener("pointerdown", this.#resizerPointerdown.bind(this, name), {
5552        signal
5553      });
5554      div.addEventListener("contextmenu", noContextMenu, {
5555        signal
5556      });
5557      div.tabIndex = -1;
5558    }
5559    this.div.prepend(this.#resizersDiv);
5560  }
5561  #resizerPointerdown(name, event) {
5562    event.preventDefault();
5563    const {
5564      isMac
5565    } = util_FeatureTest.platform;
5566    if (event.button !== 0 || event.ctrlKey && isMac) {
5567      return;
5568    }
5569    this.#altText?.toggle(false);
5570    const savedDraggable = this._isDraggable;
5571    this._isDraggable = false;
5572    this.#lastPointerCoords = [event.screenX, event.screenY];
5573    const ac = new AbortController();
5574    const signal = this._uiManager.combinedSignal(ac);
5575    this.parent.togglePointerEvents(false);
5576    window.addEventListener("pointermove", this.#resizerPointermove.bind(this, name), {
5577      passive: true,
5578      capture: true,
5579      signal
5580    });
5581    window.addEventListener("touchmove", stopEvent, {
5582      passive: false,
5583      signal
5584    });
5585    window.addEventListener("contextmenu", noContextMenu, {
5586      signal
5587    });
5588    this.#savedDimensions = {
5589      savedX: this.x,
5590      savedY: this.y,
5591      savedWidth: this.width,
5592      savedHeight: this.height
5593    };
5594    const savedParentCursor = this.parent.div.style.cursor;
5595    const savedCursor = this.div.style.cursor;
5596    this.div.style.cursor = this.parent.div.style.cursor = window.getComputedStyle(event.target).cursor;
5597    const pointerUpCallback = () => {
5598      ac.abort();
5599      this.parent.togglePointerEvents(true);
5600      this.#altText?.toggle(true);
5601      this._isDraggable = savedDraggable;
5602      this.parent.div.style.cursor = savedParentCursor;
5603      this.div.style.cursor = savedCursor;
5604      this.#addResizeToUndoStack();
5605    };
5606    window.addEventListener("pointerup", pointerUpCallback, {
5607      signal
5608    });
5609    window.addEventListener("blur", pointerUpCallback, {
5610      signal
5611    });
5612  }
5613  #resize(x, y, width, height) {
5614    this.width = width;
5615    this.height = height;
5616    this.x = x;
5617    this.y = y;
5618    this.setDims();
5619    this.fixAndSetPosition();
5620    this._onResized();
5621  }
5622  _onResized() {}
5623  #addResizeToUndoStack() {
5624    if (!this.#savedDimensions) {
5625      return;
5626    }
5627    const {
5628      savedX,
5629      savedY,
5630      savedWidth,
5631      savedHeight
5632    } = this.#savedDimensions;
5633    this.#savedDimensions = null;
5634    const newX = this.x;
5635    const newY = this.y;
5636    const newWidth = this.width;
5637    const newHeight = this.height;
5638    if (newX === savedX && newY === savedY && newWidth === savedWidth && newHeight === savedHeight) {
5639      return;
5640    }
5641    this.addCommands({
5642      cmd: this.#resize.bind(this, newX, newY, newWidth, newHeight),
5643      undo: this.#resize.bind(this, savedX, savedY, savedWidth, savedHeight),
5644      mustExec: true
5645    });
5646  }
5647  static _round(x) {
5648    return Math.round(x * 10000) / 10000;
5649  }
5650  #resizerPointermove(name, event) {
5651    const [parentWidth, parentHeight] = this.parentDimensions;
5652    const savedX = this.x;
5653    const savedY = this.y;
5654    const savedWidth = this.width;
5655    const savedHeight = this.height;
5656    const minWidth = AnnotationEditor.MIN_SIZE / parentWidth;
5657    const minHeight = AnnotationEditor.MIN_SIZE / parentHeight;
5658    const rotationMatrix = this.#getRotationMatrix(this.rotation);
5659    const transf = (x, y) => [rotationMatrix[0] * x + rotationMatrix[2] * y, rotationMatrix[1] * x + rotationMatrix[3] * y];
5660    const invRotationMatrix = this.#getRotationMatrix(360 - this.rotation);
5661    const invTransf = (x, y) => [invRotationMatrix[0] * x + invRotationMatrix[2] * y, invRotationMatrix[1] * x + invRotationMatrix[3] * y];
5662    let getPoint;
5663    let getOpposite;
5664    let isDiagonal = false;
5665    let isHorizontal = false;
5666    switch (name) {
5667      case "topLeft":
5668        isDiagonal = true;
5669        getPoint = (w, h) => [0, 0];
5670        getOpposite = (w, h) => [w, h];
5671        break;
5672      case "topMiddle":
5673        getPoint = (w, h) => [w / 2, 0];
5674        getOpposite = (w, h) => [w / 2, h];
5675        break;
5676      case "topRight":
5677        isDiagonal = true;
5678        getPoint = (w, h) => [w, 0];
5679        getOpposite = (w, h) => [0, h];
5680        break;
5681      case "middleRight":
5682        isHorizontal = true;
5683        getPoint = (w, h) => [w, h / 2];
5684        getOpposite = (w, h) => [0, h / 2];
5685        break;
5686      case "bottomRight":
5687        isDiagonal = true;
5688        getPoint = (w, h) => [w, h];
5689        getOpposite = (w, h) => [0, 0];
5690        break;
5691      case "bottomMiddle":
5692        getPoint = (w, h) => [w / 2, h];
5693        getOpposite = (w, h) => [w / 2, 0];
5694        break;
5695      case "bottomLeft":
5696        isDiagonal = true;
5697        getPoint = (w, h) => [0, h];
5698        getOpposite = (w, h) => [w, 0];
5699        break;
5700      case "middleLeft":
5701        isHorizontal = true;
5702        getPoint = (w, h) => [0, h / 2];
5703        getOpposite = (w, h) => [w, h / 2];
5704        break;
5705    }
5706    const point = getPoint(savedWidth, savedHeight);
5707    const oppositePoint = getOpposite(savedWidth, savedHeight);
5708    let transfOppositePoint = transf(...oppositePoint);
5709    const oppositeX = AnnotationEditor._round(savedX + transfOppositePoint[0]);
5710    const oppositeY = AnnotationEditor._round(savedY + transfOppositePoint[1]);
5711    let ratioX = 1;
5712    let ratioY = 1;
5713    let deltaX, deltaY;
5714    if (!event.fromKeyboard) {
5715      const {
5716        screenX,
5717        screenY
5718      } = event;
5719      const [lastScreenX, lastScreenY] = this.#lastPointerCoords;
5720      [deltaX, deltaY] = this.screenToPageTranslation(screenX - lastScreenX, screenY - lastScreenY);
5721      this.#lastPointerCoords[0] = screenX;
5722      this.#lastPointerCoords[1] = screenY;
5723    } else {
5724      ({
5725        deltaX,
5726        deltaY
5727      } = event);
5728    }
5729    [deltaX, deltaY] = invTransf(deltaX / parentWidth, deltaY / parentHeight);
5730    if (isDiagonal) {
5731      const oldDiag = Math.hypot(savedWidth, savedHeight);
5732      ratioX = ratioY = Math.max(Math.min(Math.hypot(oppositePoint[0] - point[0] - deltaX, oppositePoint[1] - point[1] - deltaY) / oldDiag, 1 / savedWidth, 1 / savedHeight), minWidth / savedWidth, minHeight / savedHeight);
5733    } else if (isHorizontal) {
5734      ratioX = MathClamp(Math.abs(oppositePoint[0] - point[0] - deltaX), minWidth, 1) / savedWidth;
5735    } else {
5736      ratioY = MathClamp(Math.abs(oppositePoint[1] - point[1] - deltaY), minHeight, 1) / savedHeight;
5737    }
5738    const newWidth = AnnotationEditor._round(savedWidth * ratioX);
5739    const newHeight = AnnotationEditor._round(savedHeight * ratioY);
5740    transfOppositePoint = transf(...getOpposite(newWidth, newHeight));
5741    const newX = oppositeX - transfOppositePoint[0];
5742    const newY = oppositeY - transfOppositePoint[1];
5743    this.#initialRect ||= [this.x, this.y, this.width, this.height];
5744    this.width = newWidth;
5745    this.height = newHeight;
5746    this.x = newX;
5747    this.y = newY;
5748    this.setDims();
5749    this.fixAndSetPosition();
5750    this._onResizing();
5751  }
5752  _onResizing() {}
5753  altTextFinish() {
5754    this.#altText?.finish();
5755  }
5756  get toolbarButtons() {
5757    return null;
5758  }
5759  async addEditToolbar() {
5760    if (this._editToolbar || this.#isInEditMode) {
5761      return this._editToolbar;
5762    }
5763    this._editToolbar = new EditorToolbar(this);
5764    this.div.append(this._editToolbar.render());
5765    const {
5766      toolbarButtons
5767    } = this;
5768    if (toolbarButtons) {
5769      for (const [name, tool] of toolbarButtons) {
5770        await this._editToolbar.addButton(name, tool);
5771      }
5772    }
5773    if (!this.hasComment) {
5774      this._editToolbar.addButton("comment", this.addCommentButton());
5775    }
5776    this._editToolbar.addButton("delete");
5777    return this._editToolbar;
5778  }
5779  addCommentButtonInToolbar() {
5780    this._editToolbar?.addButtonBefore("comment", this.addCommentButton(), ".deleteButton");
5781  }
5782  removeCommentButtonFromToolbar() {
5783    this._editToolbar?.removeButton("comment");
5784  }
5785  removeEditToolbar() {
5786    this._editToolbar?.remove();
5787    this._editToolbar = null;
5788    this.#altText?.destroy();
5789  }
5790  addContainer(container) {
5791    const editToolbarDiv = this._editToolbar?.div;
5792    if (editToolbarDiv) {
5793      editToolbarDiv.before(container);
5794    } else {
5795      this.div.append(container);
5796    }
5797  }
5798  getClientDimensions() {
5799    return this.div.getBoundingClientRect();
5800  }
5801  createAltText() {
5802    if (!this.#altText) {
5803      AltText.initialize(AnnotationEditor._l10n);
5804      this.#altText = new AltText(this);
5805      if (this.#accessibilityData) {
5806        this.#altText.data = this.#accessibilityData;
5807        this.#accessibilityData = null;
5808      }
5809    }
5810    return this.#altText;
5811  }
5812  get altTextData() {
5813    return this.#altText?.data;
5814  }
5815  set altTextData(data) {
5816    if (!this.#altText) {
5817      return;
5818    }
5819    this.#altText.data = data;
5820  }
5821  get guessedAltText() {
5822    return this.#altText?.guessedText;
5823  }
5824  async setGuessedAltText(text) {
5825    await this.#altText?.setGuessedText(text);
5826  }
5827  serializeAltText(isForCopying) {
5828    return this.#altText?.serialize(isForCopying);
5829  }
5830  hasAltText() {
5831    return !!this.#altText && !this.#altText.isEmpty();
5832  }
5833  hasAltTextData() {
5834    return this.#altText?.hasData() ?? false;
5835  }
5836  focusCommentButton() {
5837    this.#comment?.focusButton();
5838  }
5839  addCommentButton() {
5840    return this.canAddComment ? this.#comment ||= new Comment(this) : null;
5841  }
5842  addStandaloneCommentButton() {
5843    if (!this._uiManager.hasCommentManager()) {
5844      return;
5845    }
5846    if (this.#commentStandaloneButton) {
5847      if (this._uiManager.isEditingMode()) {
5848        this.#commentStandaloneButton.classList.remove("hidden");
5849      }
5850      return;
5851    }
5852    if (!this.hasComment) {
5853      return;
5854    }
5855    this.#commentStandaloneButton = this.#comment.renderForStandalone();
5856    this.div.append(this.#commentStandaloneButton);
5857  }
5858  removeStandaloneCommentButton() {
5859    this.#comment.removeStandaloneCommentButton();
5860    this.#commentStandaloneButton = null;
5861  }
5862  hideStandaloneCommentButton() {
5863    this.#commentStandaloneButton?.classList.add("hidden");
5864  }
5865  get comment() {
5866    if (!this.#comment) {
5867      return null;
5868    }
5869    const {
5870      data: {
5871        richText,
5872        text,
5873        date,
5874        deleted
5875      }
5876    } = this.#comment;
5877    return {
5878      text,
5879      richText,
5880      date,
5881      deleted,
5882      color: this.getNonHCMColor(),
5883      opacity: this.opacity ?? 1
5884    };
5885  }
5886  set comment(value) {
5887    this.#comment ||= new Comment(this);
5888    if (typeof value === "object" && value !== null) {
5889      this.#comment.restoreData(value);
5890    } else {
5891      this.#comment.data = value;
5892    }
5893    if (this.hasComment) {
5894      this.removeCommentButtonFromToolbar();
5895      this.addStandaloneCommentButton();
5896      this._uiManager.updateComment(this);
5897    } else {
5898      this.addCommentButtonInToolbar();
5899      this.removeStandaloneCommentButton();
5900      this._uiManager.removeComment(this);
5901    }
5902  }
5903  setCommentData({
5904    comment,
5905    popupRef,
5906    richText
5907  }) {
5908    if (!popupRef) {
5909      return;
5910    }
5911    this.#comment ||= new Comment(this);
5912    this.#comment.setInitialText(comment, richText);
5913    if (!this.annotationElementId) {
5914      return;
5915    }
5916    const storedData = this._uiManager.getAndRemoveDataFromAnnotationStorage(this.annotationElementId);
5917    if (storedData) {
5918      this.updateFromAnnotationLayer(storedData);
5919    }
5920  }
5921  get hasEditedComment() {
5922    return this.#comment?.hasBeenEdited();
5923  }
5924  get hasDeletedComment() {
5925    return this.#comment?.isDeleted();
5926  }
5927  get hasComment() {
5928    return !!this.#comment && !this.#comment.isEmpty() && !this.#comment.isDeleted();
5929  }
5930  async editComment(options) {
5931    this.#comment ||= new Comment(this);
5932    this.#comment.edit(options);
5933  }
5934  toggleComment(isSelected, visibility = undefined) {
5935    if (this.hasComment) {
5936      this._uiManager.toggleComment(this, isSelected, visibility);
5937    }
5938  }
5939  setSelectedCommentButton(selected) {
5940    this.#comment.setSelectedButton(selected);
5941  }
5942  addComment(serialized) {
5943    if (this.hasEditedComment) {
5944      const DEFAULT_POPUP_WIDTH = 180;
5945      const DEFAULT_POPUP_HEIGHT = 100;
5946      const [,,, trY] = serialized.rect;
5947      const [pageWidth] = this.pageDimensions;
5948      const [pageX] = this.pageTranslation;
5949      const blX = pageX + pageWidth + 1;
5950      const blY = trY - DEFAULT_POPUP_HEIGHT;
5951      const trX = blX + DEFAULT_POPUP_WIDTH;
5952      serialized.popup = {
5953        contents: this.comment.text,
5954        deleted: this.comment.deleted,
5955        rect: [blX, blY, trX, trY]
5956      };
5957    }
5958  }
5959  updateFromAnnotationLayer({
5960    popup: {
5961      contents,
5962      deleted
5963    }
5964  }) {
5965    this.#comment.data = deleted ? null : contents;
5966  }
5967  get parentBoundingClientRect() {
5968    return this.parent.boundingClientRect;
5969  }
5970  render() {
5971    const div = this.div = document.createElement("div");
5972    div.setAttribute("data-editor-rotation", (360 - this.rotation) % 360);
5973    div.className = this.name;
5974    div.setAttribute("id", this.id);
5975    div.tabIndex = this.#disabled ? -1 : 0;
5976    div.setAttribute("role", "application");
5977    if (this.defaultL10nId) {
5978      div.setAttribute("data-l10n-id", this.defaultL10nId);
5979    }
5980    if (!this._isVisible) {
5981      div.classList.add("hidden");
5982    }
5983    this.setInForeground();
5984    this.#addFocusListeners();
5985    const [parentWidth, parentHeight] = this.parentDimensions;
5986    if (this.parentRotation % 180 !== 0) {
5987      div.style.maxWidth = `${(100 * parentHeight / parentWidth).toFixed(2)}%`;
5988      div.style.maxHeight = `${(100 * parentWidth / parentHeight).toFixed(2)}%`;
5989    }
5990    const [tx, ty] = this.getInitialTranslation();
5991    this.translate(tx, ty);
5992    bindEvents(this, div, ["keydown", "pointerdown", "dblclick"]);
5993    if (this.isResizable && this._uiManager._supportsPinchToZoom) {
5994      this.#touchManager ||= new TouchManager({
5995        container: div,
5996        isPinchingDisabled: () => !this.isSelected,
5997        onPinchStart: this.#touchPinchStartCallback.bind(this),
5998        onPinching: this.#touchPinchCallback.bind(this),
5999        onPinchEnd: this.#touchPinchEndCallback.bind(this),
6000        signal: this._uiManager._signal
6001      });
6002    }
6003    this.addStandaloneCommentButton();
6004    this._uiManager._editorUndoBar?.hide();
6005    return div;
6006  }
6007  #touchPinchStartCallback() {
6008    this.#savedDimensions = {
6009      savedX: this.x,
6010      savedY: this.y,
6011      savedWidth: this.width,
6012      savedHeight: this.height
6013    };
6014    this.#altText?.toggle(false);
6015    this.parent.togglePointerEvents(false);
6016  }
6017  #touchPinchCallback(_origin, prevDistance, distance) {
6018    const slowDownFactor = 0.7;
6019    let factor = slowDownFactor * (distance / prevDistance) + 1 - slowDownFactor;
6020    if (factor === 1) {
6021      return;
6022    }
6023    const rotationMatrix = this.#getRotationMatrix(this.rotation);
6024    const transf = (x, y) => [rotationMatrix[0] * x + rotationMatrix[2] * y, rotationMatrix[1] * x + rotationMatrix[3] * y];
6025    const [parentWidth, parentHeight] = this.parentDimensions;
6026    const savedX = this.x;
6027    const savedY = this.y;
6028    const savedWidth = this.width;
6029    const savedHeight = this.height;
6030    const minWidth = AnnotationEditor.MIN_SIZE / parentWidth;
6031    const minHeight = AnnotationEditor.MIN_SIZE / parentHeight;
6032    factor = Math.max(Math.min(factor, 1 / savedWidth, 1 / savedHeight), minWidth / savedWidth, minHeight / savedHeight);
6033    const newWidth = AnnotationEditor._round(savedWidth * factor);
6034    const newHeight = AnnotationEditor._round(savedHeight * factor);
6035    if (newWidth === savedWidth && newHeight === savedHeight) {
6036      return;
6037    }
6038    this.#initialRect ||= [savedX, savedY, savedWidth, savedHeight];
6039    const transfCenterPoint = transf(savedWidth / 2, savedHeight / 2);
6040    const centerX = AnnotationEditor._round(savedX + transfCenterPoint[0]);
6041    const centerY = AnnotationEditor._round(savedY + transfCenterPoint[1]);
6042    const newTransfCenterPoint = transf(newWidth / 2, newHeight / 2);
6043    this.x = centerX - newTransfCenterPoint[0];
6044    this.y = centerY - newTransfCenterPoint[1];
6045    this.width = newWidth;
6046    this.height = newHeight;
6047    this.setDims();
6048    this.fixAndSetPosition();
6049    this._onResizing();
6050  }
6051  #touchPinchEndCallback() {
6052    this.#altText?.toggle(true);
6053    this.parent.togglePointerEvents(true);
6054    this.#addResizeToUndoStack();
6055  }
6056  pointerdown(event) {
6057    const {
6058      isMac
6059    } = util_FeatureTest.platform;
6060    if (event.button !== 0 || event.ctrlKey && isMac) {
6061      event.preventDefault();
6062      return;
6063    }
6064    this.#hasBeenClicked = true;
6065    if (this._isDraggable) {
6066      this.#setUpDragSession(event);
6067      return;
6068    }
6069    this.#selectOnPointerEvent(event);
6070  }
6071  #selectOnPointerEvent(event) {
6072    const {
6073      isMac
6074    } = util_FeatureTest.platform;
6075    if (event.ctrlKey && !isMac || event.shiftKey || event.metaKey && isMac) {
6076      this.parent.toggleSelected(this);
6077    } else {
6078      this.parent.setSelected(this);
6079    }
6080  }
6081  #setUpDragSession(event) {
6082    const {
6083      isSelected
6084    } = this;
6085    this._uiManager.setUpDragSession();
6086    let hasDraggingStarted = false;
6087    const ac = new AbortController();
6088    const signal = this._uiManager.combinedSignal(ac);
6089    const opts = {
6090      capture: true,
6091      passive: false,
6092      signal
6093    };
6094    const cancelDrag = e => {
6095      ac.abort();
6096      this.#dragPointerId = null;
6097      this.#hasBeenClicked = false;
6098      if (!this._uiManager.endDragSession()) {
6099        this.#selectOnPointerEvent(e);
6100      }
6101      if (hasDraggingStarted) {
6102        this._onStopDragging();
6103      }
6104    };
6105    if (isSelected) {
6106      this.#prevDragX = event.clientX;
6107      this.#prevDragY = event.clientY;
6108      this.#dragPointerId = event.pointerId;
6109      this.#dragPointerType = event.pointerType;
6110      window.addEventListener("pointermove", e => {
6111        if (!hasDraggingStarted) {
6112          hasDraggingStarted = true;
6113          this._uiManager.toggleComment(this, true, false);
6114          this._onStartDragging();
6115        }
6116        const {
6117          clientX: x,
6118          clientY: y,
6119          pointerId
6120        } = e;
6121        if (pointerId !== this.#dragPointerId) {
6122          stopEvent(e);
6123          return;
6124        }
6125        const [tx, ty] = this.screenToPageTranslation(x - this.#prevDragX, y - this.#prevDragY);
6126        this.#prevDragX = x;
6127        this.#prevDragY = y;
6128        this._uiManager.dragSelectedEditors(tx, ty);
6129      }, opts);
6130      window.addEventListener("touchmove", stopEvent, opts);
6131      window.addEventListener("pointerdown", e => {
6132        if (e.pointerType === this.#dragPointerType) {
6133          if (this.#touchManager || e.isPrimary) {
6134            cancelDrag(e);
6135          }
6136        }
6137        stopEvent(e);
6138      }, opts);
6139    }
6140    const pointerUpCallback = e => {
6141      if (!this.#dragPointerId || this.#dragPointerId === e.pointerId) {
6142        cancelDrag(e);
6143        return;
6144      }
6145      stopEvent(e);
6146    };
6147    window.addEventListener("pointerup", pointerUpCallback, {
6148      signal
6149    });
6150    window.addEventListener("blur", pointerUpCallback, {
6151      signal
6152    });
6153  }
6154  _onStartDragging() {}
6155  _onStopDragging() {}
6156  moveInDOM() {
6157    if (this.#moveInDOMTimeout) {
6158      clearTimeout(this.#moveInDOMTimeout);
6159    }
6160    this.#moveInDOMTimeout = setTimeout(() => {
6161      this.#moveInDOMTimeout = null;
6162      this.parent?.moveEditorInDOM(this);
6163    }, 0);
6164  }
6165  _setParentAndPosition(parent, x, y) {
6166    parent.changeParent(this);
6167    this.x = x;
6168    this.y = y;
6169    this.fixAndSetPosition();
6170    this._onTranslated();
6171  }
6172  getRect(tx, ty, rotation = this.rotation) {
6173    const scale = this.parentScale;
6174    const [pageWidth, pageHeight] = this.pageDimensions;
6175    const [pageX, pageY] = this.pageTranslation;
6176    const shiftX = tx / scale;
6177    const shiftY = ty / scale;
6178    const x = this.x * pageWidth;
6179    const y = this.y * pageHeight;
6180    const width = this.width * pageWidth;
6181    const height = this.height * pageHeight;
6182    switch (rotation) {
6183      case 0:
6184        return [x + shiftX + pageX, pageHeight - y - shiftY - height + pageY, x + shiftX + width + pageX, pageHeight - y - shiftY + pageY];
6185      case 90:
6186        return [x + shiftY + pageX, pageHeight - y + shiftX + pageY, x + shiftY + height + pageX, pageHeight - y + shiftX + width + pageY];
6187      case 180:
6188        return [x - shiftX - width + pageX, pageHeight - y + shiftY + pageY, x - shiftX + pageX, pageHeight - y + shiftY + height + pageY];
6189      case 270:
6190        return [x - shiftY - height + pageX, pageHeight - y - shiftX - width + pageY, x - shiftY + pageX, pageHeight - y - shiftX + pageY];
6191      default:
6192        throw new Error("Invalid rotation");
6193    }
6194  }
6195  getRectInCurrentCoords(rect, pageHeight) {
6196    const [x1, y1, x2, y2] = rect;
6197    const width = x2 - x1;
6198    const height = y2 - y1;
6199    switch (this.rotation) {
6200      case 0:
6201        return [x1, pageHeight - y2, width, height];
6202      case 90:
6203        return [x1, pageHeight - y1, height, width];
6204      case 180:
6205        return [x2, pageHeight - y1, width, height];
6206      case 270:
6207        return [x2, pageHeight - y2, height, width];
6208      default:
6209        throw new Error("Invalid rotation");
6210    }
6211  }
6212  getPDFRect() {
6213    return this.getRect(0, 0);
6214  }
6215  getNonHCMColor() {
6216    return this.color && AnnotationEditor._colorManager.convert(this._uiManager.getNonHCMColor(this.color));
6217  }
6218  onUpdatedColor() {
6219    this.#comment?.onUpdatedColor();
6220  }
6221  getData() {
6222    const {
6223      comment: {
6224        text: str,
6225        color,
6226        date,
6227        opacity,
6228        deleted,
6229        richText
6230      },
6231      uid: id,
6232      pageIndex,
6233      creationDate,
6234      modificationDate
6235    } = this;
6236    return {
6237      id,
6238      pageIndex,
6239      rect: this.getPDFRect(),
6240      richText,
6241      contentsObj: {
6242        str
6243      },
6244      creationDate,
6245      modificationDate: date || modificationDate,
6246      popupRef: !deleted,
6247      color,
6248      opacity
6249    };
6250  }
6251  onceAdded(focus) {}
6252  isEmpty() {
6253    return false;
6254  }
6255  enableEditMode() {
6256    if (this.isInEditMode()) {
6257      return false;
6258    }
6259    this.parent.setEditingState(false);
6260    this.#isInEditMode = true;
6261    return true;
6262  }
6263  disableEditMode() {
6264    if (!this.isInEditMode()) {
6265      return false;
6266    }
6267    this.parent.setEditingState(true);
6268    this.#isInEditMode = false;
6269    return true;
6270  }
6271  isInEditMode() {
6272    return this.#isInEditMode;
6273  }
6274  shouldGetKeyboardEvents() {
6275    return this.#isResizerEnabledForKeyboard;
6276  }
6277  needsToBeRebuilt() {
6278    return this.div && !this.isAttachedToDOM;
6279  }
6280  get isOnScreen() {
6281    const {
6282      top,
6283      left,
6284      bottom,
6285      right
6286    } = this.getClientDimensions();
6287    const {
6288      innerHeight,
6289      innerWidth
6290    } = window;
6291    return left < innerWidth && right > 0 && top < innerHeight && bottom > 0;
6292  }
6293  #addFocusListeners() {
6294    if (this.#focusAC || !this.div) {
6295      return;
6296    }
6297    this.#focusAC = new AbortController();
6298    const signal = this._uiManager.combinedSignal(this.#focusAC);
6299    this.div.addEventListener("focusin", this.focusin.bind(this), {
6300      signal
6301    });
6302    this.div.addEventListener("focusout", this.focusout.bind(this), {
6303      signal
6304    });
6305  }
6306  rebuild() {
6307    this.#addFocusListeners();
6308  }
6309  rotate(_angle) {}
6310  resize() {}
6311  serializeDeleted() {
6312    return {
6313      id: this.annotationElementId,
6314      deleted: true,
6315      pageIndex: this.pageIndex,
6316      popupRef: this._initialData?.popupRef || ""
6317    };
6318  }
6319  serialize(isForCopying = false, context = null) {
6320    return {
6321      annotationType: this.mode,
6322      pageIndex: this.pageIndex,
6323      rect: this.getPDFRect(),
6324      rotation: this.rotation,
6325      structTreeParentId: this._structTreeParentId,
6326      popupRef: this._initialData?.popupRef || ""
6327    };
6328  }
6329  static async deserialize(data, parent, uiManager) {
6330    const editor = new this.prototype.constructor({
6331      parent,
6332      id: parent.getNextId(),
6333      uiManager,
6334      annotationElementId: data.annotationElementId,
6335      creationDate: data.creationDate,
6336      modificationDate: data.modificationDate
6337    });
6338    editor.rotation = data.rotation;
6339    editor.#accessibilityData = data.accessibilityData;
6340    editor._isCopy = data.isCopy || false;
6341    const [pageWidth, pageHeight] = editor.pageDimensions;
6342    const [x, y, width, height] = editor.getRectInCurrentCoords(data.rect, pageHeight);
6343    editor.x = x / pageWidth;
6344    editor.y = y / pageHeight;
6345    editor.width = width / pageWidth;
6346    editor.height = height / pageHeight;
6347    return editor;
6348  }
6349  get hasBeenModified() {
6350    return !!this.annotationElementId && (this.deleted || this.serialize() !== null);
6351  }
6352  remove() {
6353    this.#focusAC?.abort();
6354    this.#focusAC = null;
6355    if (!this.isEmpty()) {
6356      this.commit();
6357    }
6358    if (this.parent) {
6359      this.parent.remove(this);
6360    } else {
6361      this._uiManager.removeEditor(this);
6362    }
6363    this.hideCommentPopup();
6364    if (this.#moveInDOMTimeout) {
6365      clearTimeout(this.#moveInDOMTimeout);
6366      this.#moveInDOMTimeout = null;
6367    }
6368    this.#stopResizing();
6369    this.removeEditToolbar();
6370    if (this.#telemetryTimeouts) {
6371      for (const timeout of this.#telemetryTimeouts.values()) {
6372        clearTimeout(timeout);
6373      }
6374      this.#telemetryTimeouts = null;
6375    }
6376    this.parent = null;
6377    this.#touchManager?.destroy();
6378    this.#touchManager
vendor: 12,923 bytes, lines 6378-6841
6378 = null;
6379    this.#fakeAnnotation?.remove();
6380    this.#fakeAnnotation = null;
6381  }
6382  get isResizable() {
6383    return false;
6384  }
6385  makeResizable() {
6386    if (this.isResizable) {
6387      this.#createResizers();
6388      this.#resizersDiv.classList.remove("hidden");
6389    }
6390  }
6391  get toolbarPosition() {
6392    return null;
6393  }
6394  get commentButtonPosition() {
6395    return this._uiManager.direction === "ltr" ? [1, 0] : [0, 0];
6396  }
6397  get commentButtonPositionInPage() {
6398    const {
6399      commentButtonPosition: [posX, posY]
6400    } = this;
6401    const [blX, blY, trX, trY] = this.getPDFRect();
6402    return [AnnotationEditor._round(blX + (trX - blX) * posX), AnnotationEditor._round(blY + (trY - blY) * (1 - posY))];
6403  }
6404  get commentButtonColor() {
6405    return this._uiManager.makeCommentColor(this.getNonHCMColor(), this.opacity);
6406  }
6407  get commentPopupPosition() {
6408    return this.#comment.commentPopupPositionInLayer;
6409  }
6410  set commentPopupPosition(pos) {
6411    this.#comment.commentPopupPositionInLayer = pos;
6412  }
6413  hasDefaultPopupPosition() {
6414    return this.#comment.hasDefaultPopupPosition();
6415  }
6416  get commentButtonWidth() {
6417    return this.#comment.commentButtonWidth;
6418  }
6419  get elementBeforePopup() {
6420    return this.div;
6421  }
6422  setCommentButtonStates(options) {
6423    this.#comment?.setCommentButtonStates(options);
6424  }
6425  keydown(event) {
6426    if (!this.isResizable || event.target !== this.div || event.key !== "Enter") {
6427      return;
6428    }
6429    this._uiManager.setSelected(this);
6430    this.#savedDimensions = {
6431      savedX: this.x,
6432      savedY: this.y,
6433      savedWidth: this.width,
6434      savedHeight: this.height
6435    };
6436    const children = this.#resizersDiv.children;
6437    if (!this.#allResizerDivs) {
6438      this.#allResizerDivs = Array.from(children);
6439      const boundResizerKeydown = this.#resizerKeydown.bind(this);
6440      const boundResizerBlur = this.#resizerBlur.bind(this);
6441      const signal = this._uiManager._signal;
6442      for (const div of this.#allResizerDivs) {
6443        const name = div.getAttribute("data-resizer-name");
6444        div.setAttribute("role", "spinbutton");
6445        div.addEventListener("keydown", boundResizerKeydown, {
6446          signal
6447        });
6448        div.addEventListener("blur", boundResizerBlur, {
6449          signal
6450        });
6451        div.addEventListener("focus", this.#resizerFocus.bind(this, name), {
6452          signal
6453        });
6454        div.setAttribute("data-l10n-id", AnnotationEditor._l10nResizer[name]);
6455      }
6456    }
6457    const first = this.#allResizerDivs[0];
6458    let firstPosition = 0;
6459    for (const div of children) {
6460      if (div === first) {
6461        break;
6462      }
6463      firstPosition++;
6464    }
6465    const nextFirstPosition = (360 - this.rotation + this.parentRotation) % 360 / 90 * (this.#allResizerDivs.length / 4);
6466    if (nextFirstPosition !== firstPosition) {
6467      if (nextFirstPosition < firstPosition) {
6468        for (let i = 0; i < firstPosition - nextFirstPosition; i++) {
6469          this.#resizersDiv.append(this.#resizersDiv.firstElementChild);
6470        }
6471      } else if (nextFirstPosition > firstPosition) {
6472        for (let i = 0; i < nextFirstPosition - firstPosition; i++) {
6473          this.#resizersDiv.firstElementChild.before(this.#resizersDiv.lastElementChild);
6474        }
6475      }
6476      let i = 0;
6477      for (const child of children) {
6478        const div = this.#allResizerDivs[i++];
6479        const name = div.getAttribute("data-resizer-name");
6480        child.setAttribute("data-l10n-id", AnnotationEditor._l10nResizer[name]);
6481      }
6482    }
6483    this.#setResizerTabIndex(0);
6484    this.#isResizerEnabledForKeyboard = true;
6485    this.#resizersDiv.firstElementChild.focus({
6486      focusVisible: true
6487    });
6488    event.preventDefault();
6489    event.stopImmediatePropagation();
6490  }
6491  #resizerKeydown(event) {
6492    AnnotationEditor._resizerKeyboardManager.exec(this, event);
6493  }
6494  #resizerBlur(event) {
6495    if (this.#isResizerEnabledForKeyboard && event.relatedTarget?.parentNode !== this.#resizersDiv) {
6496      this.#stopResizing();
6497    }
6498  }
6499  #resizerFocus(name) {
6500    this.#focusedResizerName = this.#isResizerEnabledForKeyboard ? name : "";
6501  }
6502  #setResizerTabIndex(value) {
6503    if (!this.#allResizerDivs) {
6504      return;
6505    }
6506    for (const div of this.#allResizerDivs) {
6507      div.tabIndex = value;
6508    }
6509  }
6510  _resizeWithKeyboard(x, y) {
6511    if (!this.#isResizerEnabledForKeyboard) {
6512      return;
6513    }
6514    this.#resizerPointermove(this.#focusedResizerName, {
6515      deltaX: x,
6516      deltaY: y,
6517      fromKeyboard: true
6518    });
6519  }
6520  #stopResizing() {
6521    this.#isResizerEnabledForKeyboard = false;
6522    this.#setResizerTabIndex(-1);
6523    this.#addResizeToUndoStack();
6524  }
6525  _stopResizingWithKeyboard() {
6526    this.#stopResizing();
6527    this.div.focus();
6528  }
6529  select() {
6530    if (this.isSelected && this._editToolbar) {
6531      this._editToolbar.show();
6532      return;
6533    }
6534    this.isSelected = true;
6535    this.makeResizable();
6536    this.div?.classList.add("selectedEditor");
6537    if (!this._editToolbar) {
6538      this.addEditToolbar().then(() => {
6539        if (this.div?.classList.contains("selectedEditor")) {
6540          this._editToolbar?.show();
6541        }
6542      });
6543      return;
6544    }
6545    this._editToolbar?.show();
6546    this.#altText?.toggleAltTextBadge(false);
6547  }
6548  focus() {
6549    if (this.div && !this.div.contains(document.activeElement)) {
6550      setTimeout(() => this.div?.focus({
6551        preventScroll: true
6552      }), 0);
6553    }
6554  }
6555  unselect() {
6556    if (!this.isSelected) {
6557      return;
6558    }
6559    this.isSelected = false;
6560    this.#resizersDiv?.classList.add("hidden");
6561    this.div?.classList.remove("selectedEditor");
6562    if (this.div?.contains(document.activeElement)) {
6563      this._uiManager.currentLayer.div.focus({
6564        preventScroll: true
6565      });
6566    }
6567    this._editToolbar?.hide();
6568    this.#altText?.toggleAltTextBadge(true);
6569    this.hideCommentPopup();
6570  }
6571  hideCommentPopup() {
6572    if (this.hasComment) {
6573      this._uiManager.toggleComment(null);
6574    }
6575  }
6576  updateParams(type, value) {}
6577  disableEditing() {}
6578  enableEditing() {}
6579  get canChangeContent() {
6580    return false;
6581  }
6582  enterInEditMode() {
6583    if (!this.canChangeContent) {
6584      return;
6585    }
6586    this.enableEditMode();
6587    this.div.focus();
6588  }
6589  dblclick(event) {
6590    if (event.target.nodeName === "BUTTON") {
6591      return;
6592    }
6593    this.enterInEditMode();
6594    this.parent.updateToolbar({
6595      mode: this.constructor._editorType,
6596      editId: this.uid
6597    });
6598  }
6599  getElementForAltText() {
6600    return this.div;
6601  }
6602  get contentDiv() {
6603    return this.div;
6604  }
6605  get isEditing() {
6606    return this.#isEditing;
6607  }
6608  set isEditing(value) {
6609    this.#isEditing = value;
6610    if (!this.parent) {
6611      return;
6612    }
6613    if (value) {
6614      this.parent.setSelected(this);
6615      this.parent.setActiveEditor(this);
6616    } else {
6617      this.parent.setActiveEditor(null);
6618    }
6619  }
6620  static get MIN_SIZE() {
6621    return 16;
6622  }
6623  static canCreateNewEmptyEditor() {
6624    return true;
6625  }
6626  get telemetryInitialData() {
6627    return {
6628      action: "added"
6629    };
6630  }
6631  get telemetryFinalData() {
6632    return null;
6633  }
6634  _reportTelemetry(data, mustWait = false) {
6635    if (mustWait) {
6636      this.#telemetryTimeouts ||= new Map();
6637      const {
6638        action
6639      } = data;
6640      let timeout = this.#telemetryTimeouts.get(action);
6641      if (timeout) {
6642        clearTimeout(timeout);
6643      }
6644      timeout = setTimeout(() => {
6645        this._reportTelemetry(data);
6646        this.#telemetryTimeouts.delete(action);
6647        if (this.#telemetryTimeouts.size === 0) {
6648          this.#telemetryTimeouts = null;
6649        }
6650      }, AnnotationEditor._telemetryTimeout);
6651      this.#telemetryTimeouts.set(action, timeout);
6652      return;
6653    }
6654    data.type ||= this.editorType;
6655    this._uiManager._eventBus.dispatch("reporttelemetry", {
6656      source: this,
6657      details: {
6658        type: "editing",
6659        data
6660      }
6661    });
6662  }
6663  show(visible = this._isVisible) {
6664    this.div.classList.toggle("hidden", !visible);
6665    this._isVisible = visible;
6666  }
6667  enable() {
6668    if (this.div) {
6669      this.div.tabIndex = 0;
6670    }
6671    this.#disabled = false;
6672  }
6673  disable() {
6674    if (this.div) {
6675      this.div.tabIndex = -1;
6676    }
6677    this.#disabled = true;
6678  }
6679  updateFakeAnnotationElement(annotationLayer) {
6680    if (!this.#fakeAnnotation && !this.deleted) {
6681      this.#fakeAnnotation = annotationLayer.addFakeAnnotation(this);
6682      return;
6683    }
6684    if (this.deleted) {
6685      this.#fakeAnnotation.remove();
6686      this.#fakeAnnotation = null;
6687      return;
6688    }
6689    if (this.hasEditedComment || this._hasBeenMoved || this._hasBeenResized) {
6690      this.#fakeAnnotation.updateEdited({
6691        rect: this.getPDFRect(),
6692        popup: this.comment
6693      });
6694    }
6695  }
6696  renderAnnotationElement(annotation) {
6697    if (this.deleted) {
6698      annotation.hide();
6699      return null;
6700    }
6701    let content = annotation.container.querySelector(".annotationContent");
6702    if (!content) {
6703      content = document.createElement("div");
6704      content.classList.add("annotationContent", this.editorType);
6705      annotation.container.prepend(content);
6706    } else if (content.nodeName === "CANVAS") {
6707      const canvas = content;
6708      content = document.createElement("div");
6709      content.classList.add("annotationContent", this.editorType);
6710      canvas.before(content);
6711    }
6712    return content;
6713  }
6714  resetAnnotationElement(annotation) {
6715    const {
6716      firstElementChild
6717    } = annotation.container;
6718    if (firstElementChild?.nodeName === "DIV" && firstElementChild.classList.contains("annotationContent")) {
6719      firstElementChild.remove();
6720    }
6721  }
6722}
6723class FakeEditor extends AnnotationEditor {
6724  constructor(params) {
6725    super(params);
6726    this.annotationElementId = params.annotationElementId;
6727    this.deleted = true;
6728  }
6729  serialize() {
6730    return this.serializeDeleted();
6731  }
6732}
6733
6734;// ./src/shared/murmurhash3.js
6735const SEED = 0xc3d2e1f0;
6736const MASK_HIGH = 0xffff0000;
6737const MASK_LOW = 0xffff;
6738class MurmurHash3_64 {
6739  constructor(seed) {
6740    this.h1 = seed ? seed & 0xffffffff : SEED;
6741    this.h2 = seed ? seed & 0xffffffff : SEED;
6742  }
6743  update(input) {
6744    let data, length;
6745    if (typeof input === "string") {
6746      data = new Uint8Array(input.length * 2);
6747      length = 0;
6748      for (let i = 0, ii = input.length; i < ii; i++) {
6749        const code = input.charCodeAt(i);
6750        if (code <= 0xff) {
6751          data[length++] = code;
6752        } else {
6753          data[length++] = code >>> 8;
6754          data[length++] = code & 0xff;
6755        }
6756      }
6757    } else if (ArrayBuffer.isView(input)) {
6758      data = input.slice();
6759      length = data.byteLength;
6760    } else {
6761      throw new Error("Invalid data format, must be a string or TypedArray.");
6762    }
6763    const blockCounts = length >> 2;
6764    const tailLength = length - blockCounts * 4;
6765    const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts);
6766    let k1 = 0,
6767      k2 = 0;
6768    let h1 = this.h1,
6769      h2 = this.h2;
6770    const C1 = 0xcc9e2d51,
6771      C2 = 0x1b873593;
6772    const C1_LOW = C1 & MASK_LOW,
6773      C2_LOW = C2 & MASK_LOW;
6774    for (let i = 0; i < blockCounts; i++) {
6775      if (i & 1) {
6776        k1 = dataUint32[i];
6777        k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
6778        k1 = k1 << 15 | k1 >>> 17;
6779        k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
6780        h1 ^= k1;
6781        h1 = h1 << 13 | h1 >>> 19;
6782        h1 = h1 * 5 + 0xe6546b64;
6783      } else {
6784        k2 = dataUint32[i];
6785        k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW;
6786        k2 = k2 << 15 | k2 >>> 17;
6787        k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW;
6788        h2 ^= k2;
6789        h2 = h2 << 13 | h2 >>> 19;
6790        h2 = h2 * 5 + 0xe6546b64;
6791      }
6792    }
6793    k1 = 0;
6794    switch (tailLength) {
6795      case 3:
6796        k1 ^= data[blockCounts * 4 + 2] << 16;
6797      case 2:
6798        k1 ^= data[blockCounts * 4 + 1] << 8;
6799      case 1:
6800        k1 ^= data[blockCounts * 4];
6801        k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
6802        k1 = k1 << 15 | k1 >>> 17;
6803        k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
6804        if (blockCounts & 1) {
6805          h1 ^= k1;
6806        } else {
6807          h2 ^= k1;
6808        }
6809    }
6810    this.h1 = h1;
6811    this.h2 = h2;
6812  }
6813  hexdigest() {
6814    let h1 = this.h1,
6815      h2 = this.h2;
6816    h1 ^= h2 >>> 1;
6817    h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW;
6818    h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16;
6819    h1 ^= h2 >>> 1;
6820    h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW;
6821    h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16;
6822    h1 ^= h2 >>> 1;
6823    return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0");
6824  }
6825}
6826
6827;// ./src/display/annotation_storage.js
6828
6829
6830
6831const SerializableEmpty = Object.freeze({
6832  map: null,
6833  hash: "",
6834  transfer: undefined
6835});
6836class AnnotationStorage {
6837  #modified = false;
6838  #modifiedIds = null;
6839  #editorsMap = null;
6840  #storage = new Map();
6841  
vendor: 18,603 bytes, lines 6841-7451
6841constructor() {
6842    this.onSetModified = null;
6843    this.onResetModified = null;
6844    this.onAnnotationEditor = null;
6845  }
6846  getValue(key, defaultValue) {
6847    const value = this.#storage.get(key);
6848    if (value === undefined) {
6849      return defaultValue;
6850    }
6851    return Object.assign(defaultValue, value);
6852  }
6853  getRawValue(key) {
6854    return this.#storage.get(key);
6855  }
6856  remove(key) {
6857    const storedValue = this.#storage.get(key);
6858    if (storedValue === undefined) {
6859      return;
6860    }
6861    if (storedValue instanceof AnnotationEditor) {
6862      this.#editorsMap.delete(storedValue.annotationElementId);
6863    }
6864    this.#storage.delete(key);
6865    if (this.#storage.size === 0) {
6866      this.resetModified();
6867    }
6868    if (typeof this.onAnnotationEditor === "function") {
6869      for (const value of this.#storage.values()) {
6870        if (value instanceof AnnotationEditor) {
6871          return;
6872        }
6873      }
6874      this.onAnnotationEditor(null);
6875    }
6876  }
6877  setValue(key, value) {
6878    const obj = this.#storage.get(key);
6879    let modified = false;
6880    if (obj !== undefined) {
6881      for (const [entry, val] of Object.entries(value)) {
6882        if (obj[entry] !== val) {
6883          modified = true;
6884          obj[entry] = val;
6885        }
6886      }
6887    } else {
6888      modified = true;
6889      this.#storage.set(key, value);
6890    }
6891    if (modified) {
6892      this.#setModified();
6893    }
6894    if (value instanceof AnnotationEditor) {
6895      (this.#editorsMap ||= new Map()).set(value.annotationElementId, value);
6896      if (typeof this.onAnnotationEditor === "function") {
6897        this.onAnnotationEditor(value.constructor._type);
6898      }
6899    }
6900  }
6901  has(key) {
6902    return this.#storage.has(key);
6903  }
6904  get size() {
6905    return this.#storage.size;
6906  }
6907  #setModified() {
6908    if (!this.#modified) {
6909      this.#modified = true;
6910      if (typeof this.onSetModified === "function") {
6911        this.onSetModified();
6912      }
6913    }
6914  }
6915  resetModified() {
6916    if (this.#modified) {
6917      this.#modified = false;
6918      if (typeof this.onResetModified === "function") {
6919        this.onResetModified();
6920      }
6921    }
6922  }
6923  get print() {
6924    return new PrintAnnotationStorage(this);
6925  }
6926  get serializable() {
6927    if (this.#storage.size === 0) {
6928      return SerializableEmpty;
6929    }
6930    const map = new Map(),
6931      hash = new MurmurHash3_64(),
6932      transfer = [];
6933    const context = Object.create(null);
6934    let hasBitmap = false;
6935    for (const [key, val] of this.#storage) {
6936      const serialized = val instanceof AnnotationEditor ? val.serialize(false, context) : val;
6937      if (val.page) {
6938        val.pageIndex = val.page._pageIndex;
6939        delete val.page;
6940      }
6941      if (serialized) {
6942        map.set(key, serialized);
6943        hash.update(`${key}:${JSON.stringify(serialized)}`);
6944        hasBitmap ||= !!serialized.bitmap;
6945      }
6946    }
6947    if (hasBitmap) {
6948      for (const value of map.values()) {
6949        if (value.bitmap) {
6950          transfer.push(value.bitmap);
6951        }
6952      }
6953    }
6954    return map.size > 0 ? {
6955      map,
6956      hash: hash.hexdigest(),
6957      transfer
6958    } : SerializableEmpty;
6959  }
6960  get editorStats() {
6961    let stats = null;
6962    const typeToEditor = new Map();
6963    let numberOfEditedComments = 0;
6964    let numberOfDeletedComments = 0;
6965    for (const value of this.#storage.values()) {
6966      if (!(value instanceof AnnotationEditor)) {
6967        if (value.popup) {
6968          if (value.popup.deleted) {
6969            numberOfDeletedComments += 1;
6970          } else {
6971            numberOfEditedComments += 1;
6972          }
6973        }
6974        continue;
6975      }
6976      if (value.isCommentDeleted) {
6977        numberOfDeletedComments += 1;
6978      } else if (value.hasEditedComment) {
6979        numberOfEditedComments += 1;
6980      }
6981      const editorStats = value.telemetryFinalData;
6982      if (!editorStats) {
6983        continue;
6984      }
6985      const {
6986        type
6987      } = editorStats;
6988      if (!typeToEditor.has(type)) {
6989        typeToEditor.set(type, Object.getPrototypeOf(value).constructor);
6990      }
6991      stats ||= Object.create(null);
6992      const map = stats[type] ||= new Map();
6993      for (const [key, val] of Object.entries(editorStats)) {
6994        if (key === "type") {
6995          continue;
6996        }
6997        let counters = map.get(key);
6998        if (!counters) {
6999          counters = new Map();
7000          map.set(key, counters);
7001        }
7002        const count = counters.get(val) ?? 0;
7003        counters.set(val, count + 1);
7004      }
7005    }
7006    if (numberOfDeletedComments > 0 || numberOfEditedComments > 0) {
7007      stats ||= Object.create(null);
7008      stats.comments = {
7009        deleted: numberOfDeletedComments,
7010        edited: numberOfEditedComments
7011      };
7012    }
7013    if (!stats) {
7014      return null;
7015    }
7016    for (const [type, editor] of typeToEditor) {
7017      stats[type] = editor.computeTelemetryFinalData(stats[type]);
7018    }
7019    return stats;
7020  }
7021  resetModifiedIds() {
7022    this.#modifiedIds = null;
7023  }
7024  updateEditor(annotationId, data) {
7025    const value = this.#editorsMap?.get(annotationId);
7026    if (value) {
7027      value.updateFromAnnotationLayer(data);
7028      return true;
7029    }
7030    return false;
7031  }
7032  getEditor(annotationId) {
7033    return this.#editorsMap?.get(annotationId) || null;
7034  }
7035  get modifiedIds() {
7036    if (this.#modifiedIds) {
7037      return this.#modifiedIds;
7038    }
7039    const ids = [];
7040    if (this.#editorsMap) {
7041      for (const value of this.#editorsMap.values()) {
7042        if (!value.serialize()) {
7043          continue;
7044        }
7045        ids.push(value.annotationElementId);
7046      }
7047    }
7048    return this.#modifiedIds = {
7049      ids: new Set(ids),
7050      hash: ids.join(",")
7051    };
7052  }
7053  [Symbol.iterator]() {
7054    return this.#storage.entries();
7055  }
7056}
7057class PrintAnnotationStorage extends AnnotationStorage {
7058  #serializable;
7059  constructor(parent) {
7060    super();
7061    const {
7062      map,
7063      hash,
7064      transfer
7065    } = parent.serializable;
7066    const clone = structuredClone(map, transfer ? {
7067      transfer
7068    } : null);
7069    this.#serializable = {
7070      map: clone,
7071      hash,
7072      transfer
7073    };
7074  }
7075  get print() {
7076    unreachable("Should not call PrintAnnotationStorage.print");
7077  }
7078  get serializable() {
7079    return this.#serializable;
7080  }
7081  get modifiedIds() {
7082    return shadow(this, "modifiedIds", {
7083      ids: new Set(),
7084      hash: ""
7085    });
7086  }
7087}
7088
7089;// ./src/display/font_loader.js
7090
7091
7092class FontLoader {
7093  #systemFonts = new Set();
7094  constructor({
7095    ownerDocument = globalThis.document,
7096    styleElement = null
7097  }) {
7098    this._document = ownerDocument;
7099    this.nativeFontFaces = new Set();
7100    this.styleElement = null;
7101    this.loadingRequests = [];
7102    this.loadTestFontId = 0;
7103  }
7104  addNativeFontFace(nativeFontFace) {
7105    this.nativeFontFaces.add(nativeFontFace);
7106    this._document.fonts.add(nativeFontFace);
7107  }
7108  removeNativeFontFace(nativeFontFace) {
7109    this.nativeFontFaces.delete(nativeFontFace);
7110    this._document.fonts.delete(nativeFontFace);
7111  }
7112  insertRule(rule) {
7113    if (!this.styleElement) {
7114      this.styleElement = this._document.createElement("style");
7115      this._document.documentElement.getElementsByTagName("head")[0].append(this.styleElement);
7116    }
7117    const styleSheet = this.styleElement.sheet;
7118    styleSheet.insertRule(rule, styleSheet.cssRules.length);
7119  }
7120  clear() {
7121    for (const nativeFontFace of this.nativeFontFaces) {
7122      this._document.fonts.delete(nativeFontFace);
7123    }
7124    this.nativeFontFaces.clear();
7125    this.#systemFonts.clear();
7126    if (this.styleElement) {
7127      this.styleElement.remove();
7128      this.styleElement = null;
7129    }
7130  }
7131  async loadSystemFont({
7132    systemFontInfo: info,
7133    disableFontFace,
7134    _inspectFont
7135  }) {
7136    if (!info || this.#systemFonts.has(info.loadedName)) {
7137      return;
7138    }
7139    assert(!disableFontFace, "loadSystemFont shouldn't be called when `disableFontFace` is set.");
7140    if (this.isFontLoadingAPISupported) {
7141      const {
7142        loadedName,
7143        src,
7144        style
7145      } = info;
7146      const fontFace = new FontFace(loadedName, src, style);
7147      this.addNativeFontFace(fontFace);
7148      try {
7149        await fontFace.load();
7150        this.#systemFonts.add(loadedName);
7151        _inspectFont?.(info);
7152      } catch {
7153        warn(`Cannot load system font: ${info.baseFontName}, installing it could help to improve PDF rendering.`);
7154        this.removeNativeFontFace(fontFace);
7155      }
7156      return;
7157    }
7158    unreachable("Not implemented: loadSystemFont without the Font Loading API.");
7159  }
7160  async bind(font) {
7161    if (font.attached || font.missingFile && !font.systemFontInfo) {
7162      return;
7163    }
7164    font.attached = true;
7165    if (font.systemFontInfo) {
7166      await this.loadSystemFont(font);
7167      return;
7168    }
7169    if (this.isFontLoadingAPISupported) {
7170      const nativeFontFace = font.createNativeFontFace();
7171      if (nativeFontFace) {
7172        this.addNativeFontFace(nativeFontFace);
7173        try {
7174          await nativeFontFace.loaded;
7175        } catch (ex) {
7176          warn(`Failed to load font '${nativeFontFace.family}': '${ex}'.`);
7177          font.disableFontFace = true;
7178          throw ex;
7179        }
7180      }
7181      return;
7182    }
7183    const rule = font.createFontFaceRule();
7184    if (rule) {
7185      this.insertRule(rule);
7186      if (this.isSyncFontLoadingSupported) {
7187        return;
7188      }
7189      await new Promise(resolve => {
7190        const request = this._queueLoadingCallback(resolve);
7191        this._prepareFontLoadEvent(font, request);
7192      });
7193    }
7194  }
7195  get isFontLoadingAPISupported() {
7196    const hasFonts = !!this._document?.fonts;
7197    return shadow(this, "isFontLoadingAPISupported", hasFonts);
7198  }
7199  get isSyncFontLoadingSupported() {
7200    return shadow(this, "isSyncFontLoadingSupported", isNodeJS || util_FeatureTest.platform.isFirefox);
7201  }
7202  _queueLoadingCallback(callback) {
7203    function completeRequest() {
7204      assert(!request.done, "completeRequest() cannot be called twice.");
7205      request.done = true;
7206      while (loadingRequests.length > 0 && loadingRequests[0].done) {
7207        const otherRequest = loadingRequests.shift();
7208        setTimeout(otherRequest.callback, 0);
7209      }
7210    }
7211    const {
7212      loadingRequests
7213    } = this;
7214    const request = {
7215      done: false,
7216      complete: completeRequest,
7217      callback
7218    };
7219    loadingRequests.push(request);
7220    return request;
7221  }
7222  get _loadTestFont() {
7223    const testFont = atob("T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA" + "FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA" + "ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA" + "AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1" + "AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD" + "6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM" + "AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D" + "IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA" + "AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA" + "AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB" + "AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY" + "AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA" + "AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA" + "AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC" + "AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3" + "Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj" + "FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA==");
7224    return shadow(this, "_loadTestFont", testFont);
7225  }
7226  _prepareFontLoadEvent(font, request) {
7227    function int32(data, offset) {
7228      return data.charCodeAt(offset) << 24 | data.charCodeAt(offset + 1) << 16 | data.charCodeAt(offset + 2) << 8 | data.charCodeAt(offset + 3) & 0xff;
7229    }
7230    function spliceString(s, offset, remove, insert) {
7231      const chunk1 = s.substring(0, offset);
7232      const chunk2 = s.substring(offset + remove);
7233      return chunk1 + insert + chunk2;
7234    }
7235    let i, ii;
7236    const canvas = this._document.createElement("canvas");
7237    canvas.width = 1;
7238    canvas.height = 1;
7239    const ctx = canvas.getContext("2d");
7240    let called = 0;
7241    function isFontReady(name, callback) {
7242      if (++called > 30) {
7243        warn("Load test font never loaded.");
7244        callback();
7245        return;
7246      }
7247      ctx.font = "30px " + name;
7248      ctx.fillText(".", 0, 20);
7249      const imageData = ctx.getImageData(0, 0, 1, 1);
7250      if (imageData.data[3] > 0) {
7251        callback();
7252        return;
7253      }
7254      setTimeout(isFontReady.bind(null, name, callback));
7255    }
7256    const loadTestFontId = `lt${Date.now()}${this.loadTestFontId++}`;
7257    let data = this._loadTestFont;
7258    const COMMENT_OFFSET = 976;
7259    data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, loadTestFontId);
7260    const CFF_CHECKSUM_OFFSET = 16;
7261    const XXXX_VALUE = 0x58585858;
7262    let checksum = int32(data, CFF_CHECKSUM_OFFSET);
7263    for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {
7264      checksum = checksum - XXXX_VALUE + int32(loadTestFontId, i) | 0;
7265    }
7266    if (i < loadTestFontId.length) {
7267      checksum = checksum - XXXX_VALUE + int32(loadTestFontId + "XXX", i) | 0;
7268    }
7269    data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum));
7270    const url = `url(data:font/opentype;base64,${btoa(data)});`;
7271    const rule = `@font-face {font-family:"${loadTestFontId}";src:${url}}`;
7272    this.insertRule(rule);
7273    const div = this._document.createElement("div");
7274    div.style.visibility = "hidden";
7275    div.style.width = div.style.height = "10px";
7276    div.style.position = "absolute";
7277    div.style.top = div.style.left = "0px";
7278    for (const name of [font.loadedName, loadTestFontId]) {
7279      const span = this._document.createElement("span");
7280      span.textContent = "Hi";
7281      span.style.fontFamily = name;
7282      div.append(span);
7283    }
7284    this._document.body.append(div);
7285    isFontReady(loadTestFontId, () => {
7286      div.remove();
7287      request.complete();
7288    });
7289  }
7290}
7291class FontFaceObject {
7292  #fontData;
7293  constructor(translatedData, inspectFont = null, extra, charProcOperatorList) {
7294    this.compiledGlyphs = Object.create(null);
7295    this.#fontData = translatedData;
7296    this._inspectFont = inspectFont;
7297    if (extra) {
7298      Object.assign(this, extra);
7299    }
7300    if (charProcOperatorList) {
7301      this.charProcOperatorList = charProcOperatorList;
7302    }
7303  }
7304  createNativeFontFace() {
7305    if (!this.data || this.disableFontFace) {
7306      return null;
7307    }
7308    let nativeFontFace;
7309    if (!this.cssFontInfo) {
7310      nativeFontFace = new FontFace(this.loadedName, this.data, {});
7311    } else {
7312      const css = {
7313        weight: this.cssFontInfo.fontWeight
7314      };
7315      if (this.cssFontInfo.italicAngle) {
7316        css.style = `oblique ${this.cssFontInfo.italicAngle}deg`;
7317      }
7318      nativeFontFace = new FontFace(this.cssFontInfo.fontFamily, this.data, css);
7319    }
7320    this._inspectFont?.(this);
7321    return nativeFontFace;
7322  }
7323  createFontFaceRule() {
7324    if (!this.data || this.disableFontFace) {
7325      return null;
7326    }
7327    const url = `url(data:${this.mimetype};base64,${this.data.toBase64()});`;
7328    let rule;
7329    if (!this.cssFontInfo) {
7330      rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`;
7331    } else {
7332      let css = `font-weight: ${this.cssFontInfo.fontWeight};`;
7333      if (this.cssFontInfo.italicAngle) {
7334        css += `font-style: oblique ${this.cssFontInfo.italicAngle}deg;`;
7335      }
7336      rule = `@font-face {font-family:"${this.cssFontInfo.fontFamily}";${css}src:${url}}`;
7337    }
7338    this._inspectFont?.(this, url);
7339    return rule;
7340  }
7341  getPathGenerator(objs, character) {
7342    if (this.compiledGlyphs[character] !== undefined) {
7343      return this.compiledGlyphs[character];
7344    }
7345    const objId = this.loadedName + "_path_" + character;
7346    let cmds;
7347    try {
7348      cmds = objs.get(objId);
7349    } catch (ex) {
7350      warn(`getPathGenerator - ignoring character: "${ex}".`);
7351    }
7352    const path = makePathFromDrawOPS(cmds?.path);
7353    if (!this.fontExtraProperties) {
7354      objs.delete(objId);
7355    }
7356    return this.compiledGlyphs[character] = path;
7357  }
7358  get black() {
7359    return this.#fontData.black;
7360  }
7361  get bold() {
7362    return this.#fontData.bold;
7363  }
7364  get disableFontFace() {
7365    return this.#fontData.disableFontFace ?? false;
7366  }
7367  set disableFontFace(value) {
7368    shadow(this, "disableFontFace", !!value);
7369  }
7370  get fontExtraProperties() {
7371    return this.#fontData.fontExtraProperties ?? false;
7372  }
7373  get isInvalidPDFjsFont() {
7374    return this.#fontData.isInvalidPDFjsFont;
7375  }
7376  get isType3Font() {
7377    return this.#fontData.isType3Font;
7378  }
7379  get italic() {
7380    return this.#fontData.italic;
7381  }
7382  get missingFile() {
7383    return this.#fontData.missingFile;
7384  }
7385  get remeasure() {
7386    return this.#fontData.remeasure;
7387  }
7388  get vertical() {
7389    return this.#fontData.vertical;
7390  }
7391  get ascent() {
7392    return this.#fontData.ascent;
7393  }
7394  get defaultWidth() {
7395    return this.#fontData.defaultWidth;
7396  }
7397  get descent() {
7398    return this.#fontData.descent;
7399  }
7400  get bbox() {
7401    return this.#fontData.bbox;
7402  }
7403  set bbox(bbox) {
7404    shadow(this, "bbox", bbox);
7405  }
7406  get fontMatrix() {
7407    return this.#fontData.fontMatrix;
7408  }
7409  get fallbackName() {
7410    return this.#fontData.fallbackName;
7411  }
7412  get loadedName() {
7413    return this.#fontData.loadedName;
7414  }
7415  get mimetype() {
7416    return this.#fontData.mimetype;
7417  }
7418  get name() {
7419    return this.#fontData.name;
7420  }
7421  get data() {
7422    return this.#fontData.data;
7423  }
7424  clearData() {
7425    this.#fontData.clearData();
7426  }
7427  get cssFontInfo() {
7428    return this.#fontData.cssFontInfo;
7429  }
7430  get systemFontInfo() {
7431    return this.#fontData.systemFontInfo;
7432  }
7433  get defaultVMetrics() {
7434    return this.#fontData.defaultVMetrics;
7435  }
7436}
7437
7438;// ./src/shared/obj-bin-transform.js
7439
7440class CssFontInfo {
7441  #buffer;
7442  #view;
7443  #decoder;
7444  static strings = ["fontFamily", "fontWeight", "italicAngle"];
7445  static write(info) {
7446    const encoder = new TextEncoder();
7447    const encodedStrings = {};
7448    let stringsLength = 0;
7449    for (const prop of CssFontInfo.strings) {
7450      const encoded = encoder.encode(info[prop]);
7451      encodedStrings[prop] = encoded;
vendor: 10,728 bytes, lines 7452-7784
7452      stringsLength += 4 + encoded.length;
7453    }
7454    const buffer = new ArrayBuffer(stringsLength);
7455    const data = new Uint8Array(buffer);
7456    const view = new DataView(buffer);
7457    let offset = 0;
7458    for (const prop of CssFontInfo.strings) {
7459      const encoded = encodedStrings[prop];
7460      const length = encoded.length;
7461      view.setUint32(offset, length);
7462      data.set(encoded, offset + 4);
7463      offset += 4 + length;
7464    }
7465    assert(offset === buffer.byteLength, "CssFontInfo.write: Buffer overflow");
7466    return buffer;
7467  }
7468  constructor(buffer) {
7469    this.#buffer = buffer;
7470    this.#view = new DataView(this.#buffer);
7471    this.#decoder = new TextDecoder();
7472  }
7473  #readString(index) {
7474    assert(index < CssFontInfo.strings.length, "Invalid string index");
7475    let offset = 0;
7476    for (let i = 0; i < index; i++) {
7477      offset += this.#view.getUint32(offset) + 4;
7478    }
7479    const length = this.#view.getUint32(offset);
7480    return this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, length));
7481  }
7482  get fontFamily() {
7483    return this.#readString(0);
7484  }
7485  get fontWeight() {
7486    return this.#readString(1);
7487  }
7488  get italicAngle() {
7489    return this.#readString(2);
7490  }
7491}
7492class SystemFontInfo {
7493  #buffer;
7494  #view;
7495  #decoder;
7496  static strings = ["css", "loadedName", "baseFontName", "src"];
7497  static write(info) {
7498    const encoder = new TextEncoder();
7499    const encodedStrings = {};
7500    let stringsLength = 0;
7501    for (const prop of SystemFontInfo.strings) {
7502      const encoded = encoder.encode(info[prop]);
7503      encodedStrings[prop] = encoded;
7504      stringsLength += 4 + encoded.length;
7505    }
7506    stringsLength += 4;
7507    let encodedStyleStyle,
7508      encodedStyleWeight,
7509      lengthEstimate = 1 + stringsLength;
7510    if (info.style) {
7511      encodedStyleStyle = encoder.encode(info.style.style);
7512      encodedStyleWeight = encoder.encode(info.style.weight);
7513      lengthEstimate += 4 + encodedStyleStyle.length + 4 + encodedStyleWeight.length;
7514    }
7515    const buffer = new ArrayBuffer(lengthEstimate);
7516    const data = new Uint8Array(buffer);
7517    const view = new DataView(buffer);
7518    let offset = 0;
7519    view.setUint8(offset++, info.guessFallback ? 1 : 0);
7520    view.setUint32(offset, 0);
7521    offset += 4;
7522    stringsLength = 0;
7523    for (const prop of SystemFontInfo.strings) {
7524      const encoded = encodedStrings[prop];
7525      const length = encoded.length;
7526      stringsLength += 4 + length;
7527      view.setUint32(offset, length);
7528      data.set(encoded, offset + 4);
7529      offset += 4 + length;
7530    }
7531    view.setUint32(offset - stringsLength - 4, stringsLength);
7532    if (info.style) {
7533      view.setUint32(offset, encodedStyleStyle.length);
7534      data.set(encodedStyleStyle, offset + 4);
7535      offset += 4 + encodedStyleStyle.length;
7536      view.setUint32(offset, encodedStyleWeight.length);
7537      data.set(encodedStyleWeight, offset + 4);
7538      offset += 4 + encodedStyleWeight.length;
7539    }
7540    assert(offset <= buffer.byteLength, "SubstitionInfo.write: Buffer overflow");
7541    return buffer.transferToFixedLength(offset);
7542  }
7543  constructor(buffer) {
7544    this.#buffer = buffer;
7545    this.#view = new DataView(this.#buffer);
7546    this.#decoder = new TextDecoder();
7547  }
7548  get guessFallback() {
7549    return this.#view.getUint8(0) !== 0;
7550  }
7551  #readString(index) {
7552    assert(index < SystemFontInfo.strings.length, "Invalid string index");
7553    let offset = 5;
7554    for (let i = 0; i < index; i++) {
7555      offset += this.#view.getUint32(offset) + 4;
7556    }
7557    const length = this.#view.getUint32(offset);
7558    return this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, length));
7559  }
7560  get css() {
7561    return this.#readString(0);
7562  }
7563  get loadedName() {
7564    return this.#readString(1);
7565  }
7566  get baseFontName() {
7567    return this.#readString(2);
7568  }
7569  get src() {
7570    return this.#readString(3);
7571  }
7572  get style() {
7573    let offset = 1;
7574    offset += 4 + this.#view.getUint32(offset);
7575    const styleLength = this.#view.getUint32(offset);
7576    const style = this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, styleLength));
7577    offset += 4 + styleLength;
7578    const weightLength = this.#view.getUint32(offset);
7579    const weight = this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, weightLength));
7580    return {
7581      style,
7582      weight
7583    };
7584  }
7585}
7586class FontInfo {
7587  static bools = ["black", "bold", "disableFontFace", "fontExtraProperties", "isInvalidPDFjsFont", "isType3Font", "italic", "missingFile", "remeasure", "vertical"];
7588  static numbers = ["ascent", "defaultWidth", "descent"];
7589  static strings = ["fallbackName", "loadedName", "mimetype", "name"];
7590  static #OFFSET_NUMBERS = Math.ceil(this.bools.length * 2 / 8);
7591  static #OFFSET_BBOX = this.#OFFSET_NUMBERS + this.numbers.length * 8;
7592  static #OFFSET_FONT_MATRIX = this.#OFFSET_BBOX + 1 + 2 * 4;
7593  static #OFFSET_DEFAULT_VMETRICS = this.#OFFSET_FONT_MATRIX + 1 + 8 * 6;
7594  static #OFFSET_STRINGS = this.#OFFSET_DEFAULT_VMETRICS + 1 + 2 * 3;
7595  #buffer;
7596  #decoder;
7597  #view;
7598  constructor({
7599    data,
7600    extra
7601  }) {
7602    this.#buffer = data;
7603    this.#decoder = new TextDecoder();
7604    this.#view = new DataView(this.#buffer);
7605    if (extra) {
7606      Object.assign(this, extra);
7607    }
7608  }
7609  #readBoolean(index) {
7610    assert(index < FontInfo.bools.length, "Invalid boolean index");
7611    const byteOffset = Math.floor(index / 4);
7612    const bitOffset = index * 2 % 8;
7613    const value = this.#view.getUint8(byteOffset) >> bitOffset & 0x03;
7614    return value === 0x00 ? undefined : value === 0x02;
7615  }
7616  get black() {
7617    return this.#readBoolean(0);
7618  }
7619  get bold() {
7620    return this.#readBoolean(1);
7621  }
7622  get disableFontFace() {
7623    return this.#readBoolean(2);
7624  }
7625  get fontExtraProperties() {
7626    return this.#readBoolean(3);
7627  }
7628  get isInvalidPDFjsFont() {
7629    return this.#readBoolean(4);
7630  }
7631  get isType3Font() {
7632    return this.#readBoolean(5);
7633  }
7634  get italic() {
7635    return this.#readBoolean(6);
7636  }
7637  get missingFile() {
7638    return this.#readBoolean(7);
7639  }
7640  get remeasure() {
7641    return this.#readBoolean(8);
7642  }
7643  get vertical() {
7644    return this.#readBoolean(9);
7645  }
7646  #readNumber(index) {
7647    assert(index < FontInfo.numbers.length, "Invalid number index");
7648    return this.#view.getFloat64(FontInfo.#OFFSET_NUMBERS + index * 8);
7649  }
7650  get ascent() {
7651    return this.#readNumber(0);
7652  }
7653  get defaultWidth() {
7654    return this.#readNumber(1);
7655  }
7656  get descent() {
7657    return this.#readNumber(2);
7658  }
7659  get bbox() {
7660    let offset = FontInfo.#OFFSET_BBOX;
7661    const numCoords = this.#view.getUint8(offset);
7662    if (numCoords === 0) {
7663      return undefined;
7664    }
7665    offset += 1;
7666    const bbox = [];
7667    for (let i = 0; i < 4; i++) {
7668      bbox.push(this.#view.getInt16(offset, true));
7669      offset += 2;
7670    }
7671    return bbox;
7672  }
7673  get fontMatrix() {
7674    let offset = FontInfo.#OFFSET_FONT_MATRIX;
7675    const numPoints = this.#view.getUint8(offset);
7676    if (numPoints === 0) {
7677      return undefined;
7678    }
7679    offset += 1;
7680    const fontMatrix = [];
7681    for (let i = 0; i < 6; i++) {
7682      fontMatrix.push(this.#view.getFloat64(offset, true));
7683      offset += 8;
7684    }
7685    return fontMatrix;
7686  }
7687  get defaultVMetrics() {
7688    let offset = FontInfo.#OFFSET_DEFAULT_VMETRICS;
7689    const numMetrics = this.#view.getUint8(offset);
7690    if (numMetrics === 0) {
7691      return undefined;
7692    }
7693    offset += 1;
7694    const defaultVMetrics = [];
7695    for (let i = 0; i < 3; i++) {
7696      defaultVMetrics.push(this.#view.getInt16(offset, true));
7697      offset += 2;
7698    }
7699    return defaultVMetrics;
7700  }
7701  #readString(index) {
7702    assert(index < FontInfo.strings.length, "Invalid string index");
7703    let offset = FontInfo.#OFFSET_STRINGS + 4;
7704    for (let i = 0; i < index; i++) {
7705      offset += this.#view.getUint32(offset) + 4;
7706    }
7707    const length = this.#view.getUint32(offset);
7708    const stringData = new Uint8Array(length);
7709    stringData.set(new Uint8Array(this.#buffer, offset + 4, length));
7710    return this.#decoder.decode(stringData);
7711  }
7712  get fallbackName() {
7713    return this.#readString(0);
7714  }
7715  get loadedName() {
7716    return this.#readString(1);
7717  }
7718  get mimetype() {
7719    return this.#readString(2);
7720  }
7721  get name() {
7722    return this.#readString(3);
7723  }
7724  get data() {
7725    let offset = FontInfo.#OFFSET_STRINGS;
7726    const stringsLength = this.#view.getUint32(offset);
7727    offset += 4 + stringsLength;
7728    const systemFontInfoLength = this.#view.getUint32(offset);
7729    offset += 4 + systemFontInfoLength;
7730    const cssFontInfoLength = this.#view.getUint32(offset);
7731    offset += 4 + cssFontInfoLength;
7732    const length = this.#view.getUint32(offset);
7733    if (length === 0) {
7734      return undefined;
7735    }
7736    return new Uint8Array(this.#buffer, offset + 4, length);
7737  }
7738  clearData() {
7739    let offset = FontInfo.#OFFSET_STRINGS;
7740    const stringsLength = this.#view.getUint32(offset);
7741    offset += 4 + stringsLength;
7742    const systemFontInfoLength = this.#view.getUint32(offset);
7743    offset += 4 + systemFontInfoLength;
7744    const cssFontInfoLength = this.#view.getUint32(offset);
7745    offset += 4 + cssFontInfoLength;
7746    const length = this.#view.getUint32(offset);
7747    const data = new Uint8Array(this.#buffer, offset + 4, length);
7748    data.fill(0);
7749    this.#view.setUint32(offset, 0);
7750  }
7751  get cssFontInfo() {
7752    let offset = FontInfo.#OFFSET_STRINGS;
7753    const stringsLength = this.#view.getUint32(offset);
7754    offset += 4 + stringsLength;
7755    const systemFontInfoLength = this.#view.getUint32(offset);
7756    offset += 4 + systemFontInfoLength;
7757    const cssFontInfoLength = this.#view.getUint32(offset);
7758    if (cssFontInfoLength === 0) {
7759      return null;
7760    }
7761    const cssFontInfoData = new Uint8Array(cssFontInfoLength);
7762    cssFontInfoData.set(new Uint8Array(this.#buffer, offset + 4, cssFontInfoLength));
7763    return new CssFontInfo(cssFontInfoData.buffer);
7764  }
7765  get systemFontInfo() {
7766    let offset = FontInfo.#OFFSET_STRINGS;
7767    const stringsLength = this.#view.getUint32(offset);
7768    offset += 4 + stringsLength;
7769    const systemFontInfoLength = this.#view.getUint32(offset);
7770    if (systemFontInfoLength === 0) {
7771      return null;
7772    }
7773    const systemFontInfoData = new Uint8Array(systemFontInfoLength);
7774    systemFontInfoData.set(new Uint8Array(this.#buffer, offset + 4, systemFontInfoLength));
7775    return new SystemFontInfo(systemFontInfoData.buffer);
7776  }
7777  static write(font) {
7778    const systemFontInfoBuffer = font.systemFontInfo ? SystemFontInfo.write(font.systemFontInfo) : null;
7779    const cssFontInfoBuffer = font.cssFontInfo ? CssFontInfo.write(font.cssFontInfo) : null;
7780    const encoder = new TextEncoder();
7781    const encodedStrings = {};
7782    let stringsLength = 0;
7783    for (const prop of FontInfo.strings) {
7784      encodedStrings[prop] = encoder.encode(font[prop]);
vendor: 5,233 bytes, lines 7785-7938
7785      stringsLength += 4 + encodedStrings[prop].length;
7786    }
7787    const lengthEstimate = FontInfo.#OFFSET_STRINGS + 4 + stringsLength + 4 + (systemFontInfoBuffer ? systemFontInfoBuffer.byteLength : 0) + 4 + (cssFontInfoBuffer ? cssFontInfoBuffer.byteLength : 0) + 4 + (font.data ? font.data.length : 0);
7788    const buffer = new ArrayBuffer(lengthEstimate);
7789    const data = new Uint8Array(buffer);
7790    const view = new DataView(buffer);
7791    let offset = 0;
7792    const numBools = FontInfo.bools.length;
7793    let boolByte = 0,
7794      boolBit = 0;
7795    for (let i = 0; i < numBools; i++) {
7796      const value = font[FontInfo.bools[i]];
7797      const bits = value === undefined ? 0x00 : value ? 0x02 : 0x01;
7798      boolByte |= bits << boolBit;
7799      boolBit += 2;
7800      if (boolBit === 8 || i === numBools - 1) {
7801        view.setUint8(offset++, boolByte);
7802        boolByte = 0;
7803        boolBit = 0;
7804      }
7805    }
7806    assert(offset === FontInfo.#OFFSET_NUMBERS, "FontInfo.write: Boolean properties offset mismatch");
7807    for (const prop of FontInfo.numbers) {
7808      view.setFloat64(offset, font[prop]);
7809      offset += 8;
7810    }
7811    assert(offset === FontInfo.#OFFSET_BBOX, "FontInfo.write: Number properties offset mismatch");
7812    if (font.bbox) {
7813      view.setUint8(offset++, 4);
7814      for (const coord of font.bbox) {
7815        view.setInt16(offset, coord, true);
7816        offset += 2;
7817      }
7818    } else {
7819      view.setUint8(offset++, 0);
7820      offset += 2 * 4;
7821    }
7822    assert(offset === FontInfo.#OFFSET_FONT_MATRIX, "FontInfo.write: BBox properties offset mismatch");
7823    if (font.fontMatrix) {
7824      view.setUint8(offset++, 6);
7825      for (const point of font.fontMatrix) {
7826        view.setFloat64(offset, point, true);
7827        offset += 8;
7828      }
7829    } else {
7830      view.setUint8(offset++, 0);
7831      offset += 8 * 6;
7832    }
7833    assert(offset === FontInfo.#OFFSET_DEFAULT_VMETRICS, "FontInfo.write: FontMatrix properties offset mismatch");
7834    if (font.defaultVMetrics) {
7835      view.setUint8(offset++, 1);
7836      for (const metric of font.defaultVMetrics) {
7837        view.setInt16(offset, metric, true);
7838        offset += 2;
7839      }
7840    } else {
7841      view.setUint8(offset++, 0);
7842      offset += 3 * 2;
7843    }
7844    assert(offset === FontInfo.#OFFSET_STRINGS, "FontInfo.write: DefaultVMetrics properties offset mismatch");
7845    view.setUint32(FontInfo.#OFFSET_STRINGS, 0);
7846    offset += 4;
7847    for (const prop of FontInfo.strings) {
7848      const encoded = encodedStrings[prop];
7849      const length = encoded.length;
7850      view.setUint32(offset, length);
7851      data.set(encoded, offset + 4);
7852      offset += 4 + length;
7853    }
7854    view.setUint32(FontInfo.#OFFSET_STRINGS, offset - FontInfo.#OFFSET_STRINGS - 4);
7855    if (!systemFontInfoBuffer) {
7856      view.setUint32(offset, 0);
7857      offset += 4;
7858    } else {
7859      const length = systemFontInfoBuffer.byteLength;
7860      view.setUint32(offset, length);
7861      assert(offset + 4 + length <= buffer.byteLength, "FontInfo.write: Buffer overflow at systemFontInfo");
7862      data.set(new Uint8Array(systemFontInfoBuffer), offset + 4);
7863      offset += 4 + length;
7864    }
7865    if (!cssFontInfoBuffer) {
7866      view.setUint32(offset, 0);
7867      offset += 4;
7868    } else {
7869      const length = cssFontInfoBuffer.byteLength;
7870      view.setUint32(offset, length);
7871      assert(offset + 4 + length <= buffer.byteLength, "FontInfo.write: Buffer overflow at cssFontInfo");
7872      data.set(new Uint8Array(cssFontInfoBuffer), offset + 4);
7873      offset += 4 + length;
7874    }
7875    if (font.data === undefined) {
7876      view.setUint32(offset, 0);
7877      offset += 4;
7878    } else {
7879      view.setUint32(offset, font.data.length);
7880      data.set(font.data, offset + 4);
7881      offset += 4 + font.data.length;
7882    }
7883    assert(offset <= buffer.byteLength, "FontInfo.write: Buffer overflow");
7884    return buffer.transferToFixedLength(offset);
7885  }
7886}
7887class PatternInfo {
7888  static #KIND = 0;
7889  static #HAS_BBOX = 1;
7890  static #HAS_BACKGROUND = 2;
7891  static #SHADING_TYPE = 3;
7892  static #N_COORD = 4;
7893  static #N_COLOR = 8;
7894  static #N_STOP = 12;
7895  static #N_FIGURES = 16;
7896  constructor(buffer) {
7897    this.buffer = buffer;
7898    this.view = new DataView(buffer);
7899    this.data = new Uint8Array(buffer);
7900  }
7901  static write(ir) {
7902    let kind,
7903      bbox = null,
7904      coords = [],
7905      colors = [],
7906      colorStops = [],
7907      figures = [],
7908      shadingType = null,
7909      background = null;
7910    switch (ir[0]) {
7911      case "RadialAxial":
7912        kind = ir[1] === "axial" ? 1 : 2;
7913        bbox = ir[2];
7914        colorStops = ir[3];
7915        if (kind === 1) {
7916          coords.push(...ir[4], ...ir[5]);
7917        } else {
7918          coords.push(ir[4][0], ir[4][1], ir[6], ir[5][0], ir[5][1], ir[7]);
7919        }
7920        break;
7921      case "Mesh":
7922        kind = 3;
7923        shadingType = ir[1];
7924        coords = ir[2];
7925        colors = ir[3];
7926        figures = ir[4] || [];
7927        bbox = ir[6];
7928        background = ir[7];
7929        break;
7930      default:
7931        throw new Error(`Unsupported pattern type: ${ir[0]}`);
7932    }
7933    const nCoord = Math.floor(coords.length / 2);
7934    const nColor = Math.floor(colors.length / 3);
7935    const nStop = colorStops.length;
7936    const nFigures = figures.length;
7937    let figuresSize = 0;
7938    for (const figure of figures) {
7939      figuresSize += 1;
7940      figuresSize = Math.ceil(figuresSize / 4) * 4;
7941      figuresSize += 4 + figure.coords.length * 4;
7942      figuresSize += 4 + figure.colors.length * 4;
7943      if (figure.verticesPerRow !== undefined) {
7944        figuresSize += 4;
7945      }
7946    }
7947    const byteLen = 20 + nCoord * 8 + nColor * 3 + nStop * 8 + (bbox ? 16 : 0) + (background ? 3 : 0) + figuresSize;
7948    const buffer = new ArrayBuffer(byteLen);
7949    const dataView = new DataView(buffer);
7950    const u8data = new Uint8Array(buffer);
7951    dataView.setUint8(PatternInfo.#KIND, kind);
7952    dataView.setUint8(PatternInfo.#HAS_BBOX, bbox ? 1 : 0);
7953    dataView.setUint8(PatternInfo.#HAS_BACKGROUND, background ? 1 : 0);
7954    dataView.setUint8(PatternInfo.#SHADING_TYPE, shadingType);
7955    dataView.setUint32(PatternInfo.#N_COORD, nCoord, true);
7956    dataView.setUint32(PatternInfo.#N_COLOR, nColor, true);
7957    dataView.setUint32(PatternInfo.#N_STOP, nStop, true);
7958    dataView.setUint32(PatternInfo.#N_FIGURES, nFigures, true);
7959    let offset = 20;
7960    const coordsView = new Float32Array(buffer, offset, nCoord * 2);
7961    coordsView.set(coords);
7962    offset += nCoord * 8;
7963    u8data.set(colors, offset);
7964    offset += nColor * 3;
7965    for (const [pos, hex] of colorStops) {
7966      dataView.setFloat32(offset, pos, true);
7967      offset += 4;
7968      dataView.setUint32(offset, parseInt(hex.slice(1), 16), true);
7969      offset += 4;
7970    }
7971    if (bbox) {
7972      for (const v of bbox) {
7973        dataView.setFloat32(offset, v, true);
7974        offset += 4;
7975      }
7976    }
7977    if (background) {
7978      u8data.set(background, offset);
7979      offset += 3;
7980    }
7981    for (let i = 0; i < figures.length; i++) {
7982      const figure = figures[i];
7983      dataView.setUint8(offset, figure.type);
7984      offset += 1;
7985      offset = Math.ceil(offset / 4) * 4;
7986      dataView.setUint32(offset, figure.coords.length, true);
7987      offset += 4;
7988      const figureCoordsView = new Int32Array(buffer, offset, figure.coords.length);
7989      figureCoordsView.set(figure.coords);
7990      offset += figure.coords.length * 4;
7991      dataView.setUint32(offset, figure.colors.length, true);
7992      offset += 4;
7993      const colorsView = new Int32Array(buffer, offset, figure.colors.length);
7994      colorsView.set(figure.colors);
7995      offset += figure.colors.length * 4;
7996      if (figure.verticesPerRow !== undefined) {
7997        dataView.setUint32(offset, figure.verticesPerRow, true);
7998        offset += 4;
7999      }
8000    }
8001    return buffer;
8002  }
8003  getIR() {
8004    const dataView = this.view;
8005    const kind = this.data[PatternInfo.#KIND];
8006    const hasBBox = !!this.data[PatternInfo.#HAS_BBOX];
8007    const hasBackground = !!this.data[PatternInfo.#HAS_BACKGROUND];
8008    const nCoord = dataView.getUint32(PatternInfo.#N_COORD, true);
8009    const nColor = dataView.getUint32(PatternInfo.#N_COLOR, true);
8010    const nStop = dataView.getUint32(PatternInfo.#N_STOP, true);
8011    const nFigures = dataView.getUint32(PatternInfo.#N_FIGURES, true);
8012    let offset = 20;
8013    const coords = new Float32Array(this.buffer, offset, nCoord * 2);
8014    offset += nCoord * 8;
8015    const colors = new Uint8Array(this.buffer, offset, nColor * 3);
8016    offset += nColor * 3;
8017    const stops = [];
8018    for (let i = 0; i < nStop; ++i) {
8019      const p = dataView.getFloat32(offset, true);
8020      offset += 4;
8021      const rgb = dataView.getUint32(offset, true);
8022      offset += 4;
8023      stops.push([p, `#${rgb.toString(16).padStart(6, "0")}`]);
8024    }
8025    let bbox = null;
8026    if (hasBBox) {
8027      bbox = [];
8028      for (let i = 0; i < 4; ++i) {
8029        bbox.push(dataView.getFloat32(offset, true));
8030        offset += 4;
8031      }
8032    }
8033    let background = null;
8034    if (hasBackground) {
8035      background = new Uint8Array(this.buffer, offset, 3);
8036      offset += 3;
8037    }
8038    const figures = [];
8039    for (let i = 0; i < nFigures; ++i) {
8040      const type = dataView.getUint8(offset);
8041      offset += 1;
8042      offset = Math.ceil(offset / 4) * 4;
8043      const coordsLength = dataView.getUint32(offset, true);
8044      offset += 4;
8045      const figureCoords = new Int32Array(this.buffer, offset, coordsLength);
8046      offset += coordsLength * 4;
8047      const colorsLength = dataView.getUint32(offset, true);
8048      offset += 4;
8049      const figureColors = new Int32Array(this.buffer, offset, colorsLength);
8050      offset += colorsLength * 4;
8051      const figure = {
8052        type,
8053        coords: figureCoords,
8054        colors: figureColors
8055      };
8056      if (type === MeshFigureType.LATTICE) {
8057        figure.verticesPerRow = dataView.getUint32(offset, true);
8058        offset += 4;
8059      }
8060      figures.push(figure);
8061    }
8062    if (kind === 1) {
8063      return ["RadialAxial", "axial", bbox, stops, Array.from(coords.slice(0, 2)), Array.from(coords.slice(2, 4)), null, null];
8064    }
8065    if (kind === 2) {
8066      return ["RadialAxial", "radial", bbox, stops, [coords[0], coords[1]], [coords[3], c
vendor: 16,469 bytes, lines 8066-8611
8066oords[4]], coords[2], coords[5]];
8067    }
8068    if (kind === 3) {
8069      const shadingType = this.data[PatternInfo.#SHADING_TYPE];
8070      let bounds = null;
8071      if (coords.length > 0) {
8072        let minX = coords[0],
8073          maxX = coords[0];
8074        let minY = coords[1],
8075          maxY = coords[1];
8076        for (let i = 0; i < coords.length; i += 2) {
8077          const x = coords[i],
8078            y = coords[i + 1];
8079          minX = minX > x ? x : minX;
8080          minY = minY > y ? y : minY;
8081          maxX = maxX < x ? x : maxX;
8082          maxY = maxY < y ? y : maxY;
8083        }
8084        bounds = [minX, minY, maxX, maxY];
8085      }
8086      return ["Mesh", shadingType, coords, colors, figures, bounds, bbox, background];
8087    }
8088    throw new Error(`Unsupported pattern kind: ${kind}`);
8089  }
8090}
8091class FontPathInfo {
8092  static write(path) {
8093    let data;
8094    let buffer;
8095    if (util_FeatureTest.isFloat16ArraySupported) {
8096      buffer = new ArrayBuffer(path.length * 2);
8097      data = new Float16Array(buffer);
8098    } else {
8099      buffer = new ArrayBuffer(path.length * 4);
8100      data = new Float32Array(buffer);
8101    }
8102    data.set(path);
8103    return buffer;
8104  }
8105  #buffer;
8106  constructor(buffer) {
8107    this.#buffer = buffer;
8108  }
8109  get path() {
8110    if (util_FeatureTest.isFloat16ArraySupported) {
8111      return new Float16Array(this.#buffer);
8112    }
8113    return new Float32Array(this.#buffer);
8114  }
8115}
8116
8117;// ./src/display/api_utils.js
8118
8119function getUrlProp(val) {
8120  if (val instanceof URL) {
8121    return val.href;
8122  }
8123  if (typeof val === "string") {
8124    if (isNodeJS) {
8125      return val;
8126    }
8127    const url = URL.parse(val, window.location);
8128    if (url) {
8129      return url.href;
8130    }
8131  }
8132  throw new Error("Invalid PDF url data: " + "either string or URL-object is expected in the url property.");
8133}
8134function getDataProp(val) {
8135  if (isNodeJS && typeof Buffer !== "undefined" && val instanceof Buffer) {
8136    throw new Error("Please provide binary data as `Uint8Array`, rather than `Buffer`.");
8137  }
8138  if (val instanceof Uint8Array && val.byteLength === val.buffer.byteLength) {
8139    return val;
8140  }
8141  if (typeof val === "string") {
8142    return stringToBytes(val);
8143  }
8144  if (val instanceof ArrayBuffer || ArrayBuffer.isView(val) || typeof val === "object" && !isNaN(val?.length)) {
8145    return new Uint8Array(val);
8146  }
8147  throw new Error("Invalid PDF binary data: either TypedArray, " + "string, or array-like object is expected in the data property.");
8148}
8149function getFactoryUrlProp(val) {
8150  if (typeof val !== "string") {
8151    return null;
8152  }
8153  if (val.endsWith("/")) {
8154    return val;
8155  }
8156  throw new Error(`Invalid factory url: "${val}" must include trailing slash.`);
8157}
8158const isRefProxy = v => typeof v === "object" && Number.isInteger(v?.num) && v.num >= 0 && Number.isInteger(v?.gen) && v.gen >= 0;
8159const isNameProxy = v => typeof v === "object" && typeof v?.name === "string";
8160const isValidExplicitDest = _isValidExplicitDest.bind(null, isRefProxy, isNameProxy);
8161class LoopbackPort {
8162  #listeners = new Map();
8163  #deferred = Promise.resolve();
8164  postMessage(obj, transfer) {
8165    const event = {
8166      data: structuredClone(obj, transfer ? {
8167        transfer
8168      } : null)
8169    };
8170    this.#deferred.then(() => {
8171      for (const [listener] of this.#listeners) {
8172        listener.call(this, event);
8173      }
8174    });
8175  }
8176  addEventListener(name, listener, options = null) {
8177    let rmAbort = null;
8178    if (options?.signal instanceof AbortSignal) {
8179      const {
8180        signal
8181      } = options;
8182      if (signal.aborted) {
8183        warn("LoopbackPort - cannot use an `aborted` signal.");
8184        return;
8185      }
8186      const onAbort = () => this.removeEventListener(name, listener);
8187      rmAbort = () => signal.removeEventListener("abort", onAbort);
8188      signal.addEventListener("abort", onAbort);
8189    }
8190    this.#listeners.set(listener, rmAbort);
8191  }
8192  removeEventListener(name, listener) {
8193    const rmAbort = this.#listeners.get(listener);
8194    rmAbort?.();
8195    this.#listeners.delete(listener);
8196  }
8197  terminate() {
8198    for (const [, rmAbort] of this.#listeners) {
8199      rmAbort?.();
8200    }
8201    this.#listeners.clear();
8202  }
8203}
8204
8205;// ./src/shared/message_handler.js
8206
8207const CallbackKind = {
8208  DATA: 1,
8209  ERROR: 2
8210};
8211const StreamKind = {
8212  CANCEL: 1,
8213  CANCEL_COMPLETE: 2,
8214  CLOSE: 3,
8215  ENQUEUE: 4,
8216  ERROR: 5,
8217  PULL: 6,
8218  PULL_COMPLETE: 7,
8219  START_COMPLETE: 8
8220};
8221function onFn() {}
8222function wrapReason(ex) {
8223  if (ex instanceof AbortException || ex instanceof InvalidPDFException || ex instanceof PasswordException || ex instanceof ResponseException || ex instanceof UnknownErrorException) {
8224    return ex;
8225  }
8226  if (!(ex instanceof Error || typeof ex === "object" && ex !== null)) {
8227    unreachable('wrapReason: Expected "reason" to be a (possibly cloned) Error.');
8228  }
8229  switch (ex.name) {
8230    case "AbortException":
8231      return new AbortException(ex.message);
8232    case "InvalidPDFException":
8233      return new InvalidPDFException(ex.message);
8234    case "PasswordException":
8235      return new PasswordException(ex.message, ex.code);
8236    case "ResponseException":
8237      return new ResponseException(ex.message, ex.status, ex.missing);
8238    case "UnknownErrorException":
8239      return new UnknownErrorException(ex.message, ex.details);
8240  }
8241  return new UnknownErrorException(ex.message, ex.toString());
8242}
8243class MessageHandler {
8244  #messageAC = new AbortController();
8245  constructor(sourceName, targetName, comObj) {
8246    this.sourceName = sourceName;
8247    this.targetName = targetName;
8248    this.comObj = comObj;
8249    this.callbackId = 1;
8250    this.streamId = 1;
8251    this.streamSinks = Object.create(null);
8252    this.streamControllers = Object.create(null);
8253    this.callbackCapabilities = Object.create(null);
8254    this.actionHandler = Object.create(null);
8255    comObj.addEventListener("message", this.#onMessage.bind(this), {
8256      signal: this.#messageAC.signal
8257    });
8258  }
8259  #onMessage({
8260    data
8261  }) {
8262    if (data.targetName !== this.sourceName) {
8263      return;
8264    }
8265    if (data.stream) {
8266      this.#processStreamMessage(data);
8267      return;
8268    }
8269    if (data.callback) {
8270      const callbackId = data.callbackId;
8271      const capability = this.callbackCapabilities[callbackId];
8272      if (!capability) {
8273        throw new Error(`Cannot resolve callback ${callbackId}`);
8274      }
8275      delete this.callbackCapabilities[callbackId];
8276      if (data.callback === CallbackKind.DATA) {
8277        capability.resolve(data.data);
8278      } else if (data.callback === CallbackKind.ERROR) {
8279        capability.reject(wrapReason(data.reason));
8280      } else {
8281        throw new Error("Unexpected callback case");
8282      }
8283      return;
8284    }
8285    const action = this.actionHandler[data.action];
8286    if (!action) {
8287      throw new Error(`Unknown action from worker: ${data.action}`);
8288    }
8289    if (data.callbackId) {
8290      const sourceName = this.sourceName,
8291        targetName = data.sourceName,
8292        comObj = this.comObj;
8293      Promise.try(action, data.data).then(function (result) {
8294        comObj.postMessage({
8295          sourceName,
8296          targetName,
8297          callback: CallbackKind.DATA,
8298          callbackId: data.callbackId,
8299          data: result
8300        });
8301      }, function (reason) {
8302        comObj.postMessage({
8303          sourceName,
8304          targetName,
8305          callback: CallbackKind.ERROR,
8306          callbackId: data.callbackId,
8307          reason: wrapReason(reason)
8308        });
8309      });
8310      return;
8311    }
8312    if (data.streamId) {
8313      this.#createStreamSink(data);
8314      return;
8315    }
8316    action(data.data);
8317  }
8318  on(actionName, handler) {
8319    const ah = this.actionHandler;
8320    if (ah[actionName]) {
8321      throw new Error(`There is already an actionName called "${actionName}"`);
8322    }
8323    ah[actionName] = handler;
8324  }
8325  send(actionName, data, transfers) {
8326    this.comObj.postMessage({
8327      sourceName: this.sourceName,
8328      targetName: this.targetName,
8329      action: actionName,
8330      data
8331    }, transfers);
8332  }
8333  sendWithPromise(actionName, data, transfers) {
8334    const callbackId = this.callbackId++;
8335    const capability = Promise.withResolvers();
8336    this.callbackCapabilities[callbackId] = capability;
8337    try {
8338      this.comObj.postMessage({
8339        sourceName: this.sourceName,
8340        targetName: this.targetName,
8341        action: actionName,
8342        callbackId,
8343        data
8344      }, transfers);
8345    } catch (ex) {
8346      capability.reject(ex);
8347    }
8348    return capability.promise;
8349  }
8350  sendWithStream(actionName, data, queueingStrategy, transfers) {
8351    const streamId = this.streamId++,
8352      sourceName = this.sourceName,
8353      targetName = this.targetName,
8354      comObj = this.comObj;
8355    return new ReadableStream({
8356      start: controller => {
8357        const startCapability = Promise.withResolvers();
8358        this.streamControllers[streamId] = {
8359          controller,
8360          startCall: startCapability,
8361          pullCall: null,
8362          cancelCall: null,
8363          isClosed: false
8364        };
8365        comObj.postMessage({
8366          sourceName,
8367          targetName,
8368          action: actionName,
8369          streamId,
8370          data,
8371          desiredSize: controller.desiredSize
8372        }, transfers);
8373        return startCapability.promise;
8374      },
8375      pull: controller => {
8376        const pullCapability = Promise.withResolvers();
8377        this.streamControllers[streamId].pullCall = pullCapability;
8378        comObj.postMessage({
8379          sourceName,
8380          targetName,
8381          stream: StreamKind.PULL,
8382          streamId,
8383          desiredSize: controller.desiredSize
8384        });
8385        return pullCapability.promise;
8386      },
8387      cancel: reason => {
8388        assert(reason instanceof Error, "cancel must have a valid reason");
8389        const cancelCapability = Promise.withResolvers();
8390        this.streamControllers[streamId].cancelCall = cancelCapability;
8391        this.streamControllers[streamId].isClosed = true;
8392        comObj.postMessage({
8393          sourceName,
8394          targetName,
8395          stream: StreamKind.CANCEL,
8396          streamId,
8397          reason: wrapReason(reason)
8398        });
8399        return cancelCapability.promise;
8400      }
8401    }, queueingStrategy);
8402  }
8403  #createStreamSink(data) {
8404    const streamId = data.streamId,
8405      sourceName = this.sourceName,
8406      targetName = data.sourceName,
8407      comObj = this.comObj;
8408    const self = this,
8409      action = this.actionHandler[data.action];
8410    const streamSink = {
8411      enqueue(chunk, size = 1, transfers) {
8412        if (this.isCancelled) {
8413          return;
8414        }
8415        const lastDesiredSize = this.desiredSize;
8416        this.desiredSize -= size;
8417        if (lastDesiredSize > 0 && this.desiredSize <= 0) {
8418          this.sinkCapability = Promise.withResolvers();
8419          this.ready = this.sinkCapability.promise;
8420        }
8421        comObj.postMessage({
8422          sourceName,
8423          targetName,
8424          stream: StreamKind.ENQUEUE,
8425          streamId,
8426          chunk
8427        }, transfers);
8428      },
8429      close() {
8430        if (this.isCancelled) {
8431          return;
8432        }
8433        this.isCancelled = true;
8434        comObj.postMessage({
8435          sourceName,
8436          targetName,
8437          stream: StreamKind.CLOSE,
8438          streamId
8439        });
8440        delete self.streamSinks[streamId];
8441      },
8442      error(reason) {
8443        assert(reason instanceof Error, "error must have a valid reason");
8444        if (this.isCancelled) {
8445          return;
8446        }
8447        this.isCancelled = true;
8448        comObj.postMessage({
8449          sourceName,
8450          targetName,
8451          stream: StreamKind.ERROR,
8452          streamId,
8453          reason: wrapReason(reason)
8454        });
8455      },
8456      sinkCapability: Promise.withResolvers(),
8457      onPull: null,
8458      onCancel: null,
8459      isCancelled: false,
8460      desiredSize: data.desiredSize,
8461      ready: null
8462    };
8463    streamSink.sinkCapability.resolve();
8464    streamSink.ready = streamSink.sinkCapability.promise;
8465    this.streamSinks[streamId] = streamSink;
8466    Promise.try(action, data.data, streamSink).then(function () {
8467      comObj.postMessage({
8468        sourceName,
8469        targetName,
8470        stream: StreamKind.START_COMPLETE,
8471        streamId,
8472        success: true
8473      });
8474    }, function (reason) {
8475      comObj.postMessage({
8476        sourceName,
8477        targetName,
8478        stream: StreamKind.START_COMPLETE,
8479        streamId,
8480        reason: wrapReason(reason)
8481      });
8482    });
8483  }
8484  #processStreamMessage(data) {
8485    const streamId = data.streamId,
8486      sourceName = this.sourceName,
8487      targetName = data.sourceName,
8488      comObj = this.comObj;
8489    const streamController = this.streamControllers[streamId],
8490      streamSink = this.streamSinks[streamId];
8491    switch (data.stream) {
8492      case StreamKind.START_COMPLETE:
8493        if (data.success) {
8494          streamController.startCall.resolve();
8495        } else {
8496          streamController.startCall.reject(wrapReason(data.reason));
8497        }
8498        break;
8499      case StreamKind.PULL_COMPLETE:
8500        if (data.success) {
8501          streamController.pullCall.resolve();
8502        } else {
8503          streamController.pullCall.reject(wrapReason(data.reason));
8504        }
8505        break;
8506      case StreamKind.PULL:
8507        if (!streamSink) {
8508          comObj.postMessage({
8509            sourceName,
8510            targetName,
8511            stream: StreamKind.PULL_COMPLETE,
8512            streamId,
8513            success: true
8514          });
8515          break;
8516        }
8517        if (streamSink.desiredSize <= 0 && data.desiredSize > 0) {
8518          streamSink.sinkCapability.resolve();
8519        }
8520        streamSink.desiredSize = data.desiredSize;
8521        Promise.try(streamSink.onPull || onFn).then(function () {
8522          comObj.postMessage({
8523            sourceName,
8524            targetName,
8525            stream: StreamKind.PULL_COMPLETE,
8526            streamId,
8527            success: true
8528          });
8529        }, function (reason) {
8530          comObj.postMessage({
8531            sourceName,
8532            targetName,
8533            stream: StreamKind.PULL_COMPLETE,
8534            streamId,
8535            reason: wrapReason(reason)
8536          });
8537        });
8538        break;
8539      case StreamKind.ENQUEUE:
8540        assert(streamController, "enqueue should have stream controller");
8541        if (streamController.isClosed) {
8542          break;
8543        }
8544        streamController.controller.enqueue(data.chunk);
8545        break;
8546      case StreamKind.CLOSE:
8547        assert(streamController, "close should have stream controller");
8548        if (streamController.isClosed) {
8549          break;
8550        }
8551        streamController.isClosed = true;
8552        streamController.controller.close();
8553        this.#deleteStreamController(streamController, streamId);
8554        break;
8555      case StreamKind.ERROR:
8556        assert(streamController, "error should have stream controller");
8557        streamController.controller.error(wrapReason(data.reason));
8558        this.#deleteStreamController(streamController, streamId);
8559        break;
8560      case StreamKind.CANCEL_COMPLETE:
8561        if (data.success) {
8562          streamController.cancelCall.resolve();
8563        } else {
8564          streamController.cancelCall.reject(wrapReason(data.reason));
8565        }
8566        this.#deleteStreamController(streamController, streamId);
8567        break;
8568      case StreamKind.CANCEL:
8569        if (!streamSink) {
8570          break;
8571        }
8572        const dataReason = wrapReason(data.reason);
8573        Promise.try(streamSink.onCancel || onFn, dataReason).then(function () {
8574          comObj.postMessage({
8575            sourceName,
8576            targetName,
8577            stream: StreamKind.CANCEL_COMPLETE,
8578            streamId,
8579            success: true
8580          });
8581        }, function (reason) {
8582          comObj.postMessage({
8583            sourceName,
8584            targetName,
8585            stream: StreamKind.CANCEL_COMPLETE,
8586            streamId,
8587            reason: wrapReason(reason)
8588          });
8589        });
8590        streamSink.sinkCapability.reject(dataReason);
8591        streamSink.isCancelled = true;
8592        delete this.streamSinks[streamId];
8593        break;
8594      default:
8595        throw new Error("Unexpected stream case");
8596    }
8597  }
8598  async #deleteStreamController(streamController, streamId) {
8599    await Promise.allSettled([streamController.startCall?.promise, streamController.pullCall?.promise, streamController.cancelCall?.promise]);
8600    delete this.streamControllers[streamId];
8601  }
8602  destroy() {
8603    this.#messageAC?.abort();
8604    this.#messageAC = null;
8605  }
8606}
8607
8608;// ./src/display/canvas_factory.js
8609
8610class BaseCanvasFactory {
8611  #enableHWA = false;
vendor: 34,720 bytes, lines 8612-9739
8612  constructor({
8613    enableHWA = false
8614  }) {
8615    this.#enableHWA = enableHWA;
8616  }
8617  create(width, height) {
8618    if (width <= 0 || height <= 0) {
8619      throw new Error("Invalid canvas size");
8620    }
8621    const canvas = this._createCanvas(width, height);
8622    return {
8623      canvas,
8624      context: canvas.getContext("2d", {
8625        willReadFrequently: !this.#enableHWA
8626      })
8627    };
8628  }
8629  reset(canvasAndContext, width, height) {
8630    if (!canvasAndContext.canvas) {
8631      throw new Error("Canvas is not specified");
8632    }
8633    if (width <= 0 || height <= 0) {
8634      throw new Error("Invalid canvas size");
8635    }
8636    canvasAndContext.canvas.width = width;
8637    canvasAndContext.canvas.height = height;
8638  }
8639  destroy(canvasAndContext) {
8640    if (!canvasAndContext.canvas) {
8641      throw new Error("Canvas is not specified");
8642    }
8643    canvasAndContext.canvas.width = 0;
8644    canvasAndContext.canvas.height = 0;
8645    canvasAndContext.canvas = null;
8646    canvasAndContext.context = null;
8647  }
8648  _createCanvas(width, height) {
8649    unreachable("Abstract method `_createCanvas` called.");
8650  }
8651}
8652class DOMCanvasFactory extends BaseCanvasFactory {
8653  constructor({
8654    ownerDocument = globalThis.document,
8655    enableHWA = false
8656  }) {
8657    super({
8658      enableHWA
8659    });
8660    this._document = ownerDocument;
8661  }
8662  _createCanvas(width, height) {
8663    const canvas = this._document.createElement("canvas");
8664    canvas.width = width;
8665    canvas.height = height;
8666    return canvas;
8667  }
8668}
8669
8670;// ./src/display/cmap_reader_factory.js
8671
8672
8673class BaseCMapReaderFactory {
8674  constructor({
8675    baseUrl = null,
8676    isCompressed = true
8677  }) {
8678    this.baseUrl = baseUrl;
8679    this.isCompressed = isCompressed;
8680  }
8681  async fetch({
8682    name
8683  }) {
8684    if (!this.baseUrl) {
8685      throw new Error("Ensure that the `cMapUrl` and `cMapPacked` API parameters are provided.");
8686    }
8687    if (!name) {
8688      throw new Error("CMap name must be specified.");
8689    }
8690    const url = this.baseUrl + name + (this.isCompressed ? ".bcmap" : "");
8691    return this._fetch(url).then(cMapData => ({
8692      cMapData,
8693      isCompressed: this.isCompressed
8694    })).catch(reason => {
8695      throw new Error(`Unable to load ${this.isCompressed ? "binary " : ""}CMap at: ${url}`);
8696    });
8697  }
8698  async _fetch(url) {
8699    unreachable("Abstract method `_fetch` called.");
8700  }
8701}
8702class DOMCMapReaderFactory extends BaseCMapReaderFactory {
8703  async _fetch(url) {
8704    const data = await fetchData(url, this.isCompressed ? "arraybuffer" : "text");
8705    return data instanceof ArrayBuffer ? new Uint8Array(data) : stringToBytes(data);
8706  }
8707}
8708
8709;// ./src/display/filter_factory.js
8710
8711
8712class BaseFilterFactory {
8713  addFilter(maps) {
8714    return "none";
8715  }
8716  addHCMFilter(fgColor, bgColor) {
8717    return "none";
8718  }
8719  addAlphaFilter(map) {
8720    return "none";
8721  }
8722  addLuminosityFilter(map) {
8723    return "none";
8724  }
8725  addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) {
8726    return "none";
8727  }
8728  destroy(keepHCM = false) {}
8729}
8730class DOMFilterFactory extends BaseFilterFactory {
8731  #baseUrl;
8732  #_cache;
8733  #_defs;
8734  #docId;
8735  #document;
8736  #_hcmCache;
8737  #id = 0;
8738  constructor({
8739    docId,
8740    ownerDocument = globalThis.document
8741  }) {
8742    super();
8743    this.#docId = docId;
8744    this.#document = ownerDocument;
8745  }
8746  get #cache() {
8747    return this.#_cache ||= new Map();
8748  }
8749  get #hcmCache() {
8750    return this.#_hcmCache ||= new Map();
8751  }
8752  get #defs() {
8753    if (!this.#_defs) {
8754      const div = this.#document.createElement("div");
8755      const {
8756        style
8757      } = div;
8758      style.visibility = "hidden";
8759      style.contain = "strict";
8760      style.width = style.height = 0;
8761      style.position = "absolute";
8762      style.top = style.left = 0;
8763      style.zIndex = -1;
8764      const svg = this.#document.createElementNS(SVG_NS, "svg");
8765      svg.setAttribute("width", 0);
8766      svg.setAttribute("height", 0);
8767      this.#_defs = this.#document.createElementNS(SVG_NS, "defs");
8768      div.append(svg);
8769      svg.append(this.#_defs);
8770      this.#document.body.append(div);
8771    }
8772    return this.#_defs;
8773  }
8774  #createTables(maps) {
8775    if (maps.length === 1) {
8776      const mapR = maps[0];
8777      const buffer = new Array(256);
8778      for (let i = 0; i < 256; i++) {
8779        buffer[i] = mapR[i] / 255;
8780      }
8781      const table = buffer.join(",");
8782      return [table, table, table];
8783    }
8784    const [mapR, mapG, mapB] = maps;
8785    const bufferR = new Array(256);
8786    const bufferG = new Array(256);
8787    const bufferB = new Array(256);
8788    for (let i = 0; i < 256; i++) {
8789      bufferR[i] = mapR[i] / 255;
8790      bufferG[i] = mapG[i] / 255;
8791      bufferB[i] = mapB[i] / 255;
8792    }
8793    return [bufferR.join(","), bufferG.join(","), bufferB.join(",")];
8794  }
8795  #createUrl(id) {
8796    if (this.#baseUrl === undefined) {
8797      this.#baseUrl = "";
8798      const url = this.#document.URL;
8799      if (url !== this.#document.baseURI) {
8800        if (isDataScheme(url)) {
8801          warn('#createUrl: ignore "data:"-URL for performance reasons.');
8802        } else {
8803          this.#baseUrl = updateUrlHash(url, "");
8804        }
8805      }
8806    }
8807    return `url(${this.#baseUrl}#${id})`;
8808  }
8809  addFilter(maps) {
8810    if (!maps) {
8811      return "none";
8812    }
8813    let value = this.#cache.get(maps);
8814    if (value) {
8815      return value;
8816    }
8817    const [tableR, tableG, tableB] = this.#createTables(maps);
8818    const key = maps.length === 1 ? tableR : `${tableR}${tableG}${tableB}`;
8819    value = this.#cache.get(key);
8820    if (value) {
8821      this.#cache.set(maps, value);
8822      return value;
8823    }
8824    const id = `g_${this.#docId}_transfer_map_${this.#id++}`;
8825    const url = this.#createUrl(id);
8826    this.#cache.set(maps, url);
8827    this.#cache.set(key, url);
8828    const filter = this.#createFilter(id);
8829    this.#addTransferMapConversion(tableR, tableG, tableB, filter);
8830    return url;
8831  }
8832  addHCMFilter(fgColor, bgColor) {
8833    const key = `${fgColor}-${bgColor}`;
8834    const filterName = "base";
8835    let info = this.#hcmCache.get(filterName);
8836    if (info?.key === key) {
8837      return info.url;
8838    }
8839    if (info) {
8840      info.filter?.remove();
8841      info.key = key;
8842      info.url = "none";
8843      info.filter = null;
8844    } else {
8845      info = {
8846        key,
8847        url: "none",
8848        filter: null
8849      };
8850      this.#hcmCache.set(filterName, info);
8851    }
8852    if (!fgColor || !bgColor) {
8853      return info.url;
8854    }
8855    const fgRGB = this.#getRGB(fgColor);
8856    fgColor = Util.makeHexColor(...fgRGB);
8857    const bgRGB = this.#getRGB(bgColor);
8858    bgColor = Util.makeHexColor(...bgRGB);
8859    this.#defs.style.color = "";
8860    if (fgColor === "#000000" && bgColor === "#ffffff" || fgColor === bgColor) {
8861      return info.url;
8862    }
8863    const map = new Array(256);
8864    for (let i = 0; i <= 255; i++) {
8865      const x = i / 255;
8866      map[i] = x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4;
8867    }
8868    const table = map.join(",");
8869    const id = `g_${this.#docId}_hcm_filter`;
8870    const filter = info.filter = this.#createFilter(id);
8871    this.#addTransferMapConversion(table, table, table, filter);
8872    this.#addGrayConversion(filter);
8873    const getSteps = (c, n) => {
8874      const start = fgRGB[c] / 255;
8875      const end = bgRGB[c] / 255;
8876      const arr = new Array(n + 1);
8877      for (let i = 0; i <= n; i++) {
8878        arr[i] = start + i / n * (end - start);
8879      }
8880      return arr.join(",");
8881    };
8882    this.#addTransferMapConversion(getSteps(0, 5), getSteps(1, 5), getSteps(2, 5), filter);
8883    info.url = this.#createUrl(id);
8884    return info.url;
8885  }
8886  addAlphaFilter(map) {
8887    let value = this.#cache.get(map);
8888    if (value) {
8889      return value;
8890    }
8891    const [tableA] = this.#createTables([map]);
8892    const key = `alpha_${tableA}`;
8893    value = this.#cache.get(key);
8894    if (value) {
8895      this.#cache.set(map, value);
8896      return value;
8897    }
8898    const id = `g_${this.#docId}_alpha_map_${this.#id++}`;
8899    const url = this.#createUrl(id);
8900    this.#cache.set(map, url);
8901    this.#cache.set(key, url);
8902    const filter = this.#createFilter(id);
8903    this.#addTransferMapAlphaConversion(tableA, filter);
8904    return url;
8905  }
8906  addLuminosityFilter(map) {
8907    let value = this.#cache.get(map || "luminosity");
8908    if (value) {
8909      return value;
8910    }
8911    let tableA, key;
8912    if (map) {
8913      [tableA] = this.#createTables([map]);
8914      key = `luminosity_${tableA}`;
8915    } else {
8916      key = "luminosity";
8917    }
8918    value = this.#cache.get(key);
8919    if (value) {
8920      this.#cache.set(map, value);
8921      return value;
8922    }
8923    const id = `g_${this.#docId}_luminosity_map_${this.#id++}`;
8924    const url = this.#createUrl(id);
8925    this.#cache.set(map, url);
8926    this.#cache.set(key, url);
8927    const filter = this.#createFilter(id);
8928    this.#addLuminosityConversion(filter);
8929    if (map) {
8930      this.#addTransferMapAlphaConversion(tableA, filter);
8931    }
8932    return url;
8933  }
8934  addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) {
8935    const key = `${fgColor}-${bgColor}-${newFgColor}-${newBgColor}`;
8936    let info = this.#hcmCache.get(filterName);
8937    if (info?.key === key) {
8938      return info.url;
8939    }
8940    if (info) {
8941      info.filter?.remove();
8942      info.key = key;
8943      info.url = "none";
8944      info.filter = null;
8945    } else {
8946      info = {
8947        key,
8948        url: "none",
8949        filter: null
8950      };
8951      this.#hcmCache.set(filterName, info);
8952    }
8953    if (!fgColor || !bgColor) {
8954      return info.url;
8955    }
8956    const [fgRGB, bgRGB] = [fgColor, bgColor].map(this.#getRGB.bind(this));
8957    let fgGray = Math.round(0.2126 * fgRGB[0] + 0.7152 * fgRGB[1] + 0.0722 * fgRGB[2]);
8958    let bgGray = Math.round(0.2126 * bgRGB[0] + 0.7152 * bgRGB[1] + 0.0722 * bgRGB[2]);
8959    let [newFgRGB, newBgRGB] = [newFgColor, newBgColor].map(this.#getRGB.bind(this));
8960    if (bgGray < fgGray) {
8961      [fgGray, bgGray, newFgRGB, newBgRGB] = [bgGray, fgGray, newBgRGB, newFgRGB];
8962    }
8963    this.#defs.style.color = "";
8964    const getSteps = (fg, bg, n) => {
8965      const arr = new Array(256);
8966      const step = (bgGray - fgGray) / n;
8967      const newStart = fg / 255;
8968      const newStep = (bg - fg) / (255 * n);
8969      let prev = 0;
8970      for (let i = 0; i <= n; i++) {
8971        const k = Math.round(fgGray + i * step);
8972        const value = newStart + i * newStep;
8973        for (let j = prev; j <= k; j++) {
8974          arr[j] = value;
8975        }
8976        prev = k + 1;
8977      }
8978      for (let i = prev; i < 256; i++) {
8979        arr[i] = arr[prev - 1];
8980      }
8981      return arr.join(",");
8982    };
8983    const id = `g_${this.#docId}_hcm_${filterName}_filter`;
8984    const filter = info.filter = this.#createFilter(id);
8985    this.#addGrayConversion(filter);
8986    this.#addTransferMapConversion(getSteps(newFgRGB[0], newBgRGB[0], 5), getSteps(newFgRGB[1], newBgRGB[1], 5), getSteps(newFgRGB[2], newBgRGB[2], 5), filter);
8987    info.url = this.#createUrl(id);
8988    return info.url;
8989  }
8990  destroy(keepHCM = false) {
8991    if (keepHCM && this.#_hcmCache?.size) {
8992      return;
8993    }
8994    this.#_defs?.parentNode.parentNode.remove();
8995    this.#_defs = null;
8996    this.#_cache?.clear();
8997    this.#_cache = null;
8998    this.#_hcmCache?.clear();
8999    this.#_hcmCache = null;
9000    this.#id = 0;
9001  }
9002  #addLuminosityConversion(filter) {
9003    const feColorMatrix = this.#document.createElementNS(SVG_NS, "feColorMatrix");
9004    feColorMatrix.setAttribute("type", "matrix");
9005    feColorMatrix.setAttribute("values", "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0.59 0.11 0 0");
9006    filter.append(feColorMatrix);
9007  }
9008  #addGrayConversion(filter) {
9009    const feColorMatrix = this.#document.createElementNS(SVG_NS, "feColorMatrix");
9010    feColorMatrix.setAttribute("type", "matrix");
9011    feColorMatrix.setAttribute("values", "0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0");
9012    filter.append(feColorMatrix);
9013  }
9014  #createFilter(id) {
9015    const filter = this.#document.createElementNS(SVG_NS, "filter");
9016    filter.setAttribute("color-interpolation-filters", "sRGB");
9017    filter.setAttribute("id", id);
9018    this.#defs.append(filter);
9019    return filter;
9020  }
9021  #appendFeFunc(feComponentTransfer, func, table) {
9022    const feFunc = this.#document.createElementNS(SVG_NS, func);
9023    feFunc.setAttribute("type", "discrete");
9024    feFunc.setAttribute("tableValues", table);
9025    feComponentTransfer.append(feFunc);
9026  }
9027  #addTransferMapConversion(rTable, gTable, bTable, filter) {
9028    const feComponentTransfer = this.#document.createElementNS(SVG_NS, "feComponentTransfer");
9029    filter.append(feComponentTransfer);
9030    this.#appendFeFunc(feComponentTransfer, "feFuncR", rTable);
9031    this.#appendFeFunc(feComponentTransfer, "feFuncG", gTable);
9032    this.#appendFeFunc(feComponentTransfer, "feFuncB", bTable);
9033  }
9034  #addTransferMapAlphaConversion(aTable, filter) {
9035    const feComponentTransfer = this.#document.createElementNS(SVG_NS, "feComponentTransfer");
9036    filter.append(feComponentTransfer);
9037    this.#appendFeFunc(feComponentTransfer, "feFuncA", aTable);
9038  }
9039  #getRGB(color) {
9040    this.#defs.style.color = color;
9041    return getRGB(getComputedStyle(this.#defs).getPropertyValue("color"));
9042  }
9043}
9044
9045;// ./src/display/standard_fontdata_factory.js
9046
9047
9048class BaseStandardFontDataFactory {
9049  constructor({
9050    baseUrl = null
9051  }) {
9052    this.baseUrl = baseUrl;
9053  }
9054  async fetch({
9055    filename
9056  }) {
9057    if (!this.baseUrl) {
9058      throw new Error("Ensure that the `standardFontDataUrl` API parameter is provided.");
9059    }
9060    if (!filename) {
9061      throw new Error("Font filename must be specified.");
9062    }
9063    const url = `${this.baseUrl}${filename}`;
9064    return this._fetch(url).catch(reason => {
9065      throw new Error(`Unable to load font data at: ${url}`);
9066    });
9067  }
9068  async _fetch(url) {
9069    unreachable("Abstract method `_fetch` called.");
9070  }
9071}
9072class DOMStandardFontDataFactory extends BaseStandardFontDataFactory {
9073  async _fetch(url) {
9074    const data = await fetchData(url, "arraybuffer");
9075    return new Uint8Array(data);
9076  }
9077}
9078
9079;// ./src/display/wasm_factory.js
9080
9081
9082class BaseWasmFactory {
9083  constructor({
9084    baseUrl = null
9085  }) {
9086    this.baseUrl = baseUrl;
9087  }
9088  async fetch({
9089    filename
9090  }) {
9091    if (!this.baseUrl) {
9092      throw new Error("Ensure that the `wasmUrl` API parameter is provided.");
9093    }
9094    if (!filename) {
9095      throw new Error("Wasm filename must be specified.");
9096    }
9097    const url = `${this.baseUrl}${filename}`;
9098    return this._fetch(url).catch(reason => {
9099      throw new Error(`Unable to load wasm data at: ${url}`);
9100    });
9101  }
9102  async _fetch(url) {
9103    unreachable("Abstract method `_fetch` called.");
9104  }
9105}
9106class DOMWasmFactory extends BaseWasmFactory {
9107  async _fetch(url) {
9108    const data = await fetchData(url, "arraybuffer");
9109    return new Uint8Array(data);
9110  }
9111}
9112
9113;// ./src/display/node_utils.js
9114
9115
9116
9117
9118
9119
9120if (isNodeJS) {
9121  warn("Please use the `legacy` build in Node.js environments.");
9122}
9123async function node_utils_fetchData(url) {
9124  const fs = process.getBuiltinModule("fs");
9125  const data = await fs.promises.readFile(url);
9126  return new Uint8Array(data);
9127}
9128class NodeFilterFactory extends BaseFilterFactory {}
9129class NodeCanvasFactory extends BaseCanvasFactory {
9130  _createCanvas(width, height) {
9131    const require = process.getBuiltinModule("module").createRequire(import.meta.url);
9132    const canvas = require("@napi-rs/canvas");
9133    return canvas.createCanvas(width, height);
9134  }
9135}
9136class NodeCMapReaderFactory extends BaseCMapReaderFactory {
9137  async _fetch(url) {
9138    return node_utils_fetchData(url);
9139  }
9140}
9141class NodeStandardFontDataFactory extends BaseStandardFontDataFactory {
9142  async _fetch(url) {
9143    return node_utils_fetchData(url);
9144  }
9145}
9146class NodeWasmFactory extends BaseWasmFactory {
9147  async _fetch(url) {
9148    return node_utils_fetchData(url);
9149  }
9150}
9151
9152;// ./src/display/canvas_dependency_tracker.js
9153
9154const FORCED_DEPENDENCY_LABEL = "__forcedDependency";
9155const {
9156  floor,
9157  ceil
9158} = Math;
9159function expandBBox(array, index, minX, minY, maxX, maxY) {
9160  array[index * 4 + 0] = Math.min(array[index * 4 + 0], minX);
9161  array[index * 4 + 1] = Math.min(array[index * 4 + 1], minY);
9162  array[index * 4 + 2] = Math.max(array[index * 4 + 2], maxX);
9163  array[index * 4 + 3] = Math.max(array[index * 4 + 3], maxY);
9164}
9165const EMPTY_BBOX = new Uint32Array(new Uint8Array([255, 255, 0, 0]).buffer)[0];
9166class BBoxReader {
9167  #bboxes;
9168  #coords;
9169  constructor(bboxes, coords) {
9170    this.#bboxes = bboxes;
9171    this.#coords = coords;
9172  }
9173  get length() {
9174    return this.#bboxes.length;
9175  }
9176  isEmpty(i) {
9177    return this.#bboxes[i] === EMPTY_BBOX;
9178  }
9179  minX(i) {
9180    return this.#coords[i * 4 + 0] / 256;
9181  }
9182  minY(i) {
9183    return this.#coords[i * 4 + 1] / 256;
9184  }
9185  maxX(i) {
9186    return (this.#coords[i * 4 + 2] + 1) / 256;
9187  }
9188  maxY(i) {
9189    return (this.#coords[i * 4 + 3] + 1) / 256;
9190  }
9191}
9192const ensureDebugMetadata = (map, key) => {
9193  if (!map) {
9194    return undefined;
9195  }
9196  let value = map.get(key);
9197  if (!value) {
9198    value = {
9199      dependencies: new Set(),
9200      isRenderingOperation: false
9201    };
9202    map.set(key, value);
9203  }
9204  return value;
9205};
9206class CanvasDependencyTracker {
9207  #simple = {
9208    __proto__: null
9209  };
9210  #incremental = {
9211    __proto__: null,
9212    transform: [],
9213    moveText: [],
9214    sameLineText: [],
9215    [FORCED_DEPENDENCY_LABEL]: []
9216  };
9217  #namedDependencies = new Map();
9218  #savesStack = [];
9219  #markedContentStack = [];
9220  #baseTransformStack = [[1, 0, 0, 1, 0, 0]];
9221  #clipBox = [-Infinity, -Infinity, Infinity, Infinity];
9222  #pendingBBox = new Float64Array([Infinity, Infinity, -Infinity, -Infinity]);
9223  #pendingBBoxIdx = -1;
9224  #pendingDependencies = new Set();
9225  #operations = new Map();
9226  #fontBBoxTrustworthy = new Map();
9227  #canvasWidth;
9228  #canvasHeight;
9229  #bboxesCoords;
9230  #bboxes;
9231  #debugMetadata;
9232  constructor(canvas, operationsCount, recordDebugMetadata = false) {
9233    this.#canvasWidth = canvas.width;
9234    this.#canvasHeight = canvas.height;
9235    this.#initializeBBoxes(operationsCount);
9236    if (recordDebugMetadata) {
9237      this.#debugMetadata = new Map();
9238    }
9239  }
9240  growOperationsCount(operationsCount) {
9241    if (operationsCount >= this.#bboxes.length) {
9242      this.#initializeBBoxes(operationsCount, this.#bboxes);
9243    }
9244  }
9245  #initializeBBoxes(operationsCount, oldBBoxes) {
9246    const buffer = new ArrayBuffer(operationsCount * 4);
9247    this.#bboxesCoords = new Uint8ClampedArray(buffer);
9248    this.#bboxes = new Uint32Array(buffer);
9249    if (oldBBoxes && oldBBoxes.length > 0) {
9250      this.#bboxes.set(oldBBoxes);
9251      this.#bboxes.fill(EMPTY_BBOX, oldBBoxes.length);
9252    } else {
9253      this.#bboxes.fill(EMPTY_BBOX);
9254    }
9255  }
9256  save(opIdx) {
9257    this.#simple = {
9258      __proto__: this.#simple
9259    };
9260    this.#incremental = {
9261      __proto__: this.#incremental,
9262      transform: {
9263        __proto__: this.#incremental.transform
9264      },
9265      moveText: {
9266        __proto__: this.#incremental.moveText
9267      },
9268      sameLineText: {
9269        __proto__: this.#incremental.sameLineText
9270      },
9271      [FORCED_DEPENDENCY_LABEL]: {
9272        __proto__: this.#incremental[FORCED_DEPENDENCY_LABEL]
9273      }
9274    };
9275    this.#clipBox = {
9276      __proto__: this.#clipBox
9277    };
9278    this.#savesStack.push(opIdx);
9279    return this;
9280  }
9281  restore(opIdx) {
9282    const previous = Object.getPrototypeOf(this.#simple);
9283    if (previous === null) {
9284      return this;
9285    }
9286    this.#simple = previous;
9287    this.#incremental = Object.getPrototypeOf(this.#incremental);
9288    this.#clipBox = Object.getPrototypeOf(this.#clipBox);
9289    const lastSave = this.#savesStack.pop();
9290    if (lastSave !== undefined) {
9291      ensureDebugMetadata(this.#debugMetadata, opIdx)?.dependencies.add(lastSave);
9292      this.#bboxes[opIdx] = this.#bboxes[lastSave];
9293    }
9294    return this;
9295  }
9296  recordOpenMarker(idx) {
9297    this.#savesStack.push(idx);
9298    return this;
9299  }
9300  getOpenMarker() {
9301    if (this.#savesStack.length === 0) {
9302      return null;
9303    }
9304    return this.#savesStack.at(-1);
9305  }
9306  recordCloseMarker(opIdx) {
9307    const lastSave = this.#savesStack.pop();
9308    if (lastSave !== undefined) {
9309      ensureDebugMetadata(this.#debugMetadata, opIdx)?.dependencies.add(lastSave);
9310      this.#bboxes[opIdx] = this.#bboxes[lastSave];
9311    }
9312    return this;
9313  }
9314  beginMarkedContent(opIdx) {
9315    this.#markedContentStack.push(opIdx);
9316    return this;
9317  }
9318  endMarkedContent(opIdx) {
9319    const lastSave = this.#markedContentStack.pop();
9320    if (lastSave !== undefined) {
9321      ensureDebugMetadata(this.#debugMetadata, opIdx)?.dependencies.add(lastSave);
9322      this.#bboxes[opIdx] = this.#bboxes[lastSave];
9323    }
9324    return this;
9325  }
9326  pushBaseTransform(ctx) {
9327    this.#baseTransformStack.push(Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx.getTransform()));
9328    return this;
9329  }
9330  popBaseTransform() {
9331    if (this.#baseTransformStack.length > 1) {
9332      this.#baseTransformStack.pop();
9333    }
9334    return this;
9335  }
9336  recordSimpleData(name, idx) {
9337    this.#simple[name] = idx;
9338    return this;
9339  }
9340  recordIncrementalData(name, idx) {
9341    this.#incremental[name].push(idx);
9342    return this;
9343  }
9344  resetIncrementalData(name, idx) {
9345    this.#incremental[name].length = 0;
9346    return this;
9347  }
9348  recordNamedData(name, idx) {
9349    this.#namedDependencies.set(name, idx);
9350    return this;
9351  }
9352  recordSimpleDataFromNamed(name, depName, fallbackIdx) {
9353    this.#simple[name] = this.#namedDependencies.get(depName) ?? fallbackIdx;
9354  }
9355  recordFutureForcedDependency(name, idx) {
9356    this.recordIncrementalData(FORCED_DEPENDENCY_LABEL, idx);
9357    return this;
9358  }
9359  inheritSimpleDataAsFutureForcedDependencies(names) {
9360    for (const name of names) {
9361      if (name in this.#simple) {
9362        this.recordFutureForcedDependency(name, this.#simple[name]);
9363      }
9364    }
9365    return this;
9366  }
9367  inheritPendingDependenciesAsFutureForcedDependencies() {
9368    for (const dep of this.#pendingDependencies) {
9369      this.recordFutureForcedDependency(FORCED_DEPENDENCY_LABEL, dep);
9370    }
9371    return this;
9372  }
9373  resetBBox(idx) {
9374    if (this.#pendingBBoxIdx !== idx) {
9375      this.#pendingBBoxIdx = idx;
9376      this.#pendingBBox[0] = Infinity;
9377      this.#pendingBBox[1] = Infinity;
9378      this.#pendingBBox[2] = -Infinity;
9379      this.#pendingBBox[3] = -Infinity;
9380    }
9381    return this;
9382  }
9383  recordClipBox(idx, ctx, minX, maxX, minY, maxY) {
9384    const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx.getTransform());
9385    const clipBox = [Infinity, Infinity, -Infinity, -Infinity];
9386    Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, clipBox);
9387    const intersection = Util.intersect(this.#clipBox, clipBox);
9388    if (intersection) {
9389      this.#clipBox[0] = intersection[0];
9390      this.#clipBox[1] = intersection[1];
9391      this.#clipBox[2] = intersection[2];
9392      this.#clipBox[3] = intersection[3];
9393    } else {
9394      this.#clipBox[0] = this.#clipBox[1] = Infinity;
9395      this.#clipBox[2] = this.#clipBox[3] = -Infinity;
9396    }
9397    return this;
9398  }
9399  recordBBox(idx, ctx, minX, maxX, minY, maxY) {
9400    const clipBox = this.#clipBox;
9401    if (clipBox[0] === Infinity) {
9402      return this;
9403    }
9404    const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx.getTransform());
9405    if (clipBox[0] === -Infinity) {
9406      Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, this.#pendingBBox);
9407      return this;
9408    }
9409    const bbox = [Infinity, Infinity, -Infinity, -Infinity];
9410    Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, bbox);
9411    this.#pendingBBox[0] = Math.min(this.#pendingBBox[0], Math.max(bbox[0], clipBox[0]));
9412    this.#pendingBBox[1] = Math.min(this.#pendingBBox[1], Math.max(bbox[1], clipBox[1]));
9413    this.#pendingBBox[2] = Math.max(this.#pendingBBox[2], Math.min(bbox[2], clipBox[2]));
9414    this.#pendingBBox[3] = Math.max(this.#pendingBBox[3], Math.min(bbox[3], clipBox[3]));
9415    return this;
9416  }
9417  recordCharacterBBox(idx, ctx, font, scale = 1, x = 0, y = 0, getMeasure) {
9418    const fontBBox = font.bbox;
9419    let isBBoxTrustworthy;
9420    let computedBBox;
9421    if (fontBBox) {
9422      isBBoxTrustworthy = fontBBox[2] !== fontBBox[0] && fontBBox[3] !== fontBBox[1] && this.#fontBBoxTrustworthy.get(font);
9423      if (isBBoxTrustworthy !== false) {
9424        computedBBox = [0, 0, 0, 0];
9425        Util.axialAlignedBoundingBox(fontBBox, font.fontMatrix, computedBBox);
9426        if (scale !== 1 || x !== 0 || y !== 0) {
9427          Util.scaleMinMax([scale, 0, 0, -scale, x, y], computedBBox);
9428        }
9429        if (isBBoxTrustworthy) {
9430          return this.recordBBox(idx, ctx, computedBBox[0], computedBBox[2], computedBBox[1], computedBBox[3]);
9431        }
9432      }
9433    }
9434    if (!getMeasure) {
9435      return this.recordFullPageBBox(idx);
9436    }
9437    const measure = getMeasure();
9438    if (fontBBox && computedBBox && isBBoxTrustworthy === undefined) {
9439      isBBoxTrustworthy = computedBBox[0] <= x - measure.actualBoundingBoxLeft && computedBBox[2] >= x + measure.actualBoundingBoxRight && computedBBox[1] <= y - measure.actualBoundingBoxAscent && computedBBox[3] >= y + measure.actualBoundingBoxDescent;
9440      this.#fontBBoxTrustworthy.set(font, isBBoxTrustworthy);
9441      if (isBBoxTrustworthy) {
9442        return this.recordBBox(idx, ctx, computedBBox[0], computedBBox[2], computedBBox[1], computedBBox[3]);
9443      }
9444    }
9445    return this.recordBBox(idx, ctx, x - measure.actualBoundingBoxLeft, x + measure.actualBoundingBoxRight, y - measure.actualBoundingBoxAscent, y + measure.actualBoundingBoxDescent);
9446  }
9447  recordFullPageBBox(idx) {
9448    this.#pendingBBox[0] = Math.max(0, this.#clipBox[0]);
9449    this.#pendingBBox[1] = Math.max(0, this.#clipBox[1]);
9450    this.#pendingBBox[2] = Math.min(this.#canvasWidth, this.#clipBox[2]);
9451    this.#pendingBBox[3] = Math.min(this.#canvasHeight, this.#clipBox[3]);
9452    return this;
9453  }
9454  getSimpleIndex(dependencyName) {
9455    return this.#simple[dependencyName];
9456  }
9457  recordDependencies(idx, dependencyNames) {
9458    const pendingDependencies = this.#pendingDependencies;
9459    const simple = this.#simple;
9460    const incremental = this.#incremental;
9461    for (const name of dependencyNames) {
9462      if (name in this.#simple) {
9463        pendingDependencies.add(simple[name]);
9464      } else if (name in incremental) {
9465        incremental[name].forEach(pendingDependencies.add, pendingDependencies);
9466      }
9467    }
9468    return this;
9469  }
9470  recordNamedDependency(idx, name) {
9471    if (this.#namedDependencies.has(name)) {
9472      this.#pendingDependencies.add(this.#namedDependencies.get(name));
9473    }
9474    return this;
9475  }
9476  recordOperation(idx, preserve = false) {
9477    this.recordDependencies(idx, [FORCED_DEPENDENCY_LABEL]);
9478    if (this.#debugMetadata) {
9479      const metadata = ensureDebugMetadata(this.#debugMetadata, idx);
9480      const {
9481        dependencies
9482      } = metadata;
9483      this.#pendingDependencies.forEach(dependencies.add, dependencies);
9484      this.#savesStack.forEach(dependencies.add, dependencies);
9485      this.#markedContentStack.forEach(dependencies.add, dependencies);
9486      dependencies.delete(idx);
9487      metadata.isRenderingOperation = true;
9488    }
9489    if (this.#pendingBBoxIdx === idx) {
9490      const minX = floor(this.#pendingBBox[0] * 256 / this.#canvasWidth);
9491      const minY = floor(this.#pendingBBox[1] * 256 / this.#canvasHeight);
9492      const maxX = ceil(this.#pendingBBox[2] * 256 / this.#canvasWidth);
9493      const maxY = ceil(this.#pendingBBox[3] * 256 / this.#canvasHeight);
9494      expandBBox(this.#bboxesCoords, idx, minX, minY, maxX, maxY);
9495      for (const depIdx of this.#pendingDependencies) {
9496        if (depIdx !== idx) {
9497          expandBBox(this.#bboxesCoords, depIdx, minX, minY, maxX, maxY);
9498        }
9499      }
9500      for (const saveIdx of this.#savesStack) {
9501        if (saveIdx !== idx) {
9502          expandBBox(this.#bboxesCoords, saveIdx, minX, minY, maxX, maxY);
9503        }
9504      }
9505      for (const saveIdx of this.#markedContentStack) {
9506        if (saveIdx !== idx) {
9507          expandBBox(this.#bboxesCoords, saveIdx, minX, minY, maxX, maxY);
9508        }
9509      }
9510      if (!preserve) {
9511        this.#pendingDependencies.clear();
9512        this.#pendingBBoxIdx = -1;
9513      }
9514    }
9515    return this;
9516  }
9517  recordShowTextOperation(idx, preserve = false) {
9518    const deps = Array.from(this.#pendingDependencies);
9519    this.recordOperation(idx, preserve);
9520    this.recordIncrementalData("sameLineText", idx);
9521    for (const dep of deps) {
9522      this.recordIncrementalData("sameLineText", dep);
9523    }
9524    return this;
9525  }
9526  bboxToClipBoxDropOperation(idx, preserve = false) {
9527    if (this.#pendingBBoxIdx === idx) {
9528      this.#pendingBBoxIdx = -1;
9529      this.#clipBox[0] = Math.max(this.#clipBox[0], this.#pendingBBox[0]);
9530      this.#clipBox[1] = Math.max(this.#clipBox[1], this.#pendingBBox[1]);
9531      this.#clipBox[2] = Math.min(this.#clipBox[2], this.#pendingBBox[2]);
9532      this.#clipBox[3] = Math.min(this.#clipBox[3], this.#pendingBBox[3]);
9533      if (!preserve) {
9534        this.#pendingDependencies.clear();
9535      }
9536    }
9537    return this;
9538  }
9539  _takePendingDependencies() {
9540    const pendingDependencies = this.#pendingDependencies;
9541    this.#pendingDependencies = new Set();
9542    return pendingDependencies;
9543  }
9544  _extractOperation(idx) {
9545    const operation = this.#operations.get(idx);
9546    this.#operations.delete(idx);
9547    return operation;
9548  }
9549  _pushPendingDependencies(dependencies) {
9550    for (const dep of dependencies) {
9551      this.#pendingDependencies.add(dep);
9552    }
9553  }
9554  take() {
9555    this.#fontBBoxTrustworthy.clear();
9556    return new BBoxReader(this.#bboxes, this.#bboxesCoords);
9557  }
9558  takeDebugMetadata() {
9559    return this.#debugMetadata;
9560  }
9561}
9562class CanvasNestedDependencyTracker {
9563  #dependencyTracker;
9564  #opIdx;
9565  #ignoreBBoxes;
9566  #nestingLevel = 0;
9567  #savesLevel = 0;
9568  constructor(dependencyTracker, opIdx, ignoreBBoxes) {
9569    if (dependencyTracker instanceof CanvasNestedDependencyTracker && dependencyTracker.#ignoreBBoxes === !!ignoreBBoxes) {
9570      return dependencyTracker;
9571    }
9572    this.#dependencyTracker = dependencyTracker;
9573    this.#opIdx = opIdx;
9574    this.#ignoreBBoxes = !!ignoreBBoxes;
9575  }
9576  growOperationsCount() {
9577    throw new Error("Unreachable");
9578  }
9579  save(opIdx) {
9580    this.#savesLevel++;
9581    this.#dependencyTracker.save(this.#opIdx);
9582    return this;
9583  }
9584  restore(opIdx) {
9585    if (this.#savesLevel > 0) {
9586      this.#dependencyTracker.restore(this.#opIdx);
9587      this.#savesLevel--;
9588    }
9589    return this;
9590  }
9591  recordOpenMarker(idx) {
9592    this.#nestingLevel++;
9593    return this;
9594  }
9595  getOpenMarker() {
9596    return this.#nestingLevel > 0 ? this.#opIdx : this.#dependencyTracker.getOpenMarker();
9597  }
9598  recordCloseMarker(idx) {
9599    this.#nestingLevel--;
9600    return this;
9601  }
9602  beginMarkedContent(opIdx) {
9603    return this;
9604  }
9605  endMarkedContent(opIdx) {
9606    return this;
9607  }
9608  pushBaseTransform(ctx) {
9609    this.#dependencyTracker.pushBaseTransform(ctx);
9610    return this;
9611  }
9612  popBaseTransform() {
9613    this.#dependencyTracker.popBaseTransform();
9614    return this;
9615  }
9616  recordSimpleData(name, idx) {
9617    this.#dependencyTracker.recordSimpleData(name, this.#opIdx);
9618    return this;
9619  }
9620  recordIncrementalData(name, idx) {
9621    this.#dependencyTracker.recordIncrementalData(name, this.#opIdx);
9622    return this;
9623  }
9624  resetIncrementalData(name, idx) {
9625    this.#dependencyTracker.resetIncrementalData(name, this.#opIdx);
9626    return this;
9627  }
9628  recordNamedData(name, idx) {
9629    return this;
9630  }
9631  recordSimpleDataFromNamed(name, depName, fallbackIdx) {
9632    this.#dependencyTracker.recordSimpleDataFromNamed(name, depName, this.#opIdx);
9633    return this;
9634  }
9635  recordFutureForcedDependency(name, idx) {
9636    this.#dependencyTracker.recordFutureForcedDependency(name, this.#opIdx);
9637    return this;
9638  }
9639  inheritSimpleDataAsFutureForcedDependencies(names) {
9640    this.#dependencyTracker.inheritSimpleDataAsFutureForcedDependencies(names);
9641    return this;
9642  }
9643  inheritPendingDependenciesAsFutureForcedDependencies() {
9644    this.#dependencyTracker.inheritPendingDependenciesAsFutureForcedDependencies();
9645    return this;
9646  }
9647  resetBBox(idx) {
9648    if (!this.#ignoreBBoxes) {
9649      this.#dependencyTracker.resetBBox(this.#opIdx);
9650    }
9651    return this;
9652  }
9653  recordClipBox(idx, ctx, minX, maxX, minY, maxY) {
9654    if (!this.#ignoreBBoxes) {
9655      this.#dependencyTracker.recordClipBox(this.#opIdx, ctx, minX, maxX, minY, maxY);
9656    }
9657    return this;
9658  }
9659  recordBBox(idx, ctx, minX, maxX, minY, maxY) {
9660    if (!this.#ignoreBBoxes) {
9661      this.#dependencyTracker.recordBBox(this.#opIdx, ctx, minX, maxX, minY, maxY);
9662    }
9663    return this;
9664  }
9665  recordCharacterBBox(idx, ctx, font, scale, x, y, getMeasure) {
9666    if (!this.#ignoreBBoxes) {
9667      this.#dependencyTracker.recordCharacterBBox(this.#opIdx, ctx, font, scale, x, y, getMeasure);
9668    }
9669    return this;
9670  }
9671  recordFullPageBBox(idx) {
9672    if (!this.#ignoreBBoxes) {
9673      this.#dependencyTracker.recordFullPageBBox(this.#opIdx);
9674    }
9675    return this;
9676  }
9677  getSimpleIndex(dependencyName) {
9678    return this.#dependencyTracker.getSimpleIndex(dependencyName);
9679  }
9680  recordDependencies(idx, dependencyNames) {
9681    this.#dependencyTracker.recordDependencies(this.#opIdx, dependencyNames);
9682    return this;
9683  }
9684  recordNamedDependency(idx, name) {
9685    this.#dependencyTracker.recordNamedDependency(this.#opIdx, name);
9686    return this;
9687  }
9688  recordOperation(idx) {
9689    this.#dependencyTracker.recordOperation(this.#opIdx, true);
9690    return this;
9691  }
9692  recordShowTextOperation(idx) {
9693    this.#dependencyTracker.recordShowTextOperation(this.#opIdx, true);
9694    return this;
9695  }
9696  bboxToClipBoxDropOperation(idx) {
9697    if (!this.#ignoreBBoxes) {
9698      this.#dependencyTracker.bboxToClipBoxDropOperation(this.#opIdx, true);
9699    }
9700    return this;
9701  }
9702  take() {
9703    throw new Error("Unreachable");
9704  }
9705  takeDebugMetadata() {
9706    throw new Error("Unreachable");
9707  }
9708}
9709const Dependencies = {
9710  stroke: ["path", "transform", "filter", "strokeColor", "strokeAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "dash"],
9711  fill: ["path", "transform", "filter", "fillColor", "fillAlpha", "globalCompositeOperation", "SMask"],
9712  imageXObject: ["transform", "SMask", "filter", "fillAlpha", "strokeAlpha", "globalCompositeOperation"],
9713  rawFillPath: ["filter", "fillColor", "fillAlpha"],
9714  showText: ["transform", "leading", "charSpacing", "wordSpacing", "hScale", "textRise", "moveText", "textMatrix", "font", "fontObj", "filter", "fillColor", "textRenderingMode", "SMask", "fillAlpha", "strokeAlpha", "globalCompositeOperation", "sameLineText"],
9715  transform: ["transform"],
9716  transformAndFill: ["transform", "fillColor"]
9717};
9718
9719;// ./src/display/pattern_helper.js
9720
9721
9722const PathType = {
9723  FILL: "Fill",
9724  STROKE: "Stroke",
9725  SHADING: "Shading"
9726};
9727function applyBoundingBox(ctx, bbox) {
9728  if (!bbox) {
9729    return;
9730  }
9731  const width = bbox[2] - bbox[0];
9732  const height = bbox[3] - bbox[1];
9733  const region = new Path2D();
9734  region.rect(bbox[0], bbox[1], width, height);
9735  ctx.clip(region);
9736}
9737class BaseShadingPattern {
9738  isModifyingCurrentTransform() {
9739    return false;
vendor: 4,978 bytes, lines 9740-9893
9740  }
9741  getPattern() {
9742    unreachable("Abstract method `getPattern` called.");
9743  }
9744}
9745class RadialAxialShadingPattern extends BaseShadingPattern {
9746  constructor(IR) {
9747    super();
9748    this._type = IR[1];
9749    this._bbox = IR[2];
9750    this._colorStops = IR[3];
9751    this._p0 = IR[4];
9752    this._p1 = IR[5];
9753    this._r0 = IR[6];
9754    this._r1 = IR[7];
9755    this.matrix = null;
9756  }
9757  isOriginBased() {
9758    return this._p0[0] === 0 && this._p0[1] === 0 && (!this.isRadial() || this._p1[0] === 0 && this._p1[1] === 0);
9759  }
9760  isRadial() {
9761    return this._type === "radial";
9762  }
9763  _createGradient(ctx, transform = null) {
9764    let grad;
9765    let firstPoint = this._p0;
9766    let secondPoint = this._p1;
9767    if (transform) {
9768      firstPoint = firstPoint.slice();
9769      secondPoint = secondPoint.slice();
9770      Util.applyTransform(firstPoint, transform);
9771      Util.applyTransform(secondPoint, transform);
9772    }
9773    if (this._type === "axial") {
9774      grad = ctx.createLinearGradient(firstPoint[0], firstPoint[1], secondPoint[0], secondPoint[1]);
9775    } else if (this._type === "radial") {
9776      let r0 = this._r0;
9777      let r1 = this._r1;
9778      if (transform) {
9779        const scale = new Float32Array(2);
9780        Util.singularValueDecompose2dScale(transform, scale);
9781        r0 *= scale[0];
9782        r1 *= scale[0];
9783      }
9784      grad = ctx.createRadialGradient(firstPoint[0], firstPoint[1], r0, secondPoint[0], secondPoint[1], r1);
9785    }
9786    for (const colorStop of this._colorStops) {
9787      grad.addColorStop(colorStop[0], colorStop[1]);
9788    }
9789    return grad;
9790  }
9791  getPattern(ctx, owner, inverse, pathType) {
9792    let pattern;
9793    if (pathType === PathType.STROKE || pathType === PathType.FILL) {
9794      if (this.isOriginBased()) {
9795        let transf = Util.transform(inverse, owner.baseTransform);
9796        if (this.matrix) {
9797          transf = Util.transform(transf, this.matrix);
9798        }
9799        const precision = 1e-3;
9800        const n1 = Math.hypot(transf[0], transf[1]);
9801        const n2 = Math.hypot(transf[2], transf[3]);
9802        const ps = (transf[0] * transf[2] + transf[1] * transf[3]) / (n1 * n2);
9803        if (Math.abs(ps) < precision) {
9804          if (this.isRadial()) {
9805            if (Math.abs(n1 - n2) < precision) {
9806              return this._createGradient(ctx, transf);
9807            }
9808          } else {
9809            return this._createGradient(ctx, transf);
9810          }
9811        }
9812      }
9813      const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, getCurrentTransform(ctx)) || [0, 0, 0, 0];
9814      const width = Math.ceil(ownerBBox[2] - ownerBBox[0]) || 1;
9815      const height = Math.ceil(ownerBBox[3] - ownerBBox[1]) || 1;
9816      const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", width, height);
9817      const tmpCtx = tmpCanvas.context;
9818      tmpCtx.clearRect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height);
9819      tmpCtx.beginPath();
9820      tmpCtx.rect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height);
9821      tmpCtx.translate(-ownerBBox[0], -ownerBBox[1]);
9822      inverse = Util.transform(inverse, [1, 0, 0, 1, ownerBBox[0], ownerBBox[1]]);
9823      tmpCtx.transform(...owner.baseTransform);
9824      if (this.matrix) {
9825        tmpCtx.transform(...this.matrix);
9826      }
9827      applyBoundingBox(tmpCtx, this._bbox);
9828      tmpCtx.fillStyle = this._createGradient(tmpCtx);
9829      tmpCtx.fill();
9830      pattern = ctx.createPattern(tmpCanvas.canvas, "no-repeat");
9831      const domMatrix = new DOMMatrix(inverse);
9832      pattern.setTransform(domMatrix);
9833    } else {
9834      applyBoundingBox(ctx, this._bbox);
9835      pattern = this._createGradient(ctx);
9836    }
9837    return pattern;
9838  }
9839}
9840function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
9841  const coords = context.coords,
9842    colors = context.colors;
9843  const bytes = data.data,
9844    rowSize = data.width * 4;
9845  let tmp;
9846  if (coords[p1 + 1] > coords[p2 + 1]) {
9847    tmp = p1;
9848    p1 = p2;
9849    p2 = tmp;
9850    tmp = c1;
9851    c1 = c2;
9852    c2 = tmp;
9853  }
9854  if (coords[p2 + 1] > coords[p3 + 1]) {
9855    tmp = p2;
9856    p2 = p3;
9857    p3 = tmp;
9858    tmp = c2;
9859    c2 = c3;
9860    c3 = tmp;
9861  }
9862  if (coords[p1 + 1] > coords[p2 + 1]) {
9863    tmp = p1;
9864    p1 = p2;
9865    p2 = tmp;
9866    tmp = c1;
9867    c1 = c2;
9868    c2 = tmp;
9869  }
9870  const x1 = (coords[p1] + context.offsetX) * context.scaleX;
9871  const y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;
9872  const x2 = (coords[p2] + context.offsetX) * context.scaleX;
9873  const y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY;
9874  const x3 = (coords[p3] + context.offsetX) * context.scaleX;
9875  const y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY;
9876  if (y1 >= y3) {
9877    return;
9878  }
9879  const c1r = colors[c1],
9880    c1g = colors[c1 + 1],
9881    c1b = colors[c1 + 2];
9882  const c2r = colors[c2],
9883    c2g = colors[c2 + 1],
9884    c2b = colors[c2 + 2];
9885  const c3r = colors[c3],
9886    c3g = colors[c3 + 1],
9887    c3b = colors[c3 + 2];
9888  const minY = Math.round(y1),
9889    maxY = Math.round(y3);
9890  let xa, car, cag, cab;
9891  let xb, cbr, cbg, cbb;
9892  for (let y = minY; y <= maxY; y++) {
9893    if (y < y2) {
vendor: 8,643 bytes, lines 9894-10150
9894      const k = y < y1 ? 0 : (y1 - y) / (y1 - y2);
9895      xa = x1 - (x1 - x2) * k;
9896      car = c1r - (c1r - c2r) * k;
9897      cag = c1g - (c1g - c2g) * k;
9898      cab = c1b - (c1b - c2b) * k;
9899    } else {
9900      let k;
9901      if (y > y3) {
9902        k = 1;
9903      } else if (y2 === y3) {
9904        k = 0;
9905      } else {
9906        k = (y2 - y) / (y2 - y3);
9907      }
9908      xa = x2 - (x2 - x3) * k;
9909      car = c2r - (c2r - c3r) * k;
9910      cag = c2g - (c2g - c3g) * k;
9911      cab = c2b - (c2b - c3b) * k;
9912    }
9913    let k;
9914    if (y < y1) {
9915      k = 0;
9916    } else if (y > y3) {
9917      k = 1;
9918    } else {
9919      k = (y1 - y) / (y1 - y3);
9920    }
9921    xb = x1 - (x1 - x3) * k;
9922    cbr = c1r - (c1r - c3r) * k;
9923    cbg = c1g - (c1g - c3g) * k;
9924    cbb = c1b - (c1b - c3b) * k;
9925    const x1_ = Math.round(Math.min(xa, xb));
9926    const x2_ = Math.round(Math.max(xa, xb));
9927    let j = rowSize * y + x1_ * 4;
9928    for (let x = x1_; x <= x2_; x++) {
9929      k = (xa - x) / (xa - xb);
9930      if (k < 0) {
9931        k = 0;
9932      } else if (k > 1) {
9933        k = 1;
9934      }
9935      bytes[j++] = car - (car - cbr) * k | 0;
9936      bytes[j++] = cag - (cag - cbg) * k | 0;
9937      bytes[j++] = cab - (cab - cbb) * k | 0;
9938      bytes[j++] = 255;
9939    }
9940  }
9941}
9942function drawFigure(data, figure, context) {
9943  const ps = figure.coords;
9944  const cs = figure.colors;
9945  let i, ii;
9946  switch (figure.type) {
9947    case MeshFigureType.LATTICE:
9948      const verticesPerRow = figure.verticesPerRow;
9949      const rows = Math.floor(ps.length / verticesPerRow) - 1;
9950      const cols = verticesPerRow - 1;
9951      for (i = 0; i < rows; i++) {
9952        let q = i * verticesPerRow;
9953        for (let j = 0; j < cols; j++, q++) {
9954          drawTriangle(data, context, ps[q], ps[q + 1], ps[q + verticesPerRow], cs[q], cs[q + 1], cs[q + verticesPerRow]);
9955          drawTriangle(data, context, ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]);
9956        }
9957      }
9958      break;
9959    case MeshFigureType.TRIANGLES:
9960      for (i = 0, ii = ps.length; i < ii; i += 3) {
9961        drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]);
9962      }
9963      break;
9964    default:
9965      throw new Error("illegal figure");
9966  }
9967}
9968class MeshShadingPattern extends BaseShadingPattern {
9969  constructor(IR) {
9970    super();
9971    this._coords = IR[2];
9972    this._colors = IR[3];
9973    this._figures = IR[4];
9974    this._bounds = IR[5];
9975    this._bbox = IR[6];
9976    this._background = IR[7];
9977    this.matrix = null;
9978  }
9979  _createMeshCanvas(combinedScale, backgroundColor, cachedCanvases) {
9980    const EXPECTED_SCALE = 1.1;
9981    const MAX_PATTERN_SIZE = 3000;
9982    const BORDER_SIZE = 2;
9983    const offsetX = Math.floor(this._bounds[0]);
9984    const offsetY = Math.floor(this._bounds[1]);
9985    const boundsWidth = Math.ceil(this._bounds[2]) - offsetX;
9986    const boundsHeight = Math.ceil(this._bounds[3]) - offsetY;
9987    const width = Math.min(Math.ceil(Math.abs(boundsWidth * combinedScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
9988    const height = Math.min(Math.ceil(Math.abs(boundsHeight * combinedScale[1] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
9989    const scaleX = boundsWidth / width;
9990    const scaleY = boundsHeight / height;
9991    const context = {
9992      coords: this._coords,
9993      colors: this._colors,
9994      offsetX: -offsetX,
9995      offsetY: -offsetY,
9996      scaleX: 1 / scaleX,
9997      scaleY: 1 / scaleY
9998    };
9999    const paddedWidth = width + BORDER_SIZE * 2;
10000    const paddedHeight = height + BORDER_SIZE * 2;
10001    const tmpCanvas = cachedCanvases.getCanvas("mesh", paddedWidth, paddedHeight);
10002    const tmpCtx = tmpCanvas.context;
10003    const data = tmpCtx.createImageData(width, height);
10004    if (backgroundColor) {
10005      const bytes = data.data;
10006      for (let i = 0, ii = bytes.length; i < ii; i += 4) {
10007        bytes[i] = backgroundColor[0];
10008        bytes[i + 1] = backgroundColor[1];
10009        bytes[i + 2] = backgroundColor[2];
10010        bytes[i + 3] = 255;
10011      }
10012    }
10013    for (const figure of this._figures) {
10014      drawFigure(data, figure, context);
10015    }
10016    tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE);
10017    const canvas = tmpCanvas.canvas;
10018    return {
10019      canvas,
10020      offsetX: offsetX - BORDER_SIZE * scaleX,
10021      offsetY: offsetY - BORDER_SIZE * scaleY,
10022      scaleX,
10023      scaleY
10024    };
10025  }
10026  isModifyingCurrentTransform() {
10027    return true;
10028  }
10029  getPattern(ctx, owner, inverse, pathType) {
10030    applyBoundingBox(ctx, this._bbox);
10031    const scale = new Float32Array(2);
10032    if (pathType === PathType.SHADING) {
10033      Util.singularValueDecompose2dScale(getCurrentTransform(ctx), scale);
10034    } else if (this.matrix) {
10035      Util.singularValueDecompose2dScale(this.matrix, scale);
10036      const [matrixScaleX, matrixScaleY] = scale;
10037      Util.singularValueDecompose2dScale(owner.baseTransform, scale);
10038      scale[0] *= matrixScaleX;
10039      scale[1] *= matrixScaleY;
10040    } else {
10041      Util.singularValueDecompose2dScale(owner.baseTransform, scale);
10042    }
10043    const temporaryPatternCanvas = this._createMeshCanvas(scale, pathType === PathType.SHADING ? null : this._background, owner.cachedCanvases);
10044    if (pathType !== PathType.SHADING) {
10045      ctx.setTransform(...owner.baseTransform);
10046      if (this.matrix) {
10047        ctx.transform(...this.matrix);
10048      }
10049    }
10050    ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
10051    ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY);
10052    return ctx.createPattern(temporaryPatternCanvas.canvas, "no-repeat");
10053  }
10054}
10055class DummyShadingPattern extends BaseShadingPattern {
10056  getPattern() {
10057    return "hotpink";
10058  }
10059}
10060function getShadingPattern(IR) {
10061  switch (IR[0]) {
10062    case "RadialAxial":
10063      return new RadialAxialShadingPattern(IR);
10064    case "Mesh":
10065      return new MeshShadingPattern(IR);
10066    case "Dummy":
10067      return new DummyShadingPattern();
10068  }
10069  throw new Error(`Unknown IR type: ${IR[0]}`);
10070}
10071const PaintType = {
10072  COLORED: 1,
10073  UNCOLORED: 2
10074};
10075class TilingPattern {
10076  static MAX_PATTERN_SIZE = 3000;
10077  constructor(IR, ctx, canvasGraphicsFactory, baseTransform) {
10078    this.color = IR[1];
10079    this.operatorList = IR[2];
10080    this.matrix = IR[3];
10081    this.bbox = IR[4];
10082    this.xstep = IR[5];
10083    this.ystep = IR[6];
10084    this.paintType = IR[7];
10085    this.tilingType = IR[8];
10086    this.ctx = ctx;
10087    this.canvasGraphicsFactory = canvasGraphicsFactory;
10088    this.baseTransform = baseTransform;
10089  }
10090  createPatternCanvas(owner, opIdx) {
10091    const {
10092      bbox,
10093      operatorList,
10094      paintType,
10095      tilingType,
10096      color,
10097      canvasGraphicsFactory
10098    } = this;
10099    let {
10100      xstep,
10101      ystep
10102    } = this;
10103    xstep = Math.abs(xstep);
10104    ystep = Math.abs(ystep);
10105    info("TilingType: " + tilingType);
10106    const x0 = bbox[0],
10107      y0 = bbox[1],
10108      x1 = bbox[2],
10109      y1 = bbox[3];
10110    const width = x1 - x0;
10111    const height = y1 - y0;
10112    const scale = new Float32Array(2);
10113    Util.singularValueDecompose2dScale(this.matrix, scale);
10114    const [matrixScaleX, matrixScaleY] = scale;
10115    Util.singularValueDecompose2dScale(this.baseTransform, scale);
10116    const combinedScaleX = matrixScaleX * scale[0];
10117    const combinedScaleY = matrixScaleY * scale[1];
10118    let canvasWidth = width,
10119      canvasHeight = height,
10120      redrawHorizontally = false,
10121      redrawVertically = false;
10122    const xScaledStep = Math.ceil(xstep * combinedScaleX);
10123    const yScaledStep = Math.ceil(ystep * combinedScaleY);
10124    const xScaledWidth = Math.ceil(width * combinedScaleX);
10125    const yScaledHeight = Math.ceil(height * combinedScaleY);
10126    if (xScaledStep >= xScaledWidth) {
10127      canvasWidth = xstep;
10128    } else {
10129      redrawHorizontally = true;
10130    }
10131    if (yScaledStep >= yScaledHeight) {
10132      canvasHeight = ystep;
10133    } else {
10134      redrawVertically = true;
10135    }
10136    const dimx = this.getSizeAndScale(canvasWidth, this.ctx.canvas.width, combinedScaleX);
10137    const dimy = this.getSizeAndScale(canvasHeight, this.ctx.canvas.height, combinedScaleY);
10138    const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", dimx.size, dimy.size);
10139    const tmpCtx = tmpCanvas.context;
10140    const graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx, opIdx);
10141    graphics.groupLevel = owner.groupLevel;
10142    this.setFillAndStrokeStyleToContext(graphics, paintType, color);
10143    tmpCtx.translate(-dimx.scale * x0, -dimy.scale * y0);
10144    graphics.transform(0, dimx.scale, 0, 0, dimy.scale, 0, 0);
10145    tmpCtx.save();
10146    graphics.dependencyTracker?.save();
10147    this.clipBbox(graphics, x0, y0, x1, y1);
10148    graphics.baseTransform = getCurrentTransform(graphics.ctx);
10149    graphics.executeOperatorList(operatorList);
10150    graphics.endDrawing();
vendor: 6,083 bytes, lines 10151-10334
10151    graphics.dependencyTracker?.restore();
10152    tmpCtx.restore();
10153    if (redrawHorizontally || redrawVertically) {
10154      const image = tmpCanvas.canvas;
10155      if (redrawHorizontally) {
10156        canvasWidth = xstep;
10157      }
10158      if (redrawVertically) {
10159        canvasHeight = ystep;
10160      }
10161      const dimx2 = this.getSizeAndScale(canvasWidth, this.ctx.canvas.width, combinedScaleX);
10162      const dimy2 = this.getSizeAndScale(canvasHeight, this.ctx.canvas.height, combinedScaleY);
10163      const xSize = dimx2.size;
10164      const ySize = dimy2.size;
10165      const tmpCanvas2 = owner.cachedCanvases.getCanvas("pattern-workaround", xSize, ySize);
10166      const tmpCtx2 = tmpCanvas2.context;
10167      const ii = redrawHorizontally ? Math.floor(width / xstep) : 0;
10168      const jj = redrawVertically ? Math.floor(height / ystep) : 0;
10169      for (let i = 0; i <= ii; i++) {
10170        for (let j = 0; j <= jj; j++) {
10171          tmpCtx2.drawImage(image, xSize * i, ySize * j, xSize, ySize, 0, 0, xSize, ySize);
10172        }
10173      }
10174      return {
10175        canvas: tmpCanvas2.canvas,
10176        scaleX: dimx2.scale,
10177        scaleY: dimy2.scale,
10178        offsetX: x0,
10179        offsetY: y0
10180      };
10181    }
10182    return {
10183      canvas: tmpCanvas.canvas,
10184      scaleX: dimx.scale,
10185      scaleY: dimy.scale,
10186      offsetX: x0,
10187      offsetY: y0
10188    };
10189  }
10190  getSizeAndScale(step, realOutputSize, scale) {
10191    const maxSize = Math.max(TilingPattern.MAX_PATTERN_SIZE, realOutputSize);
10192    let size = Math.ceil(step * scale);
10193    if (size >= maxSize) {
10194      size = maxSize;
10195    } else {
10196      scale = size / step;
10197    }
10198    return {
10199      scale,
10200      size
10201    };
10202  }
10203  clipBbox(graphics, x0, y0, x1, y1) {
10204    const bboxWidth = x1 - x0;
10205    const bboxHeight = y1 - y0;
10206    graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight);
10207    Util.axialAlignedBoundingBox([x0, y0, x1, y1], getCurrentTransform(graphics.ctx), graphics.current.minMax);
10208    graphics.clip();
10209    graphics.endPath();
10210  }
10211  setFillAndStrokeStyleToContext(graphics, paintType, color) {
10212    const context = graphics.ctx,
10213      current = graphics.current;
10214    switch (paintType) {
10215      case PaintType.COLORED:
10216        const {
10217          fillStyle,
10218          strokeStyle
10219        } = this.ctx;
10220        context.fillStyle = current.fillColor = fillStyle;
10221        context.strokeStyle = current.strokeColor = strokeStyle;
10222        break;
10223      case PaintType.UNCOLORED:
10224        context.fillStyle = context.strokeStyle = color;
10225        current.fillColor = current.strokeColor = color;
10226        break;
10227      default:
10228        throw new FormatError(`Unsupported paint type: ${paintType}`);
10229    }
10230  }
10231  isModifyingCurrentTransform() {
10232    return false;
10233  }
10234  getPattern(ctx, owner, inverse, pathType, opIdx) {
10235    let matrix = inverse;
10236    if (pathType !== PathType.SHADING) {
10237      matrix = Util.transform(matrix, owner.baseTransform);
10238      if (this.matrix) {
10239        matrix = Util.transform(matrix, this.matrix);
10240      }
10241    }
10242    const temporaryPatternCanvas = this.createPatternCanvas(owner, opIdx);
10243    let domMatrix = new DOMMatrix(matrix);
10244    domMatrix = domMatrix.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
10245    domMatrix = domMatrix.scale(1 / temporaryPatternCanvas.scaleX, 1 / temporaryPatternCanvas.scaleY);
10246    const pattern = ctx.createPattern(temporaryPatternCanvas.canvas, "repeat");
10247    pattern.setTransform(domMatrix);
10248    return pattern;
10249  }
10250}
10251
10252;// ./src/shared/image_utils.js
10253
10254function convertToRGBA(params) {
10255  switch (params.kind) {
10256    case ImageKind.GRAYSCALE_1BPP:
10257      return convertBlackAndWhiteToRGBA(params);
10258    case ImageKind.RGB_24BPP:
10259      return convertRGBToRGBA(params);
10260  }
10261  return null;
10262}
10263function convertBlackAndWhiteToRGBA({
10264  src,
10265  srcPos = 0,
10266  dest,
10267  width,
10268  height,
10269  nonBlackColor = 0xffffffff,
10270  inverseDecode = false
10271}) {
10272  const black = util_FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff;
10273  const [zeroMapping, oneMapping] = inverseDecode ? [nonBlackColor, black] : [black, nonBlackColor];
10274  const widthInSource = width >> 3;
10275  const widthRemainder = width & 7;
10276  const srcLength = src.length;
10277  dest = new Uint32Array(dest.buffer);
10278  let destPos = 0;
10279  for (let i = 0; i < height; i++) {
10280    for (const max = srcPos + widthInSource; srcPos < max; srcPos++) {
10281      const elem = srcPos < srcLength ? src[srcPos] : 255;
10282      dest[destPos++] = elem & 0b10000000 ? oneMapping : zeroMapping;
10283      dest[destPos++] = elem & 0b1000000 ? oneMapping : zeroMapping;
10284      dest[destPos++] = elem & 0b100000 ? oneMapping : zeroMapping;
10285      dest[destPos++] = elem & 0b10000 ? oneMapping : zeroMapping;
10286      dest[destPos++] = elem & 0b1000 ? oneMapping : zeroMapping;
10287      dest[destPos++] = elem & 0b100 ? oneMapping : zeroMapping;
10288      dest[destPos++] = elem & 0b10 ? oneMapping : zeroMapping;
10289      dest[destPos++] = elem & 0b1 ? oneMapping : zeroMapping;
10290    }
10291    if (widthRemainder === 0) {
10292      continue;
10293    }
10294    const elem = srcPos < srcLength ? src[srcPos++] : 255;
10295    for (let j = 0; j < widthRemainder; j++) {
10296      dest[destPos++] = elem & 1 << 7 - j ? oneMapping : zeroMapping;
10297    }
10298  }
10299  return {
10300    srcPos,
10301    destPos
10302  };
10303}
10304function convertRGBToRGBA({
10305  src,
10306  srcPos = 0,
10307  dest,
10308  destPos = 0,
10309  width,
10310  height
10311}) {
10312  let i = 0;
10313  const len = width * height * 3;
10314  const len32 = len >> 2;
10315  const src32 = new Uint32Array(src.buffer, srcPos, len32);
10316  if (FeatureTest.isLittleEndian) {
10317    for (; i < len32 - 2; i += 3, destPos += 4) {
10318      const s1 = src32[i];
10319      const s2 = src32[i + 1];
10320      const s3 = src32[i + 2];
10321      dest[destPos] = s1 | 0xff000000;
10322      dest[destPos + 1] = s1 >>> 24 | s2 << 8 | 0xff000000;
10323      dest[destPos + 2] = s2 >>> 16 | s3 << 16 | 0xff000000;
10324      dest[destPos + 3] = s3 >>> 8 | 0xff000000;
10325    }
10326    for (let j = i * 4, jj = srcPos + len; j < jj; j += 3) {
10327      dest[destPos++] = src[j] | src[j + 1] << 8 | src[j + 2] << 16 | 0xff000000;
10328    }
10329  } else {
10330    for (; i < len32 - 2; i += 3, destPos += 4) {
10331      const s1 = src32[i];
10332      const s2 = src32[i + 1];
10333      const s3 = src32[i + 2];
10334      dest[destPos] = s1 | 0xff;
10335      dest[destPos + 1] = s1 << 24 | s2 >>> 8 | 0xff;
10336      dest[destPos + 2] = s2 << 16 | s3 >>> 16 | 0xff;
10337      dest[destPos + 3] = s3 << 8 | 0xff;
10338    }
10339    for (let j = i * 4, jj = srcPos + len; j < jj; j += 3) {
10340      dest[destPos++] = src[j] << 24 | src[j + 1] << 16 | src[j + 2] << 8 | 0xff;
10341    }
10342  }
10343  return {
10344    srcPos: srcPos + len,
10345    destPos
10346  };
10347}
10348function grayToRGBA(src, dest) {
10349  if (FeatureTest.isLittleEndian) {
10350    for (let i = 0, ii = src.length; i < ii; i++) {
10351      dest[i] = src[i] * 0x10101 | 0xff000000;
10352    }
10353  } else {
10354    for (let i = 0, ii = src.length; i < ii; i++) {
10355      dest[i] = src[i] * 0x1010100 | 0x000000ff;
10356    }
10357  }
10358}
10359
10360;// ./src/display/canvas.js
10361
10362
10363
10364
10365
10366const MIN_FONT_SIZE = 16;
10367const MAX_FONT_SIZE = 100;
10368const EXECUTION_TIME = 15;
10369const EXECUTION_STEPS = 10;
10370const FULL_CHUNK_HEIGHT = 16;
10371const SCALE_MATRIX = new DOMMatrix();
10372const XY = new Float32Array(2);
10373const MIN_MAX_INIT = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]);
10374function mirrorContextOperations(ctx, destCtx) {
10375  if (ctx._removeMirroring) {
10376    throw new Error("Context is already forwarding operations.");
10377  }
10378  ctx.__originalSave = ctx.save;
10379  ctx.__originalRestore = ctx.restore;
10380  ctx.__originalRotate = ctx.rotate;
10381  ctx.__originalScale = ctx.scale;
10382  ctx.__originalTranslate = ctx.translate;
10383  ctx.__originalTransform = ctx.transform;
10384  ctx.__originalSetTransform = ctx.setTransform;
10385  ctx.__originalResetTransform = ctx.resetTransform;
10386  ctx.__originalClip = ctx.clip;
10387  ctx.__originalMoveTo = ctx.moveTo;
10388  ctx.__originalLineTo = ctx.lineTo;
10389  ctx.__originalBezierCurveTo = ctx.bezierCurveTo;
10390  ctx.__originalRect = ctx.rect;
10391  ctx.__originalClosePath = ctx.closePath;
10392  ctx.__originalBeginPath = ctx.beginPath;
10393  ctx._removeMirroring = () => {
10394    ctx.save = ctx.__originalSave;
10395    ctx.restore = ctx.__originalRestore;
10396    ctx.rotate = ctx.__originalRotate;
10397    ctx.scale = ctx.__originalScale;
10398    ctx.translate = ctx.__originalTranslate;
10399    ctx.transform = ctx.__originalTransform;
10400    ctx.setTransform = ctx.__originalSetTransform;
10401    ctx.resetTransform = ctx.__originalResetTransform;
10402    ctx.clip = ctx.__originalClip;
10403    ctx.moveTo = ctx.__originalMoveTo;
10404    ctx.lineTo = ctx.__originalLineTo;
10405    ctx.bezierCurveTo = ctx.__originalBezierCurveTo;
10406    ctx.rect = ctx.__originalRect;
10407    ctx.closePath = ctx.__originalClosePath;
10408    ctx.beginPath = ctx.__originalBeginPath;
10409    delete ctx._removeMirroring;
10410  };
10411  ctx.save = function () {
10412    destCtx.save();
10413    this.__originalSave();
10414  };
10415  ctx.restore = function () {
10416    destCtx.restore();
10417    this.__originalRestore();
10418  };
10419  ctx.translate = function (x, y) {
10420    destCtx.translate(x, y);
10421    this.__originalTranslate(x, y);
10422  };
10423  ctx.scale = function (x, y) {
10424    destCtx.scale(x, y);
10425    this.__originalScale(x, y);
10426  };
10427  ctx.transform = function (a, b, c, d, e, f) {
10428    destCtx.transform(a, b, c, d, e, f);
10429    this.__originalTransform(a, b, c, d, e, f);
10430  };
10431  ctx.setTransform = function (a, b, c, d, e, f) {
10432    destCtx.setTransform(a, b, c, d, e, f);
10433    this.__originalSetTransform(a, b, c, d, e, f);
10434  };
10435  ctx.resetTransform = function () {
10436    destCtx.resetTransform();
10437    this.__originalResetTransform();
10438  };
10439  ctx.rotate = function (angle) {
10440    destCtx.rotate(angle);
10441    this.__originalRotate(angle);
10442  };
10443  ctx.clip = function (rule) {
10444    destCtx.clip(rule);
10445    this.__originalClip(rule);
10446  };
10447  ctx.moveTo = function (x, y) {
10448    destCtx.moveTo(x, y);
10449    this.__originalMoveTo(x, y);
10450  };
10451  ctx.lineTo = function (x, y) {
10452    destCtx.lineTo(x, y);
10453    this.__originalLineTo(x, y);
10454  };
10455  ctx.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
10456    destCtx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
10457    this.__originalBezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
10458  };
10459  ctx.rect = function (x, y, width, height) {
10460    destCtx.rect(x, y, width, height);
10461    this.__originalRect(x, y, width, height);
10462  };
10463  ctx.closePath = function () {
10464    destCtx.closePath();
10465    this.__originalClosePath();
10466  };
10467  ctx.beginPath = function () {
10468    destCtx.beginPath();
10469    this.__originalBeginPath();
10470  };
10471}
10472class CachedCanvases {
10473  constructor(canvasFactory) {
10474    this.canvasFactory = canvasFactory;
10475    this.cache = Object.create(null);
10476  }
10477  getCanvas(id, width, height) {
vendor: 36,726 bytes, lines 10478-11508
10478    let canvasEntry;
10479    if (this.cache[id] !== undefined) {
10480      canvasEntry = this.cache[id];
10481      this.canvasFactory.reset(canvasEntry, width, height);
10482    } else {
10483      canvasEntry = this.canvasFactory.create(width, height);
10484      this.cache[id] = canvasEntry;
10485    }
10486    return canvasEntry;
10487  }
10488  delete(id) {
10489    delete this.cache[id];
10490  }
10491  clear() {
10492    for (const id in this.cache) {
10493      const canvasEntry = this.cache[id];
10494      this.canvasFactory.destroy(canvasEntry);
10495      delete this.cache[id];
10496    }
10497  }
10498}
10499function drawImageAtIntegerCoords(ctx, srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH) {
10500  const [a, b, c, d, tx, ty] = getCurrentTransform(ctx);
10501  if (b === 0 && c === 0) {
10502    const tlX = destX * a + tx;
10503    const rTlX = Math.round(tlX);
10504    const tlY = destY * d + ty;
10505    const rTlY = Math.round(tlY);
10506    const brX = (destX + destW) * a + tx;
10507    const rWidth = Math.abs(Math.round(brX) - rTlX) || 1;
10508    const brY = (destY + destH) * d + ty;
10509    const rHeight = Math.abs(Math.round(brY) - rTlY) || 1;
10510    ctx.setTransform(Math.sign(a), 0, 0, Math.sign(d), rTlX, rTlY);
10511    ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rWidth, rHeight);
10512    ctx.setTransform(a, b, c, d, tx, ty);
10513    return [rWidth, rHeight];
10514  }
10515  if (a === 0 && d === 0) {
10516    const tlX = destY * c + tx;
10517    const rTlX = Math.round(tlX);
10518    const tlY = destX * b + ty;
10519    const rTlY = Math.round(tlY);
10520    const brX = (destY + destH) * c + tx;
10521    const rWidth = Math.abs(Math.round(brX) - rTlX) || 1;
10522    const brY = (destX + destW) * b + ty;
10523    const rHeight = Math.abs(Math.round(brY) - rTlY) || 1;
10524    ctx.setTransform(0, Math.sign(b), Math.sign(c), 0, rTlX, rTlY);
10525    ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rHeight, rWidth);
10526    ctx.setTransform(a, b, c, d, tx, ty);
10527    return [rHeight, rWidth];
10528  }
10529  ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH);
10530  const scaleX = Math.hypot(a, b);
10531  const scaleY = Math.hypot(c, d);
10532  return [scaleX * destW, scaleY * destH];
10533}
10534class CanvasExtraState {
10535  alphaIsShape = false;
10536  fontSize = 0;
10537  fontSizeScale = 1;
10538  textMatrix = null;
10539  textMatrixScale = 1;
10540  fontMatrix = FONT_IDENTITY_MATRIX;
10541  leading = 0;
10542  x = 0;
10543  y = 0;
10544  lineX = 0;
10545  lineY = 0;
10546  charSpacing = 0;
10547  wordSpacing = 0;
10548  textHScale = 1;
10549  textRenderingMode = TextRenderingMode.FILL;
10550  textRise = 0;
10551  fillColor = "#000000";
10552  strokeColor = "#000000";
10553  patternFill = false;
10554  patternStroke = false;
10555  fillAlpha = 1;
10556  strokeAlpha = 1;
10557  lineWidth = 1;
10558  activeSMask = null;
10559  transferMaps = "none";
10560  constructor(width, height, preInit) {
10561    preInit?.(this);
10562    this.clipBox = new Float32Array([0, 0, width, height]);
10563    this.minMax = MIN_MAX_INIT.slice();
10564  }
10565  clone() {
10566    const clone = Object.create(this);
10567    clone.clipBox = this.clipBox.slice();
10568    clone.minMax = this.minMax.slice();
10569    return clone;
10570  }
10571  getPathBoundingBox(pathType = PathType.FILL, transform = null) {
10572    const box = this.minMax.slice();
10573    if (pathType === PathType.STROKE) {
10574      if (!transform) {
10575        unreachable("Stroke bounding box must include transform.");
10576      }
10577      Util.singularValueDecompose2dScale(transform, XY);
10578      const xStrokePad = XY[0] * this.lineWidth / 2;
10579      const yStrokePad = XY[1] * this.lineWidth / 2;
10580      box[0] -= xStrokePad;
10581      box[1] -= yStrokePad;
10582      box[2] += xStrokePad;
10583      box[3] += yStrokePad;
10584    }
10585    return box;
10586  }
10587  updateClipFromPath() {
10588    const intersect = Util.intersect(this.clipBox, this.getPathBoundingBox());
10589    this.startNewPathAndClipBox(intersect || [0, 0, 0, 0]);
10590  }
10591  isEmptyClip() {
10592    return this.minMax[0] === Infinity;
10593  }
10594  startNewPathAndClipBox(box) {
10595    this.clipBox.set(box, 0);
10596    this.minMax.set(MIN_MAX_INIT, 0);
10597  }
10598  getClippedPathBoundingBox(pathType = PathType.FILL, transform = null) {
10599    return Util.intersect(this.clipBox, this.getPathBoundingBox(pathType, transform));
10600  }
10601}
10602function putBinaryImageData(ctx, imgData) {
10603  if (imgData instanceof ImageData) {
10604    ctx.putImageData(imgData, 0, 0);
10605    return;
10606  }
10607  const height = imgData.height,
10608    width = imgData.width;
10609  const partialChunkHeight = height % FULL_CHUNK_HEIGHT;
10610  const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
10611  const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
10612  const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
10613  let srcPos = 0,
10614    destPos;
10615  const src = imgData.data;
10616  const dest = chunkImgData.data;
10617  let i, j, thisChunkHeight, elemsInThisChunk;
10618  if (imgData.kind === util_ImageKind.GRAYSCALE_1BPP) {
10619    const srcLength = src.byteLength;
10620    const dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2);
10621    const dest32DataLength = dest32.length;
10622    const fullSrcDiff = width + 7 >> 3;
10623    const white = 0xffffffff;
10624    const black = util_FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff;
10625    for (i = 0; i < totalChunks; i++) {
10626      thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
10627      destPos = 0;
10628      for (j = 0; j < thisChunkHeight; j++) {
10629        const srcDiff = srcLength - srcPos;
10630        let k = 0;
10631        const kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7;
10632        const kEndUnrolled = kEnd & ~7;
10633        let mask = 0;
10634        let srcByte = 0;
10635        for (; k < kEndUnrolled; k += 8) {
10636          srcByte = src[srcPos++];
10637          dest32[destPos++] = srcByte & 128 ? white : black;
10638          dest32[destPos++] = srcByte & 64 ? white : black;
10639          dest32[destPos++] = srcByte & 32 ? white : black;
10640          dest32[destPos++] = srcByte & 16 ? white : black;
10641          dest32[destPos++] = srcByte & 8 ? white : black;
10642          dest32[destPos++] = srcByte & 4 ? white : black;
10643          dest32[destPos++] = srcByte & 2 ? white : black;
10644          dest32[destPos++] = srcByte & 1 ? white : black;
10645        }
10646        for (; k < kEnd; k++) {
10647          if (mask === 0) {
10648            srcByte = src[srcPos++];
10649            mask = 128;
10650          }
10651          dest32[destPos++] = srcByte & mask ? white : black;
10652          mask >>= 1;
10653        }
10654      }
10655      while (destPos < dest32DataLength) {
10656        dest32[destPos++] = 0;
10657      }
10658      ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
10659    }
10660  } else if (imgData.kind === util_ImageKind.RGBA_32BPP) {
10661    j = 0;
10662    elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4;
10663    for (i = 0; i < fullChunks; i++) {
10664      dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
10665      srcPos += elemsInThisChunk;
10666      ctx.putImageData(chunkImgData, 0, j);
10667      j += FULL_CHUNK_HEIGHT;
10668    }
10669    if (i < totalChunks) {
10670      elemsInThisChunk = width * partialChunkHeight * 4;
10671      dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
10672      ctx.putImageData(chunkImgData, 0, j);
10673    }
10674  } else if (imgData.kind === util_ImageKind.RGB_24BPP) {
10675    thisChunkHeight = FULL_CHUNK_HEIGHT;
10676    elemsInThisChunk = width * thisChunkHeight;
10677    for (i = 0; i < totalChunks; i++) {
10678      if (i >= fullChunks) {
10679        thisChunkHeight = partialChunkHeight;
10680        elemsInThisChunk = width * thisChunkHeight;
10681      }
10682      destPos = 0;
10683      for (j = elemsInThisChunk; j--;) {
10684        dest[destPos++] = src[srcPos++];
10685        dest[destPos++] = src[srcPos++];
10686        dest[destPos++] = src[srcPos++];
10687        dest[destPos++] = 255;
10688      }
10689      ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
10690    }
10691  } else {
10692    throw new Error(`bad image kind: ${imgData.kind}`);
10693  }
10694}
10695function putBinaryImageMask(ctx, imgData) {
10696  if (imgData.bitmap) {
10697    ctx.drawImage(imgData.bitmap, 0, 0);
10698    return;
10699  }
10700  const height = imgData.height,
10701    width = imgData.width;
10702  const partialChunkHeight = height % FULL_CHUNK_HEIGHT;
10703  const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
10704  const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
10705  const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
10706  let srcPos = 0;
10707  const src = imgData.data;
10708  const dest = chunkImgData.data;
10709  for (let i = 0; i < totalChunks; i++) {
10710    const thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
10711    ({
10712      srcPos
10713    } = convertBlackAndWhiteToRGBA({
10714      src,
10715      srcPos,
10716      dest,
10717      width,
10718      height: thisChunkHeight,
10719      nonBlackColor: 0
10720    }));
10721    ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
10722  }
10723}
10724function copyCtxState(sourceCtx, destCtx) {
10725  const properties = ["strokeStyle", "fillStyle", "fillRule", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "globalCompositeOperation", "font", "filter"];
10726  for (const property of properties) {
10727    if (sourceCtx[property] !== undefined) {
10728      destCtx[property] = sourceCtx[property];
10729    }
10730  }
10731  if (sourceCtx.setLineDash !== undefined) {
10732    destCtx.setLineDash(sourceCtx.getLineDash());
10733    destCtx.lineDashOffset = sourceCtx.lineDashOffset;
10734  }
10735}
10736function resetCtxToDefault(ctx) {
10737  ctx.strokeStyle = ctx.fillStyle = "#000000";
10738  ctx.fillRule = "nonzero";
10739  ctx.globalAlpha = 1;
10740  ctx.lineWidth = 1;
10741  ctx.lineCap = "butt";
10742  ctx.lineJoin = "miter";
10743  ctx.miterLimit = 10;
10744  ctx.globalCompositeOperation = "source-over";
10745  ctx.font = "10px sans-serif";
10746  if (ctx.setLineDash !== undefined) {
10747    ctx.setLineDash([]);
10748    ctx.lineDashOffset = 0;
10749  }
10750  const {
10751    filter
10752  } = ctx;
10753  if (filter !== "none" && filter !== "") {
10754    ctx.filter = "none";
10755  }
10756}
10757function getImageSmoothingEnabled(transform, interpolate) {
10758  if (interpolate) {
10759    return true;
10760  }
10761  Util.singularValueDecompose2dScale(transform, XY);
10762  const actualScale = Math.fround(OutputScale.pixelRatio * PixelsPerInch.PDF_TO_CSS_UNITS);
10763  return XY[0] <= actualScale && XY[1] <= actualScale;
10764}
10765const LINE_CAP_STYLES = ["butt", "round", "square"];
10766const LINE_JOIN_STYLES = ["miter", "round", "bevel"];
10767const NORMAL_CLIP = {};
10768const EO_CLIP = {};
10769class CanvasGraphics {
10770  constructor(canvasCtx, commonObjs, objs, canvasFactory, filterFactory, {
10771    optionalContentConfig,
10772    markedContentStack = null
10773  }, annotationCanvasMap, pageColors, dependencyTracker) {
10774    this.ctx = canvasCtx;
10775    this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height);
10776    this.stateStack = [];
10777    this.pendingClip = null;
10778    this.pendingEOFill = false;
10779    this.res = null;
10780    this.xobjs = null;
10781    this.commonObjs = commonObjs;
10782    this.objs = objs;
10783    this.canvasFactory = canvasFactory;
10784    this.filterFactory = filterFactory;
10785    this.groupStack = [];
10786    this.baseTransform = null;
10787    this.baseTransformStack = [];
10788    this.groupLevel = 0;
10789    this.smaskStack = [];
10790    this.smaskCounter = 0;
10791    this.tempSMask = null;
10792    this.suspendedCtx = null;
10793    this.contentVisible = true;
10794    this.markedContentStack = markedContentStack || [];
10795    this.optionalContentConfig = optionalContentConfig;
10796    this.cachedCanvases = new CachedCanvases(this.canvasFactory);
10797    this.cachedPatterns = new Map();
10798    this.annotationCanvasMap = annotationCanvasMap;
10799    this.viewportScale = 1;
10800    this.outputScaleX = 1;
10801    this.outputScaleY = 1;
10802    this.pageColors = pageColors;
10803    this._cachedScaleForStroking = [-1, 0];
10804    this._cachedGetSinglePixelWidth = null;
10805    this._cachedBitmapsMap = new Map();
10806    this.dependencyTracker = dependencyTracker ?? null;
10807  }
10808  getObject(opIdx, data, fallback = null) {
10809    if (typeof data === "string") {
10810      this.dependencyTracker?.recordNamedDependency(opIdx, data);
10811      return data.startsWith("g_") ? this.commonObjs.get(data) : this.objs.get(data);
10812    }
10813    return fallback;
10814  }
10815  beginDrawing({
10816    transform,
10817    viewport,
10818    transparency = false,
10819    background = null
10820  }) {
10821    const width = this.ctx.canvas.width;
10822    const height = this.ctx.canvas.height;
10823    const savedFillStyle = this.ctx.fillStyle;
10824    this.ctx.fillStyle = background || "#ffffff";
10825    this.ctx.fillRect(0, 0, width, height);
10826    this.ctx.fillStyle = savedFillStyle;
10827    if (transparency) {
10828      const transparentCanvas = this.cachedCanvases.getCanvas("transparent", width, height);
10829      this.compositeCtx = this.ctx;
10830      this.transparentCanvas = transparentCanvas.canvas;
10831      this.ctx = transparentCanvas.context;
10832      this.ctx.save();
10833      this.ctx.transform(...getCurrentTransform(this.compositeCtx));
10834    }
10835    this.ctx.save();
10836    resetCtxToDefault(this.ctx);
10837    if (transform) {
10838      this.ctx.transform(...transform);
10839      this.outputScaleX = transform[0];
10840      this.outputScaleY = transform[0];
10841    }
10842    this.ctx.transform(...viewport.transform);
10843    this.viewportScale = viewport.scale;
10844    this.baseTransform = getCurrentTransform(this.ctx);
10845  }
10846  executeOperatorList(operatorList, executionStartIdx, continueCallback, stepper, operationsFilter) {
10847    const argsArray = operatorList.argsArray;
10848    const fnArray = operatorList.fnArray;
10849    let i = executionStartIdx || 0;
10850    const argsArrayLen = argsArray.length;
10851    if (argsArrayLen === i) {
10852      return i;
10853    }
10854    const chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === "function";
10855    const endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0;
10856    let steps = 0;
10857    const commonObjs = this.commonObjs;
10858    const objs = this.objs;
10859    let fnId, fnArgs;
10860    while (true) {
10861      if (stepper !== undefined && i === stepper.nextBreakPoint) {
10862        stepper.breakIt(i, continueCallback);
10863        return i;
10864      }
10865      if (!operationsFilter || operationsFilter(i)) {
10866        fnId = fnArray[i];
10867        fnArgs = argsArray[i] ?? null;
10868        if (fnId !== OPS.dependency) {
10869          if (fnArgs === null) {
10870            this[fnId](i);
10871          } else {
10872            this[fnId](i, ...fnArgs);
10873          }
10874        } else {
10875          for (const depObjId of fnArgs) {
10876            this.dependencyTracker?.recordNamedData(depObjId, i);
10877            const objsPool = depObjId.startsWith("g_") ? commonObjs : objs;
10878            if (!objsPool.has(depObjId)) {
10879              objsPool.get(depObjId, continueCallback);
10880              return i;
10881            }
10882          }
10883        }
10884      }
10885      i++;
10886      if (i === argsArrayLen) {
10887        return i;
10888      }
10889      if (chunkOperations && ++steps > EXECUTION_STEPS) {
10890        if (Date.now() > endTime) {
10891          continueCallback();
10892          return i;
10893        }
10894        steps = 0;
10895      }
10896    }
10897  }
10898  #restoreInitialState() {
10899    while (this.stateStack.length || this.inSMaskMode) {
10900      this.restore();
10901    }
10902    this.current.activeSMask = null;
10903    this.ctx.restore();
10904    if (this.transparentCanvas) {
10905      this.ctx = this.compositeCtx;
10906      this.ctx.save();
10907      this.ctx.setTransform(1, 0, 0, 1, 0, 0);
10908      this.ctx.drawImage(this.transparentCanvas, 0, 0);
10909      this.ctx.restore();
10910      this.transparentCanvas = null;
10911    }
10912  }
10913  endDrawing() {
10914    this.#restoreInitialState();
10915    this.cachedCanvases.clear();
10916    this.cachedPatterns.clear();
10917    for (const cache of this._cachedBitmapsMap.values()) {
10918      for (const canvas of cache.values()) {
10919        if (typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement) {
10920          canvas.width = canvas.height = 0;
10921        }
10922      }
10923      cache.clear();
10924    }
10925    this._cachedBitmapsMap.clear();
10926    this.#drawFilter();
10927  }
10928  #drawFilter() {
10929    if (this.pageColors) {
10930      const hcmFilterId = this.filterFactory.addHCMFilter(this.pageColors.foreground, this.pageColors.background);
10931      if (hcmFilterId !== "none") {
10932        const savedFilter = this.ctx.filter;
10933        this.ctx.filter = hcmFilterId;
10934        this.ctx.drawImage(this.ctx.canvas, 0, 0);
10935        this.ctx.filter = savedFilter;
10936      }
10937    }
10938  }
10939  _scaleImage(img, inverseTransform) {
10940    const width = img.width ?? img.displayWidth;
10941    const height = img.height ?? img.displayHeight;
10942    let widthScale = Math.max(Math.hypot(inverseTransform[0], inverseTransform[1]), 1);
10943    let heightScale = Math.max(Math.hypot(inverseTransform[2], inverseTransform[3]), 1);
10944    let paintWidth = width,
10945      paintHeight = height;
10946    let tmpCanvasId = "prescale1";
10947    let tmpCanvas, tmpCtx;
10948    while (widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1) {
10949      let newWidth = paintWidth,
10950        newHeight = paintHeight;
10951      if (widthScale > 2 && paintWidth > 1) {
10952        newWidth = paintWidth >= 16384 ? Math.floor(paintWidth / 2) - 1 || 1 : Math.ceil(paintWidth / 2);
10953        widthScale /= paintWidth / newWidth;
10954      }
10955      if (heightScale > 2 && paintHeight > 1) {
10956        newHeight = paintHeight >= 16384 ? Math.floor(paintHeight / 2) - 1 || 1 : Math.ceil(paintHeight) / 2;
10957        heightScale /= paintHeight / newHeight;
10958      }
10959      tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight);
10960      tmpCtx = tmpCanvas.context;
10961      tmpCtx.clearRect(0, 0, newWidth, newHeight);
10962      tmpCtx.drawImage(img, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight);
10963      img = tmpCanvas.canvas;
10964      paintWidth = newWidth;
10965      paintHeight = newHeight;
10966      tmpCanvasId = tmpCanvasId === "prescale1" ? "prescale2" : "prescale1";
10967    }
10968    return {
10969      img,
10970      paintWidth,
10971      paintHeight
10972    };
10973  }
10974  _createMaskCanvas(opIdx, img) {
10975    const ctx = this.ctx;
10976    const {
10977      width,
10978      height
10979    } = img;
10980    const fillColor = this.current.fillColor;
10981    const isPatternFill = this.current.patternFill;
10982    const currentTransform = getCurrentTransform(ctx);
10983    let cache, cacheKey, scaled, maskCanvas;
10984    if ((img.bitmap || img.data) && img.count > 1) {
10985      const mainKey = img.bitmap || img.data.buffer;
10986      cacheKey = JSON.stringify(isPatternFill ? currentTransform : [currentTransform.slice(0, 4), fillColor]);
10987      cache = this._cachedBitmapsMap.get(mainKey);
10988      if (!cache) {
10989        cache = new Map();
10990        this._cachedBitmapsMap.set(mainKey, cache);
10991      }
10992      const cachedImage = cache.get(cacheKey);
10993      if (cachedImage && !isPatternFill) {
10994        const offsetX = Math.round(Math.min(currentTransform[0], currentTransform[2]) + currentTransform[4]);
10995        const offsetY = Math.round(Math.min(currentTransform[1], currentTransform[3]) + currentTransform[5]);
10996        this.dependencyTracker?.recordDependencies(opIdx, Dependencies.transformAndFill);
10997        return {
10998          canvas: cachedImage,
10999          offsetX,
11000          offsetY
11001        };
11002      }
11003      scaled = cachedImage;
11004    }
11005    if (!scaled) {
11006      maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height);
11007      putBinaryImageMask(maskCanvas.context, img);
11008    }
11009    let maskToCanvas = Util.transform(currentTransform, [1 / width, 0, 0, -1 / height, 0, 0]);
11010    maskToCanvas = Util.transform(maskToCanvas, [1, 0, 0, 1, 0, -height]);
11011    const minMax = MIN_MAX_INIT.slice();
11012    Util.axialAlignedBoundingBox([0, 0, width, height], maskToCanvas, minMax);
11013    const [minX, minY, maxX, maxY] = minMax;
11014    const drawnWidth = Math.round(maxX - minX) || 1;
11015    const drawnHeight = Math.round(maxY - minY) || 1;
11016    const fillCanvas = this.cachedCanvases.getCanvas("fillCanvas", drawnWidth, drawnHeight);
11017    const fillCtx = fillCanvas.context;
11018    const offsetX = minX;
11019    const offsetY = minY;
11020    fillCtx.translate(-offsetX, -offsetY);
11021    fillCtx.transform(...maskToCanvas);
11022    if (!scaled) {
11023      scaled = this._scaleImage(maskCanvas.canvas, getCurrentTransformInverse(fillCtx));
11024      scaled = scaled.img;
11025      if (cache && isPatternFill) {
11026        cache.set(cacheKey, scaled);
11027      }
11028    }
11029    fillCtx.imageSmoothingEnabled = getImageSmoothingEnabled(getCurrentTransform(fillCtx), img.interpolate);
11030    drawImageAtIntegerCoords(fillCtx, scaled, 0, 0, scaled.width, scaled.height, 0, 0, width, height);
11031    fillCtx.globalCompositeOperation = "source-in";
11032    const inverse = Util.transform(getCurrentTransformInverse(fillCtx), [1, 0, 0, 1, -offsetX, -offsetY]);
11033    fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(ctx, this, inverse, PathType.FILL, opIdx) : fillColor;
11034    fillCtx.fillRect(0, 0, width, height);
11035    if (cache && !isPatternFill) {
11036      this.cachedCanvases.delete("fillCanvas");
11037      cache.set(cacheKey, fillCanvas.canvas);
11038    }
11039    this.dependencyTracker?.recordDependencies(opIdx, Dependencies.transformAndFill);
11040    return {
11041      canvas: fillCanvas.canvas,
11042      offsetX: Math.round(offsetX),
11043      offsetY: Math.round(offsetY)
11044    };
11045  }
11046  setLineWidth(opIdx, width) {
11047    this.dependencyTracker?.recordSimpleData("lineWidth", opIdx);
11048    if (width !== this.current.lineWidth) {
11049      this._cachedScaleForStroking[0] = -1;
11050    }
11051    this.current.lineWidth = width;
11052    this.ctx.lineWidth = width;
11053  }
11054  setLineCap(opIdx, style) {
11055    this.dependencyTracker?.recordSimpleData("lineCap", opIdx);
11056    this.ctx.lineCap = LINE_CAP_STYLES[style];
11057  }
11058  setLineJoin(opIdx, style) {
11059    this.dependencyTracker?.recordSimpleData("lineJoin", opIdx);
11060    this.ctx.lineJoin = LINE_JOIN_STYLES[style];
11061  }
11062  setMiterLimit(opIdx, limit) {
11063    this.dependencyTracker?.recordSimpleData("miterLimit", opIdx);
11064    this.ctx.miterLimit = limit;
11065  }
11066  setDash(opIdx, dashArray, dashPhase) {
11067    this.dependencyTracker?.recordSimpleData("dash", opIdx);
11068    const ctx = this.ctx;
11069    if (ctx.setLineDash !== undefined) {
11070      ctx.setLineDash(dashArray);
11071      ctx.lineDashOffset = dashPhase;
11072    }
11073  }
11074  setRenderingIntent(opIdx, intent) {}
11075  setFlatness(opIdx, flatness) {}
11076  setGState(opIdx, states) {
11077    for (const [key, value] of states) {
11078      switch (key) {
11079        case "LW":
11080          this.setLineWidth(opIdx, value);
11081          break;
11082        case "LC":
11083          this.setLineCap(opIdx, value);
11084          break;
11085        case "LJ":
11086          this.setLineJoin(opIdx, value);
11087          break;
11088        case "ML":
11089          this.setMiterLimit(opIdx, value);
11090          break;
11091        case "D":
11092          this.setDash(opIdx, value[0], value[1]);
11093          break;
11094        case "RI":
11095          this.setRenderingIntent(opIdx, value);
11096          break;
11097        case "FL":
11098          this.setFlatness(opIdx, value);
11099          break;
11100        case "Font":
11101          this.setFont(opIdx, value[0], value[1]);
11102          break;
11103        case "CA":
11104          this.dependencyTracker?.recordSimpleData("strokeAlpha", opIdx);
11105          this.current.strokeAlpha = value;
11106          break;
11107        case "ca":
11108          this.dependencyTracker?.recordSimpleData("fillAlpha", opIdx);
11109          this.ctx.globalAlpha = this.current.fillAlpha = value;
11110          break;
11111        case "BM":
11112          this.dependencyTracker?.recordSimpleData("globalCompositeOperation", opIdx);
11113          this.ctx.globalCompositeOperation = value;
11114          break;
11115        case "SMask":
11116          this.dependencyTracker?.recordSimpleData("SMask", opIdx);
11117          this.current.activeSMask = value ? this.tempSMask : null;
11118          this.tempSMask = null;
11119          this.checkSMaskState();
11120          break;
11121        case "TR":
11122          this.dependencyTracker?.recordSimpleData("filter", opIdx);
11123          this.ctx.filter = this.current.transferMaps = this.filterFactory.addFilter(value);
11124          break;
11125      }
11126    }
11127  }
11128  get inSMaskMode() {
11129    return !!this.suspendedCtx;
11130  }
11131  checkSMaskState() {
11132    const inSMaskMode = this.inSMaskMode;
11133    if (this.current.activeSMask && !inSMaskMode) {
11134      this.beginSMaskMode();
11135    } else if (!this.current.activeSMask && inSMaskMode) {
11136      this.endSMaskMode();
11137    }
11138  }
11139  beginSMaskMode(opIdx) {
11140    if (this.inSMaskMode) {
11141      throw new Error("beginSMaskMode called while already in smask mode");
11142    }
11143    const drawnWidth = this.ctx.canvas.width;
11144    const drawnHeight = this.ctx.canvas.height;
11145    const cacheId = "smaskGroupAt" + this.groupLevel;
11146    const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight);
11147    this.suspendedCtx = this.ctx;
11148    const ctx = this.ctx = scratchCanvas.context;
11149    ctx.setTransform(this.suspendedCtx.getTransform());
11150    copyCtxState(this.suspendedCtx, ctx);
11151    mirrorContextOperations(ctx, this.suspendedCtx);
11152    this.setGState(opIdx, [["BM", "source-over"]]);
11153  }
11154  endSMaskMode() {
11155    if (!this.inSMaskMode) {
11156      throw new Error("endSMaskMode called while not in smask mode");
11157    }
11158    this.ctx._removeMirroring();
11159    copyCtxState(this.ctx, this.suspendedCtx);
11160    this.ctx = this.suspendedCtx;
11161    this.suspendedCtx = null;
11162  }
11163  compose(dirtyBox) {
11164    if (!this.current.activeSMask) {
11165      return;
11166    }
11167    if (!dirtyBox) {
11168      dirtyBox = [0, 0, this.ctx.canvas.width, this.ctx.canvas.height];
11169    } else {
11170      dirtyBox[0] = Math.floor(dirtyBox[0]);
11171      dirtyBox[1] = Math.floor(dirtyBox[1]);
11172      dirtyBox[2] = Math.ceil(dirtyBox[2]);
11173      dirtyBox[3] = Math.ceil(dirtyBox[3]);
11174    }
11175    const smask = this.current.activeSMask;
11176    const suspendedCtx = this.suspendedCtx;
11177    this.composeSMask(suspendedCtx, smask, this.ctx, dirtyBox);
11178    this.ctx.save();
11179    this.ctx.setTransform(1, 0, 0, 1, 0, 0);
11180    this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
11181    this.ctx.restore();
11182  }
11183  composeSMask(ctx, smask, layerCtx, layerBox) {
11184    const layerOffsetX = layerBox[0];
11185    const layerOffsetY = layerBox[1];
11186    const layerWidth = layerBox[2] - layerOffsetX;
11187    const layerHeight = layerBox[3] - layerOffsetY;
11188    if (layerWidth === 0 || layerHeight === 0) {
11189      return;
11190    }
11191    this.genericComposeSMask(smask.context, layerCtx, layerWidth, layerHeight, smask.subtype, smask.backdrop, smask.transferMap, layerOffsetX, layerOffsetY, smask.offsetX, smask.offsetY);
11192    ctx.save();
11193    ctx.globalAlpha = 1;
11194    ctx.globalCompositeOperation = "source-over";
11195    ctx.setTransform(1, 0, 0, 1, 0, 0);
11196    ctx.drawImage(layerCtx.canvas, 0, 0);
11197    ctx.restore();
11198  }
11199  genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap, layerOffsetX, layerOffsetY, maskOffsetX, maskOffsetY) {
11200    let maskCanvas = maskCtx.canvas;
11201    let maskX = layerOffsetX - maskOffsetX;
11202    let maskY = layerOffsetY - maskOffsetY;
11203    if (backdrop) {
11204      if (maskX < 0 || maskY < 0 || maskX + width > maskCanvas.width || maskY + height > maskCanvas.height) {
11205        const canvas = this.cachedCanvases.getCanvas("maskExtension", width, height);
11206        const ctx = canvas.context;
11207        ctx.drawImage(maskCanvas, -maskX, -maskY);
11208        ctx.globalCompositeOperation = "destination-atop";
11209        ctx.fillStyle = backdrop;
11210        ctx.fillRect(0, 0, width, height);
11211        ctx.globalCompositeOperation = "source-over";
11212        maskCanvas = canvas.canvas;
11213        maskX = maskY = 0;
11214      } else {
11215        maskCtx.save();
11216        maskCtx.globalAlpha = 1;
11217        maskCtx.setTransform(1, 0, 0, 1, 0, 0);
11218        const clip = new Path2D();
11219        clip.rect(maskX, maskY, width, height);
11220        maskCtx.clip(clip);
11221        maskCtx.globalCompositeOperation = "destination-atop";
11222        maskCtx.fillStyle = backdrop;
11223        maskCtx.fillRect(maskX, maskY, width, height);
11224        maskCtx.restore();
11225      }
11226    }
11227    layerCtx.save();
11228    layerCtx.globalAlpha = 1;
11229    layerCtx.setTransform(1, 0, 0, 1, 0, 0);
11230    if (subtype === "Alpha" && transferMap) {
11231      layerCtx.filter = this.filterFactory.addAlphaFilter(transferMap);
11232    } else if (subtype === "Luminosity") {
11233      layerCtx.filter = this.filterFactory.addLuminosityFilter(transferMap);
11234    }
11235    const clip = new Path2D();
11236    clip.rect(layerOffsetX, layerOffsetY, width, height);
11237    layerCtx.clip(clip);
11238    layerCtx.globalCompositeOperation = "destination-in";
11239    layerCtx.drawImage(maskCanvas, maskX, maskY, width, height, layerOffsetX, layerOffsetY, width, height);
11240    layerCtx.restore();
11241  }
11242  save(opIdx) {
11243    if (this.inSMaskMode) {
11244      copyCtxState(this.ctx, this.suspendedCtx);
11245    }
11246    this.ctx.save();
11247    const old = this.current;
11248    this.stateStack.push(old);
11249    this.current = old.clone();
11250    this.dependencyTracker?.save(opIdx);
11251  }
11252  restore(opIdx) {
11253    this.dependencyTracker?.restore(opIdx);
11254    if (this.stateStack.length === 0) {
11255      if (this.inSMaskMode) {
11256        this.endSMaskMode();
11257      }
11258      return;
11259    }
11260    this.current = this.stateStack.pop();
11261    this.ctx.restore();
11262    if (this.inSMaskMode) {
11263      copyCtxState(this.suspendedCtx, this.ctx);
11264    }
11265    this.checkSMaskState();
11266    this.pendingClip = null;
11267    this._cachedScaleForStroking[0] = -1;
11268    this._cachedGetSinglePixelWidth = null;
11269  }
11270  transform(opIdx, a, b, c, d, e, f) {
11271    this.dependencyTracker?.recordIncrementalData("transform", opIdx);
11272    this.ctx.transform(a, b, c, d, e, f);
11273    this._cachedScaleForStroking[0] = -1;
11274    this._cachedGetSinglePixelWidth = null;
11275  }
11276  constructPath(opIdx, op, data, minMax) {
11277    let [path] = data;
11278    if (!minMax) {
11279      path ||= data[0] = new Path2D();
11280      this[op](opIdx, path);
11281      return;
11282    }
11283    if (this.dependencyTracker !== null) {
11284      const outerExtraSize = op === OPS.stroke ? this.current.lineWidth / 2 : 0;
11285      this.dependencyTracker.resetBBox(opIdx).recordBBox(opIdx, this.ctx, minMax[0] - outerExtraSize, minMax[2] + outerExtraSize, minMax[1] - outerExtraSize, minMax[3] + outerExtraSize).recordDependencies(opIdx, ["transform"]);
11286    }
11287    if (!(path instanceof Path2D)) {
11288      path = data[0] = makePathFromDrawOPS(path);
11289    }
11290    Util.axialAlignedBoundingBox(minMax, getCurrentTransform(this.ctx), this.current.minMax);
11291    this[op](opIdx, path);
11292    this._pathStartIdx = opIdx;
11293  }
11294  closePath(opIdx) {
11295    this.ctx.closePath();
11296  }
11297  stroke(opIdx, path, consumePath = true) {
11298    const ctx = this.ctx;
11299    const strokeColor = this.current.strokeColor;
11300    ctx.globalAlpha = this.current.strokeAlpha;
11301    if (this.contentVisible) {
11302      if (typeof strokeColor === "object" && strokeColor?.getPattern) {
11303        const baseTransform = strokeColor.isModifyingCurrentTransform() ? ctx.getTransform() : null;
11304        ctx.save();
11305        ctx.strokeStyle = strokeColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.STROKE, opIdx);
11306        if (baseTransform) {
11307          const newPath = new Path2D();
11308          newPath.addPath(path, ctx.getTransform().invertSelf().multiplySelf(baseTransform));
11309          path = newPath;
11310        }
11311        this.rescaleAndStroke(path, false);
11312        ctx.restore();
11313      } else {
11314        this.rescaleAndStroke(path, true);
11315      }
11316    }
11317    this.dependencyTracker?.recordDependencies(opIdx, Dependencies.stroke);
11318    if (consumePath) {
11319      this.consumePath(opIdx, path, this.current.getClippedPathBoundingBox(PathType.STROKE, getCurrentTransform(this.ctx)));
11320    }
11321    ctx.globalAlpha = this.current.fillAlpha;
11322  }
11323  closeStroke(opIdx, path) {
11324    this.stroke(opIdx, path);
11325  }
11326  fill(opIdx, path, consumePath = true) {
11327    const ctx = this.ctx;
11328    const fillColor = this.current.fillColor;
11329    const isPatternFill = this.current.patternFill;
11330    let needRestore = false;
11331    if (isPatternFill) {
11332      const baseTransform = fillColor.isModifyingCurrentTransform() ? ctx.getTransform() : null;
11333      this.dependencyTracker?.save(opIdx);
11334      ctx.save();
11335      ctx.fillStyle = fillColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.FILL, opIdx);
11336      if (baseTransform) {
11337        const newPath = new Path2D();
11338        newPath.addPath(path, ctx.getTransform().invertSelf().multiplySelf(baseTransform));
11339        path = newPath;
11340      }
11341      needRestore = true;
11342    }
11343    const intersect = this.current.getClippedPathBoundingBox();
11344    if (this.contentVisible && intersect !== null) {
11345      if (this.pendingEOFill) {
11346        ctx.fill(path, "evenodd");
11347        this.pendingEOFill = false;
11348      } else {
11349        ctx.fill(path);
11350      }
11351    }
11352    this.dependencyTracker?.recordDependencies(opIdx, Dependencies.fill);
11353    if (needRestore) {
11354      ctx.restore();
11355      this.dependencyTracker?.restore(opIdx);
11356    }
11357    if (consumePath) {
11358      this.consumePath(opIdx, path, intersect);
11359    }
11360  }
11361  eoFill(opIdx, path) {
11362    this.pendingEOFill = true;
11363    this.fill(opIdx, path);
11364  }
11365  fillStroke(opIdx, path) {
11366    this.fill(opIdx, path, false);
11367    this.stroke(opIdx, path, false);
11368    this.consumePath(opIdx, path);
11369  }
11370  eoFillStroke(opIdx, path) {
11371    this.pendingEOFill = true;
11372    this.fillStroke(opIdx, path);
11373  }
11374  closeFillStroke(opIdx, path) {
11375    this.fillStroke(opIdx, path);
11376  }
11377  closeEOFillStroke(opIdx, path) {
11378    this.pendingEOFill = true;
11379    this.fillStroke(opIdx, path);
11380  }
11381  endPath(opIdx, path) {
11382    this.consumePath(opIdx, path);
11383  }
11384  rawFillPath(opIdx, path) {
11385    this.ctx.fill(path);
11386    this.dependencyTracker?.recordDependencies(opIdx, Dependencies.rawFillPath).recordOperation(opIdx);
11387  }
11388  clip(opIdx) {
11389    this.dependencyTracker?.recordFutureForcedDependency("clipMode", opIdx);
11390    this.pendingClip = NORMAL_CLIP;
11391  }
11392  eoClip(opIdx) {
11393    this.dependencyTracker?.recordFutureForcedDependency("clipMode", opIdx);
11394    this.pendingClip = EO_CLIP;
11395  }
11396  beginText(opIdx) {
11397    this.current.textMatrix = null;
11398    this.current.textMatrixScale = 1;
11399    this.current.x = this.current.lineX = 0;
11400    this.current.y = this.current.lineY = 0;
11401    this.dependencyTracker?.recordOpenMarker(opIdx).resetIncrementalData("sameLineText").resetIncrementalData("moveText", opIdx);
11402  }
11403  endText(opIdx) {
11404    const paths = this.pendingTextPaths;
11405    const ctx = this.ctx;
11406    if (this.dependencyTracker) {
11407      const {
11408        dependencyTracker
11409      } = this;
11410      if (paths !== undefined) {
11411        dependencyTracker.recordFutureForcedDependency("textClip", dependencyTracker.getOpenMarker()).recordFutureForcedDependency("textClip", opIdx);
11412      }
11413      dependencyTracker.recordCloseMarker(opIdx);
11414    }
11415    if (paths !== undefined) {
11416      const newPath = new Path2D();
11417      const invTransf = ctx.getTransform().invertSelf();
11418      for (const {
11419        transform,
11420        x,
11421        y,
11422        fontSize,
11423        path
11424      } of paths) {
11425        if (!path) {
11426          continue;
11427        }
11428        newPath.addPath(path, new DOMMatrix(transform).preMultiplySelf(invTransf).translate(x, y).scale(fontSize, -fontSize));
11429      }
11430      ctx.clip(newPath);
11431    }
11432    delete this.pendingTextPaths;
11433  }
11434  setCharSpacing(opIdx, spacing) {
11435    this.dependencyTracker?.recordSimpleData("charSpacing", opIdx);
11436    this.current.charSpacing = spacing;
11437  }
11438  setWordSpacing(opIdx, spacing) {
11439    this.dependencyTracker?.recordSimpleData("wordSpacing", opIdx);
11440    this.current.wordSpacing = spacing;
11441  }
11442  setHScale(opIdx, scale) {
11443    this.dependencyTracker?.recordSimpleData("hScale", opIdx);
11444    this.current.textHScale = scale / 100;
11445  }
11446  setLeading(opIdx, leading) {
11447    this.dependencyTracker?.recordSimpleData("leading", opIdx);
11448    this.current.leading = -leading;
11449  }
11450  setFont(opIdx, fontRefName, size) {
11451    this.dependencyTracker?.recordSimpleData("font", opIdx).recordSimpleDataFromNamed("fontObj", fontRefName, opIdx);
11452    const fontObj = this.commonObjs.get(fontRefName);
11453    const current = this.current;
11454    if (!fontObj) {
11455      throw new Error(`Can't find font for ${fontRefName}`);
11456    }
11457    current.fontMatrix = fontObj.fontMatrix || FONT_IDENTITY_MATRIX;
11458    if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) {
11459      warn("Invalid font matrix for font " + fontRefName);
11460    }
11461    if (size < 0) {
11462      size = -size;
11463      current.fontDirection = -1;
11464    } else {
11465      current.fontDirection = 1;
11466    }
11467    this.current.font = fontObj;
11468    this.current.fontSize = size;
11469    if (fontObj.isType3Font) {
11470      return;
11471    }
11472    const name = fontObj.loadedName || "sans-serif";
11473    const typeface = fontObj.systemFontInfo?.css || `"${name}", ${fontObj.fallbackName}`;
11474    let bold = "normal";
11475    if (fontObj.black) {
11476      bold = "900";
11477    } else if (fontObj.bold) {
11478      bold = "bold";
11479    }
11480    const italic = fontObj.italic ? "italic" : "normal";
11481    let browserFontSize = size;
11482    if (size < MIN_FONT_SIZE) {
11483      browserFontSize = MIN_FONT_SIZE;
11484    } else if (size > MAX_FONT_SIZE) {
11485      browserFontSize = MAX_FONT_SIZE;
11486    }
11487    this.current.fontSizeScale = size / browserFontSize;
11488    this.ctx.font = `${italic} ${bold} ${browserFontSize}px ${typeface}`;
11489  }
11490  setTextRenderingMode(opIdx, mode) {
11491    this.dependencyTracker?.recordSimpleData("textRenderingMode", opIdx);
11492    this.current.textRenderingMode = mode;
11493  }
11494  setTextRise(opIdx, rise) {
11495    this.dependencyTracker?.recordSimpleData("textRise", opIdx);
11496    this.current.textRise = rise;
11497  }
11498  moveText(opIdx, x, y) {
11499    this.dependencyTracker?.resetIncrementalData("sameLineText").recordIncrementalData("moveText", opIdx);
11500    this.current.x = this.current.lineX += x;
11501    this.current.y = this.current.lineY += y;
11502  }
11503  setLeadingMoveText(opIdx, x, y) {
11504    this.setLeading(opIdx, -y);
11505    this.moveText(opIdx, x, y);
11506  }
11507  setTextMatrix(opIdx, matrix) {
11508    this.dependencyTracker?.resetIncrementalData("sameLineText")
vendor: 5,039 bytes, lines 11508-11629
11508.recordSimpleData("textMatrix", opIdx);
11509    const {
11510      current
11511    } = this;
11512    current.textMatrix = matrix;
11513    current.textMatrixScale = Math.hypot(matrix[0], matrix[1]);
11514    current.x = current.lineX = 0;
11515    current.y = current.lineY = 0;
11516  }
11517  nextLine(opIdx) {
11518    this.moveText(opIdx, 0, this.current.leading);
11519    this.dependencyTracker?.recordIncrementalData("moveText", this.dependencyTracker.getSimpleIndex("leading") ?? opIdx);
11520  }
11521  #getScaledPath(path, currentTransform, transform) {
11522    const newPath = new Path2D();
11523    newPath.addPath(path, new DOMMatrix(transform).invertSelf().multiplySelf(currentTransform));
11524    return newPath;
11525  }
11526  paintChar(opIdx, character, x, y, patternFillTransform, patternStrokeTransform) {
11527    const ctx = this.ctx;
11528    const current = this.current;
11529    const font = current.font;
11530    const textRenderingMode = current.textRenderingMode;
11531    const fontSize = current.fontSize / current.fontSizeScale;
11532    const fillStrokeMode = textRenderingMode & TextRenderingMode.FILL_STROKE_MASK;
11533    const isAddToPathSet = !!(textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG);
11534    const patternFill = current.patternFill && !font.missingFile;
11535    const patternStroke = current.patternStroke && !font.missingFile;
11536    let path;
11537    if ((font.disableFontFace || isAddToPathSet || patternFill || patternStroke) && !font.missingFile) {
11538      path = font.getPathGenerator(this.commonObjs, character);
11539    }
11540    if (path && (font.disableFontFace || patternFill || patternStroke)) {
11541      ctx.save();
11542      ctx.translate(x, y);
11543      ctx.scale(fontSize, -fontSize);
11544      this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font);
11545      let currentTransform;
11546      if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
11547        if (patternFillTransform) {
11548          currentTransform = ctx.getTransform();
11549          ctx.setTransform(...patternFillTransform);
11550          const scaledPath = this.#getScaledPath(path, currentTransform, patternFillTransform);
11551          ctx.fill(scaledPath);
11552        } else {
11553          ctx.fill(path);
11554        }
11555      }
11556      if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
11557        if (patternStrokeTransform) {
11558          currentTransform ||= ctx.getTransform();
11559          ctx.setTransform(...patternStrokeTransform);
11560          const {
11561            a,
11562            b,
11563            c,
11564            d
11565          } = currentTransform;
11566          const invPatternTransform = Util.inverseTransform(patternStrokeTransform);
11567          const transf = Util.transform([a, b, c, d, 0, 0], invPatternTransform);
11568          Util.singularValueDecompose2dScale(transf, XY);
11569          ctx.lineWidth *= Math.max(XY[0], XY[1]) / fontSize;
11570          ctx.stroke(this.#getScaledPath(path, currentTransform, patternStrokeTransform));
11571        } else {
11572          ctx.lineWidth /= fontSize;
11573          ctx.stroke(path);
11574        }
11575      }
11576      ctx.restore();
11577    } else {
11578      if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
11579        ctx.fillText(character, x, y);
11580        this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font, fontSize, x, y, () => ctx.measureText(character));
11581      }
11582      if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
11583        if (this.dependencyTracker) {
11584          this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font, fontSize, x, y, () => ctx.measureText(character)).recordDependencies(opIdx, Dependencies.stroke);
11585        }
11586        ctx.strokeText(character, x, y);
11587      }
11588    }
11589    if (isAddToPathSet) {
11590      const paths = this.pendingTextPaths ||= [];
11591      paths.push({
11592        transform: getCurrentTransform(ctx),
11593        x,
11594        y,
11595        fontSize,
11596        path
11597      });
11598      this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font, fontSize, x, y);
11599    }
11600  }
11601  get isFontSubpixelAAEnabled() {
11602    const {
11603      context: ctx
11604    } = this.cachedCanvases.getCanvas("isFontSubpixelAAEnabled", 10, 10);
11605    ctx.scale(1.5, 1);
11606    ctx.fillText("I", 0, 10);
11607    const data = ctx.getImageData(0, 0, 10, 10).data;
11608    let enabled = false;
11609    for (let i = 3; i < data.length; i += 4) {
11610      if (data[i] > 0 && data[i] < 255) {
11611        enabled = true;
11612        break;
11613      }
11614    }
11615    return shadow(this, "isFontSubpixelAAEnabled", enabled);
11616  }
11617  showText(opIdx, glyphs) {
11618    if (this.dependencyTracker) {
11619      this.dependencyTracker.recordDependencies(opIdx, Dependencies.showText).resetBBox(opIdx);
11620      if (this.current.textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG) {
11621        this.dependencyTracker.recordFutureForcedDependency("textClip", opIdx).inheritPendingDependenciesAsFutureForcedDependencies();
11622      }
11623    }
11624    const current = this.current;
11625    const font = current.font;
11626    if (font.isType3Font) {
11627      this.showType3Text(opIdx, glyphs);
11628      this.dependencyTracker?.recordShowTextOperation(opIdx);
11629      return 
vendor: 7,185 bytes, lines 11629-11806
11629undefined;
11630    }
11631    const fontSize = current.fontSize;
11632    if (fontSize === 0) {
11633      this.dependencyTracker?.recordOperation(opIdx);
11634      return undefined;
11635    }
11636    const ctx = this.ctx;
11637    const fontSizeScale = current.fontSizeScale;
11638    const charSpacing = current.charSpacing;
11639    const wordSpacing = current.wordSpacing;
11640    const fontDirection = current.fontDirection;
11641    const textHScale = current.textHScale * fontDirection;
11642    const glyphsLength = glyphs.length;
11643    const vertical = font.vertical;
11644    const spacingDir = vertical ? 1 : -1;
11645    const defaultVMetrics = font.defaultVMetrics;
11646    const widthAdvanceScale = fontSize * current.fontMatrix[0];
11647    const simpleFillText = current.textRenderingMode === TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill;
11648    ctx.save();
11649    if (current.textMatrix) {
11650      ctx.transform(...current.textMatrix);
11651    }
11652    ctx.translate(current.x, current.y + current.textRise);
11653    if (fontDirection > 0) {
11654      ctx.scale(textHScale, -1);
11655    } else {
11656      ctx.scale(textHScale, 1);
11657    }
11658    let patternFillTransform, patternStrokeTransform;
11659    const fillStrokeMode = current.textRenderingMode & TextRenderingMode.FILL_STROKE_MASK;
11660    const needsFill = fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE;
11661    const needsStroke = fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE;
11662    if (needsFill && current.patternFill) {
11663      ctx.save();
11664      const pattern = current.fillColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.FILL, opIdx);
11665      patternFillTransform = getCurrentTransform(ctx);
11666      ctx.restore();
11667      ctx.fillStyle = pattern;
11668    }
11669    if (needsStroke && current.patternStroke) {
11670      ctx.save();
11671      const pattern = current.strokeColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.STROKE, opIdx);
11672      patternStrokeTransform = getCurrentTransform(ctx);
11673      ctx.restore();
11674      ctx.strokeStyle = pattern;
11675    }
11676    let lineWidth = current.lineWidth;
11677    const scale = current.textMatrixScale;
11678    if (scale === 0 || lineWidth === 0) {
11679      if (needsStroke) {
11680        lineWidth = this.getSinglePixelWidth();
11681      }
11682    } else {
11683      lineWidth /= scale;
11684    }
11685    if (fontSizeScale !== 1.0) {
11686      ctx.scale(fontSizeScale, fontSizeScale);
11687      lineWidth /= fontSizeScale;
11688    }
11689    ctx.lineWidth = lineWidth;
11690    if (font.isInvalidPDFjsFont) {
11691      const chars = [];
11692      let width = 0;
11693      for (const glyph of glyphs) {
11694        chars.push(glyph.unicode);
11695        width += glyph.width;
11696      }
11697      const joinedChars = chars.join("");
11698      ctx.fillText(joinedChars, 0, 0);
11699      if (this.dependencyTracker !== null) {
11700        const measure = ctx.measureText(joinedChars);
11701        this.dependencyTracker.recordBBox(opIdx, this.ctx, -measure.actualBoundingBoxLeft, measure.actualBoundingBoxRight, -measure.actualBoundingBoxAscent, measure.actualBoundingBoxDescent).recordShowTextOperation(opIdx);
11702      }
11703      current.x += width * widthAdvanceScale * textHScale;
11704      ctx.restore();
11705      this.compose();
11706      return undefined;
11707    }
11708    let x = 0,
11709      i;
11710    for (i = 0; i < glyphsLength; ++i) {
11711      const glyph = glyphs[i];
11712      if (typeof glyph === "number") {
11713        x += spacingDir * glyph * fontSize / 1000;
11714        continue;
11715      }
11716      let restoreNeeded = false;
11717      const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
11718      const character = glyph.fontChar;
11719      const accent = glyph.accent;
11720      let scaledX, scaledY;
11721      let width = glyph.width;
11722      if (vertical) {
11723        const vmetric = glyph.vmetric || defaultVMetrics;
11724        const vx = -(glyph.vmetric ? vmetric[1] : width * 0.5) * widthAdvanceScale;
11725        const vy = vmetric[2] * widthAdvanceScale;
11726        width = vmetric ? -vmetric[0] : width;
11727        scaledX = vx / fontSizeScale;
11728        scaledY = (x + vy) / fontSizeScale;
11729      } else {
11730        scaledX = x / fontSizeScale;
11731        scaledY = 0;
11732      }
11733      let measure;
11734      if (font.remeasure && width > 0) {
11735        measure = ctx.measureText(character);
11736        const measuredWidth = measure.width * 1000 / fontSize * fontSizeScale;
11737        if (width < measuredWidth && this.isFontSubpixelAAEnabled) {
11738          const characterScaleX = width / measuredWidth;
11739          restoreNeeded = true;
11740          ctx.save();
11741          ctx.scale(characterScaleX, 1);
11742          scaledX /= characterScaleX;
11743        } else if (width !== measuredWidth) {
11744          scaledX += (width - measuredWidth) / 2000 * fontSize / fontSizeScale;
11745        }
11746      }
11747      if (this.contentVisible && (glyph.isInFont || font.missingFile)) {
11748        if (simpleFillText && !accent) {
11749          ctx.fillText(character, scaledX, scaledY);
11750          this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, measure ? {
11751            bbox: null
11752          } : font, fontSize / fontSizeScale, scaledX, scaledY, () => measure ?? ctx.measureText(character));
11753        } else {
11754          this.paintChar(opIdx, character, scaledX, scaledY, patternFillTransform, patternStrokeTransform);
11755          if (accent) {
11756            const scaledAccentX = scaledX + fontSize * accent.offset.x / fontSizeScale;
11757            const scaledAccentY = scaledY - fontSize * accent.offset.y / fontSizeScale;
11758            this.paintChar(opIdx, accent.fontChar, scaledAccentX, scaledAccentY, patternFillTransform, patternStrokeTransform);
11759          }
11760        }
11761      }
11762      const charWidth = vertical ? width * widthAdvanceScale - spacing * fontDirection : width * widthAdvanceScale + spacing * fontDirection;
11763      x += charWidth;
11764      if (restoreNeeded) {
11765        ctx.restore();
11766      }
11767    }
11768    if (vertical) {
11769      current.y -= x;
11770    } else {
11771      current.x += x * textHScale;
11772    }
11773    ctx.restore();
11774    this.compose();
11775    this.dependencyTracker?.recordShowTextOperation(opIdx);
11776    return undefined;
11777  }
11778  showType3Text(opIdx, glyphs) {
11779    const ctx = this.ctx;
11780    const current = this.current;
11781    const font = current.font;
11782    const fontSize = current.fontSize;
11783    const fontDirection = current.fontDirection;
11784    const spacingDir = font.vertical ? 1 : -1;
11785    const charSpacing = current.charSpacing;
11786    const wordSpacing = current.wordSpacing;
11787    const textHScale = current.textHScale * fontDirection;
11788    const fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
11789    const glyphsLength = glyphs.length;
11790    const isTextInvisible = current.textRenderingMode === TextRenderingMode.INVISIBLE;
11791    let i, glyph, width, spacingLength;
11792    if (isTextInvisible || fontSize === 0) {
11793      return;
11794    }
11795    this._cachedScaleForStroking[0] = -1;
11796    this._cachedGetSinglePixelWidth = null;
11797    ctx.save();
11798    if (current.textMatrix) {
11799      ctx.transform(...current.textMatrix);
11800    }
11801    ctx.translate(current.x, current.y + current.textRise);
11802    ctx.scale(textHScale, fontDirection);
11803    const dependencyTracker = this.dependencyTracker;
11804    this.dependencyTracker = dependencyTracker ? new CanvasNestedDependencyTracker(dependencyTracker, opIdx) : null;
11805    for (i = 0; i < glyphsLength; ++i) {
11806      glyph = glyphs[i];
vendor: 1,863 bytes, lines 11807-11851
11807      if (typeof glyph === "number") {
11808        spacingLength = spacingDir * glyph * fontSize / 1000;
11809        this.ctx.translate(spacingLength, 0);
11810        current.x += spacingLength * textHScale;
11811        continue;
11812      }
11813      const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
11814      const operatorList = font.charProcOperatorList[glyph.operatorListId];
11815      if (!operatorList) {
11816        warn(`Type3 character "${glyph.operatorListId}" is not available.`);
11817      } else if (this.contentVisible) {
11818        this.save();
11819        ctx.scale(fontSize, fontSize);
11820        ctx.transform(...fontMatrix);
11821        this.executeOperatorList(operatorList);
11822        this.restore();
11823      }
11824      const p = [glyph.width, 0];
11825      Util.applyTransform(p, fontMatrix);
11826      width = p[0] * fontSize + spacing;
11827      ctx.translate(width, 0);
11828      current.x += width * textHScale;
11829    }
11830    ctx.restore();
11831    if (dependencyTracker) {
11832      this.dependencyTracker = dependencyTracker;
11833    }
11834  }
11835  setCharWidth(opIdx, xWidth, yWidth) {}
11836  setCharWidthAndBounds(opIdx, xWidth, yWidth, llx, lly, urx, ury) {
11837    const clip = new Path2D();
11838    clip.rect(llx, lly, urx - llx, ury - lly);
11839    this.ctx.clip(clip);
11840    this.dependencyTracker?.recordBBox(opIdx, this.ctx, llx, urx, lly, ury).recordClipBox(opIdx, this.ctx, llx, urx, lly, ury);
11841    this.endPath(opIdx);
11842  }
11843  getColorN_Pattern(opIdx, IR) {
11844    let pattern;
11845    if (IR[0] === "TilingPattern") {
11846      const baseTransform = this.baseTransform || getCurrentTransform(this.ctx);
11847      const canvasGraphicsFactory = {
11848        createCanvasGraphics: (ctx, renderingOpIdx) => new CanvasGraphics(ctx, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, {
11849          optionalContentConfig: this.optionalContentConfig,
11850          markedContentStack: this.markedContentStack
11851        }, undefined, undefined
vendor: 16,709 bytes, lines 11851-12318
11851, this.dependencyTracker ? new CanvasNestedDependencyTracker(this.dependencyTracker, renderingOpIdx, true) : null)
11852      };
11853      pattern = new TilingPattern(IR, this.ctx, canvasGraphicsFactory, baseTransform);
11854    } else {
11855      pattern = this._getPattern(opIdx, IR[1], IR[2]);
11856    }
11857    return pattern;
11858  }
11859  setStrokeColorN(opIdx, ...args) {
11860    this.dependencyTracker?.recordSimpleData("strokeColor", opIdx);
11861    this.current.strokeColor = this.getColorN_Pattern(opIdx, args);
11862    this.current.patternStroke = true;
11863  }
11864  setFillColorN(opIdx, ...args) {
11865    this.dependencyTracker?.recordSimpleData("fillColor", opIdx);
11866    this.current.fillColor = this.getColorN_Pattern(opIdx, args);
11867    this.current.patternFill = true;
11868  }
11869  setStrokeRGBColor(opIdx, color) {
11870    this.dependencyTracker?.recordSimpleData("strokeColor", opIdx);
11871    this.ctx.strokeStyle = this.current.strokeColor = color;
11872    this.current.patternStroke = false;
11873  }
11874  setStrokeTransparent(opIdx) {
11875    this.dependencyTracker?.recordSimpleData("strokeColor", opIdx);
11876    this.ctx.strokeStyle = this.current.strokeColor = "transparent";
11877    this.current.patternStroke = false;
11878  }
11879  setFillRGBColor(opIdx, color) {
11880    this.dependencyTracker?.recordSimpleData("fillColor", opIdx);
11881    this.ctx.fillStyle = this.current.fillColor = color;
11882    this.current.patternFill = false;
11883  }
11884  setFillTransparent(opIdx) {
11885    this.dependencyTracker?.recordSimpleData("fillColor", opIdx);
11886    this.ctx.fillStyle = this.current.fillColor = "transparent";
11887    this.current.patternFill = false;
11888  }
11889  _getPattern(opIdx, objId, matrix = null) {
11890    let pattern;
11891    if (this.cachedPatterns.has(objId)) {
11892      pattern = this.cachedPatterns.get(objId);
11893    } else {
11894      pattern = getShadingPattern(this.getObject(opIdx, objId));
11895      this.cachedPatterns.set(objId, pattern);
11896    }
11897    if (matrix) {
11898      pattern.matrix = matrix;
11899    }
11900    return pattern;
11901  }
11902  shadingFill(opIdx, objId) {
11903    if (!this.contentVisible) {
11904      return;
11905    }
11906    const ctx = this.ctx;
11907    this.save(opIdx);
11908    const pattern = this._getPattern(opIdx, objId);
11909    ctx.fillStyle = pattern.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.SHADING, opIdx);
11910    const inv = getCurrentTransformInverse(ctx);
11911    if (inv) {
11912      const {
11913        width,
11914        height
11915      } = ctx.canvas;
11916      const minMax = MIN_MAX_INIT.slice();
11917      Util.axialAlignedBoundingBox([0, 0, width, height], inv, minMax);
11918      const [x0, y0, x1, y1] = minMax;
11919      this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0);
11920    } else {
11921      this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
11922    }
11923    this.dependencyTracker?.resetBBox(opIdx).recordFullPageBBox(opIdx).recordDependencies(opIdx, Dependencies.transform).recordDependencies(opIdx, Dependencies.fill).recordOperation(opIdx);
11924    this.compose(this.current.getClippedPathBoundingBox());
11925    this.restore(opIdx);
11926  }
11927  beginInlineImage() {
11928    unreachable("Should not call beginInlineImage");
11929  }
11930  beginImageData() {
11931    unreachable("Should not call beginImageData");
11932  }
11933  paintFormXObjectBegin(opIdx, matrix, bbox) {
11934    if (!this.contentVisible) {
11935      return;
11936    }
11937    this.save(opIdx);
11938    this.baseTransformStack.push(this.baseTransform);
11939    if (matrix) {
11940      this.transform(opIdx, ...matrix);
11941    }
11942    this.baseTransform = getCurrentTransform(this.ctx);
11943    if (bbox) {
11944      Util.axialAlignedBoundingBox(bbox, this.baseTransform, this.current.minMax);
11945      const [x0, y0, x1, y1] = bbox;
11946      const clip = new Path2D();
11947      clip.rect(x0, y0, x1 - x0, y1 - y0);
11948      this.ctx.clip(clip);
11949      this.dependencyTracker?.recordClipBox(opIdx, this.ctx, x0, x1, y0, y1);
11950      this.endPath(opIdx);
11951    }
11952  }
11953  paintFormXObjectEnd(opIdx) {
11954    if (!this.contentVisible) {
11955      return;
11956    }
11957    this.restore(opIdx);
11958    this.baseTransform = this.baseTransformStack.pop();
11959  }
11960  beginGroup(opIdx, group) {
11961    if (!this.contentVisible) {
11962      return;
11963    }
11964    this.save(opIdx);
11965    if (this.inSMaskMode) {
11966      this.endSMaskMode();
11967      this.current.activeSMask = null;
11968    }
11969    const currentCtx = this.ctx;
11970    if (!group.isolated) {
11971      info("TODO: Support non-isolated groups.");
11972    }
11973    if (group.knockout) {
11974      warn("Knockout groups not supported.");
11975    }
11976    const currentTransform = getCurrentTransform(currentCtx);
11977    if (group.matrix) {
11978      currentCtx.transform(...group.matrix);
11979    }
11980    if (!group.bbox) {
11981      throw new Error("Bounding box is required.");
11982    }
11983    let bounds = MIN_MAX_INIT.slice();
11984    Util.axialAlignedBoundingBox(group.bbox, getCurrentTransform(currentCtx), bounds);
11985    const canvasBounds = [0, 0, currentCtx.canvas.width, currentCtx.canvas.height];
11986    bounds = Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0];
11987    const offsetX = Math.floor(bounds[0]);
11988    const offsetY = Math.floor(bounds[1]);
11989    const drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1);
11990    const drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1);
11991    this.current.startNewPathAndClipBox([0, 0, drawnWidth, drawnHeight]);
11992    let cacheId = "groupAt" + this.groupLevel;
11993    if (group.smask) {
11994      cacheId += "_smask_" + this.smaskCounter++ % 2;
11995    }
11996    const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight);
11997    const groupCtx = scratchCanvas.context;
11998    groupCtx.translate(-offsetX, -offsetY);
11999    groupCtx.transform(...currentTransform);
12000    let clip = new Path2D();
12001    const [x0, y0, x1, y1] = group.bbox;
12002    clip.rect(x0, y0, x1 - x0, y1 - y0);
12003    if (group.matrix) {
12004      const path = new Path2D();
12005      path.addPath(clip, new DOMMatrix(group.matrix));
12006      clip = path;
12007    }
12008    groupCtx.clip(clip);
12009    if (group.smask) {
12010      this.smaskStack.push({
12011        canvas: scratchCanvas.canvas,
12012        context: groupCtx,
12013        offsetX,
12014        offsetY,
12015        subtype: group.smask.subtype,
12016        backdrop: group.smask.backdrop,
12017        transferMap: group.smask.transferMap || null,
12018        startTransformInverse: null
12019      });
12020    }
12021    if (!group.smask || this.dependencyTracker) {
12022      currentCtx.setTransform(1, 0, 0, 1, 0, 0);
12023      currentCtx.translate(offsetX, offsetY);
12024      currentCtx.save();
12025    }
12026    copyCtxState(currentCtx, groupCtx);
12027    this.ctx = groupCtx;
12028    this.dependencyTracker?.inheritSimpleDataAsFutureForcedDependencies(["fillAlpha", "strokeAlpha", "globalCompositeOperation"]).pushBaseTransform(currentCtx);
12029    this.setGState(opIdx, [["BM", "source-over"], ["ca", 1], ["CA", 1]]);
12030    this.groupStack.push(currentCtx);
12031    this.groupLevel++;
12032  }
12033  endGroup(opIdx, group) {
12034    if (!this.contentVisible) {
12035      return;
12036    }
12037    this.groupLevel--;
12038    const groupCtx = this.ctx;
12039    const ctx = this.groupStack.pop();
12040    this.ctx = ctx;
12041    this.ctx.imageSmoothingEnabled = false;
12042    this.dependencyTracker?.popBaseTransform();
12043    if (group.smask) {
12044      this.tempSMask = this.smaskStack.pop();
12045      this.restore(opIdx);
12046      if (this.dependencyTracker) {
12047        this.ctx.restore();
12048      }
12049    } else {
12050      this.ctx.restore();
12051      const currentMtx = getCurrentTransform(this.ctx);
12052      this.restore(opIdx);
12053      this.ctx.save();
12054      this.ctx.setTransform(...currentMtx);
12055      const dirtyBox = MIN_MAX_INIT.slice();
12056      Util.axialAlignedBoundingBox([0, 0, groupCtx.canvas.width, groupCtx.canvas.height], currentMtx, dirtyBox);
12057      this.ctx.drawImage(groupCtx.canvas, 0, 0);
12058      this.ctx.restore();
12059      this.compose(dirtyBox);
12060    }
12061  }
12062  beginAnnotation(opIdx, id, rect, transform, matrix, hasOwnCanvas) {
12063    this.#restoreInitialState();
12064    resetCtxToDefault(this.ctx);
12065    this.ctx.save();
12066    this.save(opIdx);
12067    if (this.baseTransform) {
12068      this.ctx.setTransform(...this.baseTransform);
12069    }
12070    if (rect) {
12071      const width = rect[2] - rect[0];
12072      const height = rect[3] - rect[1];
12073      if (hasOwnCanvas && this.annotationCanvasMap) {
12074        transform = transform.slice();
12075        transform[4] -= rect[0];
12076        transform[5] -= rect[1];
12077        rect = rect.slice();
12078        rect[0] = rect[1] = 0;
12079        rect[2] = width;
12080        rect[3] = height;
12081        Util.singularValueDecompose2dScale(getCurrentTransform(this.ctx), XY);
12082        const {
12083          viewportScale
12084        } = this;
12085        const canvasWidth = Math.ceil(width * this.outputScaleX * viewportScale);
12086        const canvasHeight = Math.ceil(height * this.outputScaleY * viewportScale);
12087        this.annotationCanvas = this.canvasFactory.create(canvasWidth, canvasHeight);
12088        const {
12089          canvas,
12090          context
12091        } = this.annotationCanvas;
12092        this.annotationCanvasMap.set(id, canvas);
12093        this.annotationCanvas.savedCtx = this.ctx;
12094        this.ctx = context;
12095        this.ctx.save();
12096        this.ctx.setTransform(XY[0], 0, 0, -XY[1], 0, height * XY[1]);
12097        resetCtxToDefault(this.ctx);
12098      } else {
12099        resetCtxToDefault(this.ctx);
12100        this.endPath(opIdx);
12101        const clip = new Path2D();
12102        clip.rect(rect[0], rect[1], width, height);
12103        this.ctx.clip(clip);
12104      }
12105    }
12106    this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height);
12107    this.transform(opIdx, ...transform);
12108    this.transform(opIdx, ...matrix);
12109  }
12110  endAnnotation(opIdx) {
12111    if (this.annotationCanvas) {
12112      this.ctx.restore();
12113      this.#drawFilter();
12114      this.ctx = this.annotationCanvas.savedCtx;
12115      delete this.annotationCanvas.savedCtx;
12116      delete this.annotationCanvas;
12117    }
12118  }
12119  paintImageMaskXObject(opIdx, img) {
12120    if (!this.contentVisible) {
12121      return;
12122    }
12123    const count = img.count;
12124    img = this.getObject(opIdx, img.data, img);
12125    img.count = count;
12126    const ctx = this.ctx;
12127    const mask = this._createMaskCanvas(opIdx, img);
12128    const maskCanvas = mask.canvas;
12129    ctx.save();
12130    ctx.setTransform(1, 0, 0, 1, 0, 0);
12131    ctx.drawImage(maskCanvas, mask.offsetX, mask.offsetY);
12132    this.dependencyTracker?.resetBBox(opIdx).recordBBox(opIdx, this.ctx, mask.offsetX, mask.offsetX + maskCanvas.width, mask.offsetY, mask.offsetY + maskCanvas.height).recordOperation(opIdx);
12133    ctx.restore();
12134    this.compose();
12135  }
12136  paintImageMaskXObjectRepeat(opIdx, img, scaleX, skewX = 0, skewY = 0, scaleY, positions) {
12137    if (!this.contentVisible) {
12138      return;
12139    }
12140    img = this.getObject(opIdx, img.data, img);
12141    const ctx = this.ctx;
12142    ctx.save();
12143    const currentTransform = getCurrentTransform(ctx);
12144    ctx.transform(scaleX, skewX, skewY, scaleY, 0, 0);
12145    const mask = this._createMaskCanvas(opIdx, img);
12146    ctx.setTransform(1, 0, 0, 1, mask.offsetX - currentTransform[4], mask.offsetY - currentTransform[5]);
12147    this.dependencyTracker?.resetBBox(opIdx);
12148    for (let i = 0, ii = positions.length; i < ii; i += 2) {
12149      const trans = Util.transform(currentTransform, [scaleX, skewX, skewY, scaleY, positions[i], positions[i + 1]]);
12150      ctx.drawImage(mask.canvas, trans[4], trans[5]);
12151      this.dependencyTracker?.recordBBox(opIdx, this.ctx, trans[4], trans[4] + mask.canvas.width, trans[5], trans[5] + mask.canvas.height);
12152    }
12153    ctx.restore();
12154    this.compose();
12155    this.dependencyTracker?.recordOperation(opIdx);
12156  }
12157  paintImageMaskXObjectGroup(opIdx, images) {
12158    if (!this.contentVisible) {
12159      return;
12160    }
12161    const ctx = this.ctx;
12162    const fillColor = this.current.fillColor;
12163    const isPatternFill = this.current.patternFill;
12164    this.dependencyTracker?.resetBBox(opIdx).recordDependencies(opIdx, Dependencies.transformAndFill);
12165    for (const image of images) {
12166      const {
12167        data,
12168        width,
12169        height,
12170        transform
12171      } = image;
12172      const maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height);
12173      const maskCtx = maskCanvas.context;
12174      maskCtx.save();
12175      const img = this.getObject(opIdx, data, image);
12176      putBinaryImageMask(maskCtx, img);
12177      maskCtx.globalCompositeOperation = "source-in";
12178      maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, getCurrentTransformInverse(ctx), PathType.FILL, opIdx) : fillColor;
12179      maskCtx.fillRect(0, 0, width, height);
12180      maskCtx.restore();
12181      ctx.save();
12182      ctx.transform(...transform);
12183      ctx.scale(1, -1);
12184      drawImageAtIntegerCoords(ctx, maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
12185      this.dependencyTracker?.recordBBox(opIdx, ctx, 0, width, 0, height);
12186      ctx.restore();
12187    }
12188    this.compose();
12189    this.dependencyTracker?.recordOperation(opIdx);
12190  }
12191  paintImageXObject(opIdx, objId) {
12192    if (!this.contentVisible) {
12193      return;
12194    }
12195    const imgData = this.getObject(opIdx, objId);
12196    if (!imgData) {
12197      warn("Dependent image isn't ready yet");
12198      return;
12199    }
12200    this.paintInlineImageXObject(opIdx, imgData);
12201  }
12202  paintImageXObjectRepeat(opIdx, objId, scaleX, scaleY, positions) {
12203    if (!this.contentVisible) {
12204      return;
12205    }
12206    const imgData = this.getObject(opIdx, objId);
12207    if (!imgData) {
12208      warn("Dependent image isn't ready yet");
12209      return;
12210    }
12211    const width = imgData.width;
12212    const height = imgData.height;
12213    const map = [];
12214    for (let i = 0, ii = positions.length; i < ii; i += 2) {
12215      map.push({
12216        transform: [scaleX, 0, 0, scaleY, positions[i], positions[i + 1]],
12217        x: 0,
12218        y: 0,
12219        w: width,
12220        h: height
12221      });
12222    }
12223    this.paintInlineImageXObjectGroup(opIdx, imgData, map);
12224  }
12225  applyTransferMapsToCanvas(ctx) {
12226    if (this.current.transferMaps !== "none") {
12227      ctx.filter = this.current.transferMaps;
12228      ctx.drawImage(ctx.canvas, 0, 0);
12229      ctx.filter = "none";
12230    }
12231    return ctx.canvas;
12232  }
12233  applyTransferMapsToBitmap(imgData) {
12234    if (this.current.transferMaps === "none") {
12235      return imgData.bitmap;
12236    }
12237    const {
12238      bitmap,
12239      width,
12240      height
12241    } = imgData;
12242    const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height);
12243    const tmpCtx = tmpCanvas.context;
12244    tmpCtx.filter = this.current.transferMaps;
12245    tmpCtx.drawImage(bitmap, 0, 0);
12246    tmpCtx.filter = "none";
12247    return tmpCanvas.canvas;
12248  }
12249  paintInlineImageXObject(opIdx, imgData) {
12250    if (!this.contentVisible) {
12251      return;
12252    }
12253    const width = imgData.width;
12254    const height = imgData.height;
12255    const ctx = this.ctx;
12256    this.save(opIdx);
12257    const {
12258      filter
12259    } = ctx;
12260    if (filter !== "none" && filter !== "") {
12261      ctx.filter = "none";
12262    }
12263    ctx.scale(1 / width, -1 / height);
12264    let imgToPaint;
12265    if (imgData.bitmap) {
12266      imgToPaint = this.applyTransferMapsToBitmap(imgData);
12267    } else if (typeof HTMLElement === "function" && imgData instanceof HTMLElement || !imgData.data) {
12268      imgToPaint = imgData;
12269    } else {
12270      const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height);
12271      const tmpCtx = tmpCanvas.context;
12272      putBinaryImageData(tmpCtx, imgData);
12273      imgToPaint = this.applyTransferMapsToCanvas(tmpCtx);
12274    }
12275    const scaled = this._scaleImage(imgToPaint, getCurrentTransformInverse(ctx));
12276    ctx.imageSmoothingEnabled = getImageSmoothingEnabled(getCurrentTransform(ctx), imgData.interpolate);
12277    this.dependencyTracker?.resetBBox(opIdx).recordBBox(opIdx, ctx, 0, width, -height, 0).recordDependencies(opIdx, Dependencies.imageXObject).recordOperation(opIdx);
12278    drawImageAtIntegerCoords(ctx, scaled.img, 0, 0, scaled.paintWidth, scaled.paintHeight, 0, -height, width, height);
12279    this.compose();
12280    this.restore(opIdx);
12281  }
12282  paintInlineImageXObjectGroup(opIdx, imgData, map) {
12283    if (!this.contentVisible) {
12284      return;
12285    }
12286    const ctx = this.ctx;
12287    let imgToPaint;
12288    if (imgData.bitmap) {
12289      imgToPaint = imgData.bitmap;
12290    } else {
12291      const w = imgData.width;
12292      const h = imgData.height;
12293      const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", w, h);
12294      const tmpCtx = tmpCanvas.context;
12295      putBinaryImageData(tmpCtx, imgData);
12296      imgToPaint = this.applyTransferMapsToCanvas(tmpCtx);
12297    }
12298    this.dependencyTracker?.resetBBox(opIdx);
12299    for (const entry of map) {
12300      ctx.save();
12301      ctx.transform(...entry.transform);
12302      ctx.scale(1, -1);
12303      drawImageAtIntegerCoords(ctx, imgToPaint, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1);
12304      this.dependencyTracker?.recordBBox(opIdx, ctx, 0, 1, -1, 0);
12305      ctx.restore();
12306    }
12307    this.dependencyTracker?.recordOperation(opIdx);
12308    this.compose();
12309  }
12310  paintSolidColorImageMask(opIdx) {
12311    if (!this.contentVisible) {
12312      return;
12313    }
12314    this.dependencyTracker?.resetBBox(opIdx).recordBBox(opIdx, this.ctx, 0, 1, 0, 1).recordDependencies(opIdx, Dependencies.fill).recordOperation(opIdx);
12315    this.ctx.fillRect(0, 0, 1, 1);
12316    this.compose();
12317  }
12318  markPoint(opIdx, tag) {
vendor: 29,675 bytes, lines 12318-13409
12318}
12319  markPointProps(opIdx, tag, properties) {}
12320  beginMarkedContent(opIdx, tag) {
12321    this.dependencyTracker?.beginMarkedContent(opIdx);
12322    this.markedContentStack.push({
12323      visible: true
12324    });
12325  }
12326  beginMarkedContentProps(opIdx, tag, properties) {
12327    this.dependencyTracker?.beginMarkedContent(opIdx);
12328    if (tag === "OC") {
12329      this.markedContentStack.push({
12330        visible: this.optionalContentConfig.isVisible(properties)
12331      });
12332    } else {
12333      this.markedContentStack.push({
12334        visible: true
12335      });
12336    }
12337    this.contentVisible = this.isContentVisible();
12338  }
12339  endMarkedContent(opIdx) {
12340    this.dependencyTracker?.endMarkedContent(opIdx);
12341    this.markedContentStack.pop();
12342    this.contentVisible = this.isContentVisible();
12343  }
12344  beginCompat(opIdx) {}
12345  endCompat(opIdx) {}
12346  consumePath(opIdx, path, clipBox) {
12347    const isEmpty = this.current.isEmptyClip();
12348    if (this.pendingClip) {
12349      this.current.updateClipFromPath();
12350    }
12351    if (!this.pendingClip) {
12352      this.compose(clipBox);
12353    }
12354    const ctx = this.ctx;
12355    if (this.pendingClip) {
12356      if (!isEmpty) {
12357        if (this.pendingClip === EO_CLIP) {
12358          ctx.clip(path, "evenodd");
12359        } else {
12360          ctx.clip(path);
12361        }
12362      }
12363      this.pendingClip = null;
12364      this.dependencyTracker?.bboxToClipBoxDropOperation(opIdx).recordFutureForcedDependency("clipPath", opIdx);
12365    } else {
12366      this.dependencyTracker?.recordOperation(opIdx);
12367    }
12368    this.current.startNewPathAndClipBox(this.current.clipBox);
12369  }
12370  getSinglePixelWidth() {
12371    if (!this._cachedGetSinglePixelWidth) {
12372      const m = getCurrentTransform(this.ctx);
12373      if (m[1] === 0 && m[2] === 0) {
12374        this._cachedGetSinglePixelWidth = 1 / Math.min(Math.abs(m[0]), Math.abs(m[3]));
12375      } else {
12376        const absDet = Math.abs(m[0] * m[3] - m[2] * m[1]);
12377        const normX = Math.hypot(m[0], m[2]);
12378        const normY = Math.hypot(m[1], m[3]);
12379        this._cachedGetSinglePixelWidth = Math.max(normX, normY) / absDet;
12380      }
12381    }
12382    return this._cachedGetSinglePixelWidth;
12383  }
12384  getScaleForStroking() {
12385    if (this._cachedScaleForStroking[0] === -1) {
12386      const {
12387        lineWidth
12388      } = this.current;
12389      const {
12390        a,
12391        b,
12392        c,
12393        d
12394      } = this.ctx.getTransform();
12395      let scaleX, scaleY;
12396      if (b === 0 && c === 0) {
12397        const normX = Math.abs(a);
12398        const normY = Math.abs(d);
12399        if (normX === normY) {
12400          if (lineWidth === 0) {
12401            scaleX = scaleY = 1 / normX;
12402          } else {
12403            const scaledLineWidth = normX * lineWidth;
12404            scaleX = scaleY = scaledLineWidth < 1 ? 1 / scaledLineWidth : 1;
12405          }
12406        } else if (lineWidth === 0) {
12407          scaleX = 1 / normX;
12408          scaleY = 1 / normY;
12409        } else {
12410          const scaledXLineWidth = normX * lineWidth;
12411          const scaledYLineWidth = normY * lineWidth;
12412          scaleX = scaledXLineWidth < 1 ? 1 / scaledXLineWidth : 1;
12413          scaleY = scaledYLineWidth < 1 ? 1 / scaledYLineWidth : 1;
12414        }
12415      } else {
12416        const absDet = Math.abs(a * d - b * c);
12417        const normX = Math.hypot(a, b);
12418        const normY = Math.hypot(c, d);
12419        if (lineWidth === 0) {
12420          scaleX = normY / absDet;
12421          scaleY = normX / absDet;
12422        } else {
12423          const baseArea = lineWidth * absDet;
12424          scaleX = normY > baseArea ? normY / baseArea : 1;
12425          scaleY = normX > baseArea ? normX / baseArea : 1;
12426        }
12427      }
12428      this._cachedScaleForStroking[0] = scaleX;
12429      this._cachedScaleForStroking[1] = scaleY;
12430    }
12431    return this._cachedScaleForStroking;
12432  }
12433  rescaleAndStroke(path, saveRestore) {
12434    const {
12435      ctx,
12436      current: {
12437        lineWidth
12438      }
12439    } = this;
12440    const [scaleX, scaleY] = this.getScaleForStroking();
12441    if (scaleX === scaleY) {
12442      ctx.lineWidth = (lineWidth || 1) * scaleX;
12443      ctx.stroke(path);
12444      return;
12445    }
12446    const dashes = ctx.getLineDash();
12447    if (saveRestore) {
12448      ctx.save();
12449    }
12450    ctx.scale(scaleX, scaleY);
12451    SCALE_MATRIX.a = 1 / scaleX;
12452    SCALE_MATRIX.d = 1 / scaleY;
12453    const newPath = new Path2D();
12454    newPath.addPath(path, SCALE_MATRIX);
12455    if (dashes.length > 0) {
12456      const scale = Math.max(scaleX, scaleY);
12457      ctx.setLineDash(dashes.map(x => x / scale));
12458      ctx.lineDashOffset /= scale;
12459    }
12460    ctx.lineWidth = lineWidth || 1;
12461    ctx.stroke(newPath);
12462    if (saveRestore) {
12463      ctx.restore();
12464    }
12465  }
12466  isContentVisible() {
12467    for (let i = this.markedContentStack.length - 1; i >= 0; i--) {
12468      if (!this.markedContentStack[i].visible) {
12469        return false;
12470      }
12471    }
12472    return true;
12473  }
12474}
12475for (const op in OPS) {
12476  if (CanvasGraphics.prototype[op] !== undefined) {
12477    CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op];
12478  }
12479}
12480
12481;// ./src/display/worker_options.js
12482class GlobalWorkerOptions {
12483  static #port = null;
12484  static #src = "";
12485  static get workerPort() {
12486    return this.#port;
12487  }
12488  static set workerPort(val) {
12489    if (!(typeof Worker !== "undefined" && val instanceof Worker) && val !== null) {
12490      throw new Error("Invalid `workerPort` type.");
12491    }
12492    this.#port = val;
12493  }
12494  static get workerSrc() {
12495    return this.#src;
12496  }
12497  static set workerSrc(val) {
12498    if (typeof val !== "string") {
12499      throw new Error("Invalid `workerSrc` type.");
12500    }
12501    this.#src = val;
12502  }
12503}
12504
12505;// ./src/display/metadata.js
12506class Metadata {
12507  #map;
12508  #data;
12509  constructor({
12510    parsedData,
12511    rawData
12512  }) {
12513    this.#map = parsedData;
12514    this.#data = rawData;
12515  }
12516  getRaw() {
12517    return this.#data;
12518  }
12519  get(name) {
12520    return this.#map.get(name) ?? null;
12521  }
12522  [Symbol.iterator]() {
12523    return this.#map.entries();
12524  }
12525}
12526
12527;// ./src/display/optional_content_config.js
12528
12529
12530const INTERNAL = Symbol("INTERNAL");
12531class OptionalContentGroup {
12532  #isDisplay = false;
12533  #isPrint = false;
12534  #userSet = false;
12535  #visible = true;
12536  constructor(renderingIntent, {
12537    name,
12538    intent,
12539    usage,
12540    rbGroups
12541  }) {
12542    this.#isDisplay = !!(renderingIntent & RenderingIntentFlag.DISPLAY);
12543    this.#isPrint = !!(renderingIntent & RenderingIntentFlag.PRINT);
12544    this.name = name;
12545    this.intent = intent;
12546    this.usage = usage;
12547    this.rbGroups = rbGroups;
12548  }
12549  get visible() {
12550    if (this.#userSet) {
12551      return this.#visible;
12552    }
12553    if (!this.#visible) {
12554      return false;
12555    }
12556    const {
12557      print,
12558      view
12559    } = this.usage;
12560    if (this.#isDisplay) {
12561      return view?.viewState !== "OFF";
12562    } else if (this.#isPrint) {
12563      return print?.printState !== "OFF";
12564    }
12565    return true;
12566  }
12567  _setVisible(internal, visible, userSet = false) {
12568    if (internal !== INTERNAL) {
12569      unreachable("Internal method `_setVisible` called.");
12570    }
12571    this.#userSet = userSet;
12572    this.#visible = visible;
12573  }
12574}
12575class OptionalContentConfig {
12576  #cachedGetHash = null;
12577  #groups = new Map();
12578  #initialHash = null;
12579  #order = null;
12580  constructor(data, renderingIntent = RenderingIntentFlag.DISPLAY) {
12581    this.renderingIntent = renderingIntent;
12582    this.name = null;
12583    this.creator = null;
12584    if (data === null) {
12585      return;
12586    }
12587    this.name = data.name;
12588    this.creator = data.creator;
12589    this.#order = data.order;
12590    for (const group of data.groups) {
12591      this.#groups.set(group.id, new OptionalContentGroup(renderingIntent, group));
12592    }
12593    if (data.baseState === "OFF") {
12594      for (const group of this.#groups.values()) {
12595        group._setVisible(INTERNAL, false);
12596      }
12597    }
12598    for (const on of data.on) {
12599      this.#groups.get(on)._setVisible(INTERNAL, true);
12600    }
12601    for (const off of data.off) {
12602      this.#groups.get(off)._setVisible(INTERNAL, false);
12603    }
12604    this.#initialHash = this.getHash();
12605  }
12606  #evaluateVisibilityExpression(array) {
12607    const length = array.length;
12608    if (length < 2) {
12609      return true;
12610    }
12611    const operator = array[0];
12612    for (let i = 1; i < length; i++) {
12613      const element = array[i];
12614      let state;
12615      if (Array.isArray(element)) {
12616        state = this.#evaluateVisibilityExpression(element);
12617      } else if (this.#groups.has(element)) {
12618        state = this.#groups.get(element).visible;
12619      } else {
12620        warn(`Optional content group not found: ${element}`);
12621        return true;
12622      }
12623      switch (operator) {
12624        case "And":
12625          if (!state) {
12626            return false;
12627          }
12628          break;
12629        case "Or":
12630          if (state) {
12631            return true;
12632          }
12633          break;
12634        case "Not":
12635          return !state;
12636        default:
12637          return true;
12638      }
12639    }
12640    return operator === "And";
12641  }
12642  isVisible(group) {
12643    if (this.#groups.size === 0) {
12644      return true;
12645    }
12646    if (!group) {
12647      info("Optional content group not defined.");
12648      return true;
12649    }
12650    if (group.type === "OCG") {
12651      if (!this.#groups.has(group.id)) {
12652        warn(`Optional content group not found: ${group.id}`);
12653        return true;
12654      }
12655      return this.#groups.get(group.id).visible;
12656    } else if (group.type === "OCMD") {
12657      if (group.expression) {
12658        return this.#evaluateVisibilityExpression(group.expression);
12659      }
12660      if (!group.policy || group.policy === "AnyOn") {
12661        for (const id of group.ids) {
12662          if (!this.#groups.has(id)) {
12663            warn(`Optional content group not found: ${id}`);
12664            return true;
12665          }
12666          if (this.#groups.get(id).visible) {
12667            return true;
12668          }
12669        }
12670        return false;
12671      } else if (group.policy === "AllOn") {
12672        for (const id of group.ids) {
12673          if (!this.#groups.has(id)) {
12674            warn(`Optional content group not found: ${id}`);
12675            return true;
12676          }
12677          if (!this.#groups.get(id).visible) {
12678            return false;
12679          }
12680        }
12681        return true;
12682      } else if (group.policy === "AnyOff") {
12683        for (const id of group.ids) {
12684          if (!this.#groups.has(id)) {
12685            warn(`Optional content group not found: ${id}`);
12686            return true;
12687          }
12688          if (!this.#groups.get(id).visible) {
12689            return true;
12690          }
12691        }
12692        return false;
12693      } else if (group.policy === "AllOff") {
12694        for (const id of group.ids) {
12695          if (!this.#groups.has(id)) {
12696            warn(`Optional content group not found: ${id}`);
12697            return true;
12698          }
12699          if (this.#groups.get(id).visible) {
12700            return false;
12701          }
12702        }
12703        return true;
12704      }
12705      warn(`Unknown optional content policy ${group.policy}.`);
12706      return true;
12707    }
12708    warn(`Unknown group type ${group.type}.`);
12709    return true;
12710  }
12711  setVisibility(id, visible = true, preserveRB = true) {
12712    const group = this.#groups.get(id);
12713    if (!group) {
12714      warn(`Optional content group not found: ${id}`);
12715      return;
12716    }
12717    if (preserveRB && visible && group.rbGroups.length) {
12718      for (const rbGroup of group.rbGroups) {
12719        for (const otherId of rbGroup) {
12720          if (otherId !== id) {
12721            this.#groups.get(otherId)?._setVisible(INTERNAL, false, true);
12722          }
12723        }
12724      }
12725    }
12726    group._setVisible(INTERNAL, !!visible, true);
12727    this.#cachedGetHash = null;
12728  }
12729  setOCGState({
12730    state,
12731    preserveRB
12732  }) {
12733    let operator;
12734    for (const elem of state) {
12735      switch (elem) {
12736        case "ON":
12737        case "OFF":
12738        case "Toggle":
12739          operator = elem;
12740          continue;
12741      }
12742      const group = this.#groups.get(elem);
12743      if (!group) {
12744        continue;
12745      }
12746      switch (operator) {
12747        case "ON":
12748          this.setVisibility(elem, true, preserveRB);
12749          break;
12750        case "OFF":
12751          this.setVisibility(elem, false, preserveRB);
12752          break;
12753        case "Toggle":
12754          this.setVisibility(elem, !group.visible, preserveRB);
12755          break;
12756      }
12757    }
12758    this.#cachedGetHash = null;
12759  }
12760  get hasInitialVisibility() {
12761    return this.#initialHash === null || this.getHash() === this.#initialHash;
12762  }
12763  getOrder() {
12764    if (!this.#groups.size) {
12765      return null;
12766    }
12767    if (this.#order) {
12768      return this.#order.slice();
12769    }
12770    return [...this.#groups.keys()];
12771  }
12772  getGroup(id) {
12773    return this.#groups.get(id) || null;
12774  }
12775  getHash() {
12776    if (this.#cachedGetHash !== null) {
12777      return this.#cachedGetHash;
12778    }
12779    const hash = new MurmurHash3_64();
12780    for (const [id, group] of this.#groups) {
12781      hash.update(`${id}:${group.visible}`);
12782    }
12783    return this.#cachedGetHash = hash.hexdigest();
12784  }
12785  [Symbol.iterator]() {
12786    return this.#groups.entries();
12787  }
12788}
12789
12790;// ./src/shared/base_pdf_stream.js
12791
12792class BasePDFStream {
12793  #PDFStreamReader = null;
12794  #PDFStreamRangeReader = null;
12795  _fullReader = null;
12796  _rangeReaders = new Set();
12797  _source = null;
12798  constructor(source, PDFStreamReader, PDFStreamRangeReader) {
12799    this._source = source;
12800    this.#PDFStreamReader = PDFStreamReader;
12801    this.#PDFStreamRangeReader = PDFStreamRangeReader;
12802  }
12803  get _progressiveDataLength() {
12804    return this._fullReader?._loaded ?? 0;
12805  }
12806  getFullReader() {
12807    assert(!this._fullReader, "BasePDFStream.getFullReader can only be called once.");
12808    return this._fullReader = new this.#PDFStreamReader(this);
12809  }
12810  getRangeReader(begin, end) {
12811    if (end <= this._progressiveDataLength) {
12812      return null;
12813    }
12814    const reader = new this.#PDFStreamRangeReader(this, begin, end);
12815    this._rangeReaders.add(reader);
12816    return reader;
12817  }
12818  cancelAllRequests(reason) {
12819    this._fullReader?.cancel(reason);
12820    for (const reader of new Set(this._rangeReaders)) {
12821      reader.cancel(reason);
12822    }
12823  }
12824}
12825class BasePDFStreamReader {
12826  onProgress = null;
12827  _contentLength = 0;
12828  _filename = null;
12829  _headersCapability = Promise.withResolvers();
12830  _isRangeSupported = false;
12831  _isStreamingSupported = false;
12832  _loaded = 0;
12833  _stream = null;
12834  constructor(stream) {
12835    this._stream = stream;
12836  }
12837  get headersReady() {
12838    return this._headersCapability.promise;
12839  }
12840  get filename() {
12841    return this._filename;
12842  }
12843  get contentLength() {
12844    return this._contentLength;
12845  }
12846  get isRangeSupported() {
12847    return this._isRangeSupported;
12848  }
12849  get isStreamingSupported() {
12850    return this._isStreamingSupported;
12851  }
12852  async read() {
12853    unreachable("Abstract method `read` called");
12854  }
12855  cancel(reason) {
12856    unreachable("Abstract method `cancel` called");
12857  }
12858}
12859class BasePDFStreamRangeReader {
12860  _stream = null;
12861  constructor(stream, begin, end) {
12862    this._stream = stream;
12863  }
12864  async read() {
12865    unreachable("Abstract method `read` called");
12866  }
12867  cancel(reason) {
12868    unreachable("Abstract method `cancel` called");
12869  }
12870}
12871
12872;// ./src/display/transport_stream.js
12873
12874
12875
12876function getArrayBuffer(val) {
12877  return val instanceof Uint8Array && val.byteLength === val.buffer.byteLength ? val.buffer : new Uint8Array(val).buffer;
12878}
12879class PDFDataTransportStream extends BasePDFStream {
12880  _progressiveDone = false;
12881  _queuedChunks = [];
12882  constructor(source) {
12883    super(source, PDFDataTransportStreamReader, PDFDataTransportStreamRangeReader);
12884    const {
12885      pdfDataRangeTransport
12886    } = source;
12887    const {
12888      initialData,
12889      progressiveDone
12890    } = pdfDataRangeTransport;
12891    if (initialData?.length > 0) {
12892      const buffer = getArrayBuffer(initialData);
12893      this._queuedChunks.push(buffer);
12894    }
12895    this._progressiveDone = progressiveDone;
12896    pdfDataRangeTransport.addRangeListener((begin, chunk) => {
12897      this.#onReceiveData(begin, chunk);
12898    });
12899    pdfDataRangeTransport.addProgressListener((loaded, total) => {
12900      if (total !== undefined) {
12901        this._fullReader?.onProgress?.({
12902          loaded,
12903          total
12904        });
12905      }
12906    });
12907    pdfDataRangeTransport.addProgressiveReadListener(chunk => {
12908      this.#onReceiveData(undefined, chunk);
12909    });
12910    pdfDataRangeTransport.addProgressiveDoneListener(() => {
12911      this._fullReader?.progressiveDone();
12912      this._progressiveDone = true;
12913    });
12914    pdfDataRangeTransport.transportReady();
12915  }
12916  #onReceiveData(begin, chunk) {
12917    const buffer = getArrayBuffer(chunk);
12918    if (begin === undefined) {
12919      if (this._fullReader) {
12920        this._fullReader._enqueue(buffer);
12921      } else {
12922        this._queuedChunks.push(buffer);
12923      }
12924    } else {
12925      const rangeReader = this._rangeReaders.keys().find(r => r._begin === begin);
12926      assert(rangeReader, "#onReceiveData - no `PDFDataTransportStreamRangeReader` instance found.");
12927      rangeReader._enqueue(buffer);
12928    }
12929  }
12930  getFullReader() {
12931    const reader = super.getFullReader();
12932    this._queuedChunks = null;
12933    return reader;
12934  }
12935  getRangeReader(begin, end) {
12936    const reader = super.getRangeReader(begin, end);
12937    if (reader) {
12938      reader.onDone = () => this._rangeReaders.delete(reader);
12939      this._source.pdfDataRangeTransport.requestDataRange(begin, end);
12940    }
12941    return reader;
12942  }
12943  cancelAllRequests(reason) {
12944    super.cancelAllRequests(reason);
12945    this._source.pdfDataRangeTransport.abort();
12946  }
12947}
12948class PDFDataTransportStreamReader extends BasePDFStreamReader {
12949  _done = false;
12950  _queuedChunks = null;
12951  _requests = [];
12952  constructor(stream) {
12953    super(stream);
12954    const {
12955      pdfDataRangeTransport,
12956      disableRange,
12957      disableStream
12958    } = stream._source;
12959    const {
12960      length,
12961      contentDispositionFilename
12962    } = pdfDataRangeTransport;
12963    this._queuedChunks = stream._queuedChunks || [];
12964    for (const chunk of this._queuedChunks) {
12965      this._loaded += chunk.byteLength;
12966    }
12967    this._done = stream._progressiveDone;
12968    this._contentLength = length;
12969    this._isStreamingSupported = !disableStream;
12970    this._isRangeSupported = !disableRange;
12971    if (isPdfFile(contentDispositionFilename)) {
12972      this._filename = contentDispositionFilename;
12973    }
12974    this._headersCapability.resolve();
12975  }
12976  _enqueue(chunk) {
12977    if (this._done) {
12978      return;
12979    }
12980    if (this._requests.length > 0) {
12981      const capability = this._requests.shift();
12982      capability.resolve({
12983        value: chunk,
12984        done: false
12985      });
12986    } else {
12987      this._queuedChunks.push(chunk);
12988    }
12989    this._loaded += chunk.byteLength;
12990  }
12991  async read() {
12992    if (this._queuedChunks.length > 0) {
12993      const chunk = this._queuedChunks.shift();
12994      return {
12995        value: chunk,
12996        done: false
12997      };
12998    }
12999    if (this._done) {
13000      return {
13001        value: undefined,
13002        done: true
13003      };
13004    }
13005    const capability = Promise.withResolvers();
13006    this._requests.push(capability);
13007    return capability.promise;
13008  }
13009  cancel(reason) {
13010    this._done = true;
13011    for (const capability of this._requests) {
13012      capability.resolve({
13013        value: undefined,
13014        done: true
13015      });
13016    }
13017    this._requests.length = 0;
13018  }
13019  progressiveDone() {
13020    this._done ||= true;
13021  }
13022}
13023class PDFDataTransportStreamRangeReader extends BasePDFStreamRangeReader {
13024  onDone = null;
13025  _begin = -1;
13026  _done = false;
13027  _queuedChunk = null;
13028  _requests = [];
13029  constructor(stream, begin, end) {
13030    super(stream, begin, end);
13031    this._begin = begin;
13032  }
13033  _enqueue(chunk) {
13034    if (this._done) {
13035      return;
13036    }
13037    if (this._requests.length === 0) {
13038      this._queuedChunk = chunk;
13039    } else {
13040      const firstCapability = this._requests.shift();
13041      firstCapability.resolve({
13042        value: chunk,
13043        done: false
13044      });
13045      for (const capability of this._requests) {
13046        capability.resolve({
13047          value: undefined,
13048          done: true
13049        });
13050      }
13051      this._requests.length = 0;
13052    }
13053    this._done = true;
13054    this.onDone?.();
13055  }
13056  async read() {
13057    if (this._queuedChunk) {
13058      const chunk = this._queuedChunk;
13059      this._queuedChunk = null;
13060      return {
13061        value: chunk,
13062        done: false
13063      };
13064    }
13065    if (this._done) {
13066      return {
13067        value: undefined,
13068        done: true
13069      };
13070    }
13071    const capability = Promise.withResolvers();
13072    this._requests.push(capability);
13073    return capability.promise;
13074  }
13075  cancel(reason) {
13076    this._done = true;
13077    for (const capability of this._requests) {
13078      capability.resolve({
13079        value: undefined,
13080        done: true
13081      });
13082    }
13083    this._requests.length = 0;
13084    this.onDone?.();
13085  }
13086}
13087
13088;// ./src/display/content_disposition.js
13089
13090function getFilenameFromContentDispositionHeader(contentDisposition) {
13091  let needsEncodingFixup = true;
13092  let tmp = toParamRegExp("filename\\*", "i").exec(contentDisposition);
13093  if (tmp) {
13094    tmp = tmp[1];
13095    let filename = rfc2616unquote(tmp);
13096    filename = unescape(filename);
13097    filename = rfc5987decode(filename);
13098    filename = rfc2047decode(filename);
13099    return fixupEncoding(filename);
13100  }
13101  tmp = rfc2231getparam(contentDisposition);
13102  if (tmp) {
13103    const filename = rfc2047decode(tmp);
13104    return fixupEncoding(filename);
13105  }
13106  tmp = toParamRegExp("filename", "i").exec(contentDisposition);
13107  if (tmp) {
13108    tmp = tmp[1];
13109    let filename = rfc2616unquote(tmp);
13110    filename = rfc2047decode(filename);
13111    return fixupEncoding(filename);
13112  }
13113  function toParamRegExp(attributePattern, flags) {
13114    return new RegExp("(?:^|;)\\s*" + attributePattern + "\\s*=\\s*" + "(" + '[^";\\s][^;\\s]*' + "|" + '"(?:[^"\\\\]|\\\\"?)+"?' + ")", flags);
13115  }
13116  function textdecode(encoding, value) {
13117    if (encoding) {
13118      if (!/^[\x00-\xFF]+$/.test(value)) {
13119        return value;
13120      }
13121      try {
13122        const decoder = new TextDecoder(encoding, {
13123          fatal: true
13124        });
13125        const buffer = stringToBytes(value);
13126        value = decoder.decode(buffer);
13127        needsEncodingFixup = false;
13128      } catch {}
13129    }
13130    return value;
13131  }
13132  function fixupEncoding(value) {
13133    if (needsEncodingFixup && /[\x80-\xff]/.test(value)) {
13134      value = textdecode("utf-8", value);
13135      if (needsEncodingFixup) {
13136        value = textdecode("iso-8859-1", value);
13137      }
13138    }
13139    return value;
13140  }
13141  function rfc2231getparam(contentDispositionStr) {
13142    const matches = [];
13143    let match;
13144    const iter = toParamRegExp("filename\\*((?!0\\d)\\d+)(\\*?)", "ig");
13145    while ((match = iter.exec(contentDispositionStr)) !== null) {
13146      let [, n, quot, part] = match;
13147      n = parseInt(n, 10);
13148      if (n in matches) {
13149        if (n === 0) {
13150          break;
13151        }
13152        continue;
13153      }
13154      matches[n] = [quot, part];
13155    }
13156    const parts = [];
13157    for (let n = 0; n < matches.length; ++n) {
13158      if (!(n in matches)) {
13159        break;
13160      }
13161      let [quot, part] = matches[n];
13162      part = rfc2616unquote(part);
13163      if (quot) {
13164        part = unescape(part);
13165        if (n === 0) {
13166          part = rfc5987decode(part);
13167        }
13168      }
13169      parts.push(part);
13170    }
13171    return parts.join("");
13172  }
13173  function rfc2616unquote(value) {
13174    if (value.startsWith('"')) {
13175      const parts = value.slice(1).split('\\"');
13176      for (let i = 0; i < parts.length; ++i) {
13177        const quotindex = parts[i].indexOf('"');
13178        if (quotindex !== -1) {
13179          parts[i] = parts[i].slice(0, quotindex);
13180          parts.length = i + 1;
13181        }
13182        parts[i] = parts[i].replaceAll(/\\(.)/g, "$1");
13183      }
13184      value = parts.join('"');
13185    }
13186    return value;
13187  }
13188  function rfc5987decode(extvalue) {
13189    const encodingend = extvalue.indexOf("'");
13190    if (encodingend === -1) {
13191      return extvalue;
13192    }
13193    const encoding = extvalue.slice(0, encodingend);
13194    const langvalue = extvalue.slice(encodingend + 1);
13195    const value = langvalue.replace(/^[^']*'/, "");
13196    return textdecode(encoding, value);
13197  }
13198  function rfc2047decode(value) {
13199    if (!value.startsWith("=?") || /[\x00-\x19\x80-\xff]/.test(value)) {
13200      return value;
13201    }
13202    return value.replaceAll(/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g, function (matches, charset, encoding, text) {
13203      if (encoding === "q" || encoding === "Q") {
13204        text = text.replaceAll("_", " ");
13205        text = text.replaceAll(/=([0-9a-fA-F]{2})/g, function (match, hex) {
13206          return String.fromCharCode(parseInt(hex, 16));
13207        });
13208        return textdecode(charset, text);
13209      }
13210      try {
13211        text = atob(text);
13212      } catch {}
13213      return textdecode(charset, text);
13214    });
13215  }
13216  return "";
13217}
13218
13219;// ./src/display/network_utils.js
13220
13221
13222
13223function createHeaders(isHttp, httpHeaders) {
13224  const headers = new Headers();
13225  if (!isHttp || !httpHeaders || typeof httpHeaders !== "object") {
13226    return headers;
13227  }
13228  for (const key in httpHeaders) {
13229    const val = httpHeaders[key];
13230    if (val !== undefined) {
13231      headers.append(key, val);
13232    }
13233  }
13234  return headers;
13235}
13236function getResponseOrigin(url) {
13237  return URL.parse(url)?.origin ?? null;
13238}
13239function validateRangeRequestCapabilities({
13240  responseHeaders,
13241  isHttp,
13242  rangeChunkSize,
13243  disableRange
13244}) {
13245  const returnValues = {
13246    allowRangeRequests: false,
13247    suggestedLength: undefined
13248  };
13249  const length = parseInt(responseHeaders.get("Content-Length"), 10);
13250  if (!Number.isInteger(length)) {
13251    return returnValues;
13252  }
13253  returnValues.suggestedLength = length;
13254  if (length <= 2 * rangeChunkSize) {
13255    return returnValues;
13256  }
13257  if (disableRange || !isHttp) {
13258    return returnValues;
13259  }
13260  if (responseHeaders.get("Accept-Ranges") !== "bytes") {
13261    return returnValues;
13262  }
13263  const contentEncoding = responseHeaders.get("Content-Encoding") || "identity";
13264  if (contentEncoding !== "identity") {
13265    return returnValues;
13266  }
13267  returnValues.allowRangeRequests = true;
13268  return returnValues;
13269}
13270function extractFilenameFromHeader(responseHeaders) {
13271  const contentDisposition = responseHeaders.get("Content-Disposition");
13272  if (contentDisposition) {
13273    let filename = getFilenameFromContentDispositionHeader(contentDisposition);
13274    if (filename.includes("%")) {
13275      try {
13276        filename = decodeURIComponent(filename);
13277      } catch {}
13278    }
13279    if (isPdfFile(filename)) {
13280      return filename;
13281    }
13282  }
13283  return null;
13284}
13285function createResponseError(status, url) {
13286  return new ResponseException(`Unexpected server response (${status}) while retrieving PDF "${url}".`, status, status === 404 || status === 0 && url.startsWith("file:"));
13287}
13288function ensureResponseOrigin(rangeOrigin, origin) {
13289  if (rangeOrigin !== origin) {
13290    throw new Error(`Expected range response-origin "${rangeOrigin}" to match "${origin}".`);
13291  }
13292}
13293
13294;// ./src/display/fetch_stream.js
13295
13296
13297
13298function fetchUrl(url, headers, withCredentials, abortController) {
13299  return fetch(url, {
13300    method: "GET",
13301    headers,
13302    signal: abortController.signal,
13303    mode: "cors",
13304    credentials: withCredentials ? "include" : "same-origin",
13305    redirect: "follow"
13306  });
13307}
13308function ensureResponseStatus(status, url) {
13309  if (status !== 200 && status !== 206) {
13310    throw createResponseError(status, url);
13311  }
13312}
13313function fetch_stream_getArrayBuffer(val) {
13314  if (val instanceof Uint8Array) {
13315    return val.buffer;
13316  }
13317  if (val instanceof ArrayBuffer) {
13318    return val;
13319  }
13320  warn(`getArrayBuffer - unexpected data format: ${val}`);
13321  return new Uint8Array(val).buffer;
13322}
13323class PDFFetchStream extends BasePDFStream {
13324  _responseOrigin = null;
13325  constructor(source) {
13326    super(source, PDFFetchStreamReader, PDFFetchStreamRangeReader);
13327    this.isHttp = /^https?:/i.test(source.url);
13328    this.headers = createHeaders(this.isHttp, source.httpHeaders);
13329  }
13330}
13331class PDFFetchStreamReader extends BasePDFStreamReader {
13332  _abortController = new AbortController();
13333  _reader = null;
13334  constructor(stream) {
13335    super(stream);
13336    const {
13337      disableRange,
13338      disableStream,
13339      length,
13340      rangeChunkSize,
13341      url,
13342      withCredentials
13343    } = stream._source;
13344    this._contentLength = length;
13345    this._isStreamingSupported = !disableStream;
13346    this._isRangeSupported = !disableRange;
13347    const headers = new Headers(stream.headers);
13348    fetchUrl(url, headers, withCredentials, this._abortController).then(response => {
13349      stream._responseOrigin = getResponseOrigin(response.url);
13350      ensureResponseStatus(response.status, url);
13351      this._reader = response.body.getReader();
13352      const responseHeaders = response.headers;
13353      const {
13354        allowRangeRequests,
13355        suggestedLength
13356      } = validateRangeRequestCapabilities({
13357        responseHeaders,
13358        isHttp: stream.isHttp,
13359        rangeChunkSize,
13360        disableRange
13361      });
13362      this._isRangeSupported = allowRangeRequests;
13363      this._contentLength = suggestedLength || this._contentLength;
13364      this._filename = extractFilenameFromHeader(responseHeaders);
13365      if (!this._isStreamingSupported && this._isRangeSupported) {
13366        this.cancel(new AbortException("Streaming is disabled."));
13367      }
13368      this._headersCapability.resolve();
13369    }).catch(this._headersCapability.reject);
13370  }
13371  async read() {
13372    await this._headersCapability.promise;
13373    const {
13374      value,
13375      done
13376    } = await this._reader.read();
13377    if (done) {
13378      return {
13379        value,
13380        done
13381      };
13382    }
13383    this._loaded += value.byteLength;
13384    this.onProgress?.({
13385      loaded: this._loaded,
13386      total: this._contentLength
13387    });
13388    return {
13389      value: fetch_stream_getArrayBuffer(value),
13390      done: false
13391    };
13392  }
13393  cancel(reason) {
13394    this._reader?.cancel(reason);
13395    this._abortController.abort();
13396  }
13397}
13398class PDFFetchStreamRangeReader extends BasePDFStreamRangeReader {
13399  _abortController = new AbortController();
13400  _readCapability = Promise.withResolvers();
13401  _reader = null;
13402  constructor(stream, begin, end) {
13403    super(stream, begin, end);
13404    const {
13405      url,
13406      withCredentials
13407    } = stream._source;
13408    const headers = new Headers(stream.headers);
13409    headers.append("Range", `bytes=${begin}
13409-${end - 1}`);
13410    fetchUrl(url, headers, withCredentials, this._abortController).then(response => {
13411      const responseOrigin = getResponseOrigin(response.url);
13412      ensureResponseOrigin(responseOrigin, stream._responseOrigin);
13413      ensureResponseStatus(response.status, url);
13414      this._reader = response.body.getReader();
13415      this._readCapability.resolve();
13416    }).catch(this._readCapability.reject);
13417  }
13418  async read() {
13419    await this._readCapability.promise;
13420    const {
13421      value,
13422      done
13423    } = await this._reader.read();
13424    if (done) {
13425      return {
13426        value,
13427        done
13428      };
13429    }
13430    return {
13431      value: fetch_stream_getArrayBuffer(value),
13432      done: false
13433    };
13434  }
13435  cancel(reason) {
13436    this._reader?.cancel(reason);
13437    this._abortController.abort();
13438  }
13439}
13440
13441;// ./src/display/network.js
13442
13443
13444
13445const OK_RESPONSE = 200;
13446const PARTIAL_CONTENT_RESPONSE = 206;
13447function network_getArrayBuffer(val) {
13448  return typeof val !== "string" ? val : stringToBytes(val).buffer;
13449}
13450class PDFNetworkStream extends BasePDFStream {
13451  #pendingRequests = new WeakMap();
13452  _responseOrigin = null;
13453  constructor(source) {
13454    super(source, PDFNetworkStreamReader, PDFNetworkStreamRangeReader);
13455    this.url = source.url;
13456    this.isHttp = /^https?:/i.test(this.url);
13457    this.headers = createHeaders(this.isHttp, source.httpHeaders);
13458  }
13459  _request(args) {
13460    const xhr = new XMLHttpRequest();
13461    const pendingRequest = {
13462      validateStatus: null,
13463      onHeadersReceived: args.onHeadersReceived,
13464      onDone: args.onDone,
13465      onError: args.onError,
13466      onProgress: args.onProgress
13467    };
13468    this.#pendingRequests.set(xhr, pendingRequest);
13469    xhr.open("GET", this.url);
13470    xhr.withCredentials = this._source.withCredentials;
13471    for (const [key, val] of this.headers) {
13472      xhr.setRequestHeader(key, val);
13473    }
13474    if (this.isHttp && "begin" in args && "end" in args) {
13475      xhr.setRequestHeader("Range", `bytes=${args.begin}-${args.end - 1}`);
13476      pendingRequest.validateStatus = status => status === PARTIAL_CONTENT_RESPONSE || status === OK_RESPONSE;
13477    } else {
13478      pendingRequest.validateStatus = status => status === OK_RESPONSE;
13479    }
13480    xhr.responseType = "arraybuffer";
13481    assert(args.onError, "Expected `onError` callback to be provided.");
13482    xhr.onerror = () => args.onError(xhr.status);
13483    xhr.onreadystatechange = this.#onStateChange.bind(this, xhr);
13484    xhr.onprogress = this.#onProgress.bind(this, xhr);
13485    xhr.send(null);
13486    return xhr;
13487  }
13488  #onProgress(xhr, evt) {
13489    const pendingRequest = this.#pendingRequests.get(xhr);
13490    pendingRequest?.onProgress?.(evt);
13491  }
13492  #onStateChange(xhr, evt) {
13493    const pendingRequest = this.#pendingRequests.get(xhr);
13494    if (!pendingRequest) {
13495      return;
13496    }
13497    if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
13498      pendingRequest.onHeadersReceived();
13499      delete pendingRequest.onHeadersReceived;
13500    }
13501    if (xhr.readyState !== 4) {
13502      return;
13503    }
13504    if (!this.#pendingRequests.has(xhr)) {
13505      return;
13506    }
13507    this.#pendingRequests.delete(xhr);
13508    if (xhr.status === 0 && this.isHttp) {
13509      pendingRequest.onError(xhr.status);
13510      return;
13511    }
13512    const xhrStatus = xhr.status || OK_RESPONSE;
13513    if (!pendingRequest.validateStatus(xhrStatus)) {
13514      pendingRequest.onError(xhr.status);
13515      return;
13516    }
13517    const chunk = network_getArrayBuffer(xhr.response);
13518    if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
13519      const rangeHeader = xhr.getResponseHeader("Content-Range");
13520      if (/bytes (\d+)-(\d+)\/(\d+)/.test(rangeHeader)) {
13521        pendingRequest.onDone(chunk);
13522      } else {
13523        warn(`Missing or invalid "Content-Range" header.`);
13524        pendingRequest.onError(0);
13525      }
13526    } else if (chunk) {
13527      pendingRequest.onDone(chunk);
13528    } else {
13529      pendingRequest.onError(xhr.status);
13530    }
13531  }
13532  _abortRequest(xhr) {
13533    if (this.#pendingRequests.has(xhr)) {
13534      this.#pendingRequests.delete(xhr);
13535      xhr.abort();
13536    }
13537  }
13538  getRangeReader(begin, end) {
13539    const reader = super.getRangeReader(begin, end);
13540    if (reader) {
13541      reader.onClosed = () => this._rangeReaders.delete(reader);
13542    }
13543    return reader;
13544  }
13545}
13546class PDFNetworkStreamReader extends BasePDFStreamReader {
13547  _cachedChunks = [];
13548  _done = false;
vendor: 5,466 bytes, lines 13549-13753
13549  _requests = [];
13550  _storedError = null;
13551  constructor(stream) {
13552    super(stream);
13553    const {
13554      length
13555    } = stream._source;
13556    this._contentLength = length;
13557    this._fullRequestXhr = stream._request({
13558      onHeadersReceived: this.#onHeadersReceived.bind(this),
13559      onDone: this.#onDone.bind(this),
13560      onError: this.#onError.bind(this),
13561      onProgress: this.#onProgress.bind(this)
13562    });
13563  }
13564  #onHeadersReceived() {
13565    const stream = this._stream;
13566    const {
13567      disableRange,
13568      rangeChunkSize
13569    } = stream._source;
13570    const fullRequestXhr = this._fullRequestXhr;
13571    stream._responseOrigin = getResponseOrigin(fullRequestXhr.responseURL);
13572    const rawResponseHeaders = fullRequestXhr.getAllResponseHeaders();
13573    const responseHeaders = new Headers(rawResponseHeaders ? rawResponseHeaders.trimStart().replace(/[^\S ]+$/, "").split(/[\r\n]+/).map(x => {
13574      const [key, ...val] = x.split(": ");
13575      return [key, val.join(": ")];
13576    }) : []);
13577    const {
13578      allowRangeRequests,
13579      suggestedLength
13580    } = validateRangeRequestCapabilities({
13581      responseHeaders,
13582      isHttp: stream.isHttp,
13583      rangeChunkSize,
13584      disableRange
13585    });
13586    if (allowRangeRequests) {
13587      this._isRangeSupported = true;
13588    }
13589    this._contentLength = suggestedLength || this._contentLength;
13590    this._filename = extractFilenameFromHeader(responseHeaders);
13591    if (this._isRangeSupported) {
13592      stream._abortRequest(fullRequestXhr);
13593    }
13594    this._headersCapability.resolve();
13595  }
13596  #onDone(chunk) {
13597    if (this._requests.length > 0) {
13598      const capability = this._requests.shift();
13599      capability.resolve({
13600        value: chunk,
13601        done: false
13602      });
13603    } else {
13604      this._cachedChunks.push(chunk);
13605    }
13606    this._done = true;
13607    if (this._cachedChunks.length > 0) {
13608      return;
13609    }
13610    for (const capability of this._requests) {
13611      capability.resolve({
13612        value: undefined,
13613        done: true
13614      });
13615    }
13616    this._requests.length = 0;
13617  }
13618  #onError(status) {
13619    this._storedError = createResponseError(status, this._stream.url);
13620    this._headersCapability.reject(this._storedError);
13621    for (const capability of this._requests) {
13622      capability.reject(this._storedError);
13623    }
13624    this._requests.length = 0;
13625    this._cachedChunks.length = 0;
13626  }
13627  #onProgress(evt) {
13628    this.onProgress?.({
13629      loaded: evt.loaded,
13630      total: evt.lengthComputable ? evt.total : this._contentLength
13631    });
13632  }
13633  async read() {
13634    await this._headersCapability.promise;
13635    if (this._storedError) {
13636      throw this._storedError;
13637    }
13638    if (this._cachedChunks.length > 0) {
13639      const chunk = this._cachedChunks.shift();
13640      return {
13641        value: chunk,
13642        done: false
13643      };
13644    }
13645    if (this._done) {
13646      return {
13647        value: undefined,
13648        done: true
13649      };
13650    }
13651    const capability = Promise.withResolvers();
13652    this._requests.push(capability);
13653    return capability.promise;
13654  }
13655  cancel(reason) {
13656    this._done = true;
13657    this._headersCapability.reject(reason);
13658    for (const capability of this._requests) {
13659      capability.resolve({
13660        value: undefined,
13661        done: true
13662      });
13663    }
13664    this._requests.length = 0;
13665    this._stream._abortRequest(this._fullRequestXhr);
13666    this._fullRequestXhr = null;
13667  }
13668}
13669class PDFNetworkStreamRangeReader extends BasePDFStreamRangeReader {
13670  onClosed = null;
13671  _done = false;
13672  _queuedChunk = null;
13673  _requests = [];
13674  _storedError = null;
13675  constructor(stream, begin, end) {
13676    super(stream, begin, end);
13677    this._requestXhr = stream._request({
13678      begin,
13679      end,
13680      onHeadersReceived: this.#onHeadersReceived.bind(this),
13681      onDone: this.#onDone.bind(this),
13682      onError: this.#onError.bind(this),
13683      onProgress: null
13684    });
13685  }
13686  #onHeadersReceived() {
13687    const responseOrigin = getResponseOrigin(this._requestXhr?.responseURL);
13688    try {
13689      ensureResponseOrigin(responseOrigin, this._stream._responseOrigin);
13690    } catch (ex) {
13691      this._storedError = ex;
13692      this.#onError(0);
13693    }
13694  }
13695  #onDone(chunk) {
13696    if (this._requests.length > 0) {
13697      const capability = this._requests.shift();
13698      capability.resolve({
13699        value: chunk,
13700        done: false
13701      });
13702    } else {
13703      this._queuedChunk = chunk;
13704    }
13705    this._done = true;
13706    for (const capability of this._requests) {
13707      capability.resolve({
13708        value: undefined,
13709        done: true
13710      });
13711    }
13712    this._requests.length = 0;
13713    this.onClosed?.();
13714  }
13715  #onError(status) {
13716    this._storedError ??= createResponseError(status, this._stream.url);
13717    for (const capability of this._requests) {
13718      capability.reject(this._storedError);
13719    }
13720    this._requests.length = 0;
13721    this._queuedChunk = null;
13722  }
13723  async read() {
13724    if (this._storedError) {
13725      throw this._storedError;
13726    }
13727    if (this._queuedChunk !== null) {
13728      const chunk = this._queuedChunk;
13729      this._queuedChunk = null;
13730      return {
13731        value: chunk,
13732        done: false
13733      };
13734    }
13735    if (this._done) {
13736      return {
13737        value: undefined,
13738        done: true
13739      };
13740    }
13741    const capability = Promise.withResolvers();
13742    this._requests.push(capability);
13743    return capability.promise;
13744  }
13745  cancel(reason) {
13746    this._done = true;
13747    for (const capability of this._requests) {
13748      capability.resolve({
13749        value: undefined,
13750        done: true
13751      });
13752    }
13753    this._requests.length = 0;
13754    this._stream._abortRequest(this._requestXhr);
13755    this.onClosed?.();
13756  }
13757}
13758
13759;// ./src/display/node_stream.js
13760
13761
13762
13763const urlRegex = /^[a-z][a-z0-9\-+.]+:/i;
13764function parseUrlOrPath(sourceUrl) {
13765  if (urlRegex.test(sourceUrl)) {
13766    return new URL(sourceUrl);
13767  }
13768  const url = process.getBuiltinModule("url");
13769  return new URL(url.pathToFileURL(sourceUrl));
13770}
13771function getReadableStream(readStream) {
13772  const {
13773    Readable
13774  } = process.getBuiltinModule("stream");
13775  if (typeof Readable.toWeb === "function") {
13776    return Readable.toWeb(readStream);
13777  }
13778  const require = process.getBuiltinModule("module").createRequire(import.meta.url);
13779  const polyfill = require("node-readable-to-web-readable-stream");
13780  return polyfill.makeDefaultReadableStreamFromNodeReadable(readStream);
13781}
13782function node_stream_getArrayBuffer(val) {
13783  if (val instanceof Uint8Array) {
13784    return val.buffer;
13785  }
13786  if (val instanceof ArrayBuffer) {
13787    return val;
13788  }
13789  warn(`getArrayBuffer - unexpected data format: ${val}`);
13790  return new Uint8Array(val).buffer;
13791}
13792class PDFNodeStream extends BasePDFStream {
13793  constructor(source) {
13794    super(source, PDFNodeStreamReader, PDFNodeStreamRangeReader);
13795    this.url = parseUrlOrPath(source.url);
13796    assert(this.url.protocol === "file:", "PDFNodeStream only supports file:// URLs.");
13797  }
13798}
13799class PDFNodeStreamReader extends BasePDFStreamReader {
13800  _reader = null;
13801  constructor(stream) {
13802    super(stream);
13803    const {
13804      disableRange,
13805      disableStream,
13806      length,
13807      rangeChunkSize
13808    } = stream._source;
13809    this._contentLength = length;
13810    this._isStreamingSupported = !disableStream;
13811    this._isRangeSupported = !disableRange;
13812    const url = stream.url;
13813    const fs = process.getBuiltinModule("fs");
13814    fs.promises.lstat(url).then(stat => {
13815      const readStream = fs.createReadStream(url);
13816      const readableStream = getReadableStream(readStream);
13817      this._reader = readableStream.getReader();
13818      const {
13819        size
13820      } = stat;
13821      if (size <= 2 * rangeChunkSize) {
13822        this._isRangeSupported = false;
13823      }
13824      this._contentLength = size;
13825      if (!this._isStreamingSupported && this._isRangeSupported) {
13826        this.cancel(new AbortException("Streaming is disabled."));
13827      }
13828      this._headersCapability.resolve();
13829    }).catch(error => {
13830      if (error.code === "ENOENT") {
13831        error = createResponseError(0, url.href);
13832      }
13833      this._headersCapability.reject(error);
13834    });
13835  }
13836  async read() {
13837    await this._headersCapability.promise;
13838    const {
13839      value,
13840      done
13841    } = await this._reader.read();
13842    if (done) {
13843      return {
13844        value,
13845        done
13846      };
13847    }
13848    this._loaded += value.length;
13849    this.onProgress?.({
13850      loaded: this._loaded,
13851      total: this._contentLength
13852    });
13853    return {
13854      value: node_stream_getArrayBuffer(value),
13855      done: false
13856    };
13857  }
13858  cancel(reason) {
13859    this._reader?.cancel(reason);
13860  }
13861}
13862class PDFNodeStreamRangeReader extends BasePDFStreamRangeReader {
13863  _readCapability = Promise.withResolvers();
13864  _reader = null;
13865  constructor(stream, begin, end) {
13866    super(stream, begin, end);
13867    const url = stream.url;
13868    const fs = process.getBuiltinModule("fs");
13869    try {
13870      const readStream = fs.createReadStream(url, {
13871        start: begin,
13872        end: end - 1
13873      });
13874      const readableStream = getReadableStream(readStream);
13875      this._reader = readableStream.getReader();
13876      this._readCapability.resolve();
13877    } catch (error) {
13878      this._readCapability.reject(error);
13879    }
13880  }
13881  async read() {
13882    await this._readCapability.promise;
13883    const {
13884      value,
13885      done
13886    } = await this._reader.read();
13887    if (done) {
13888      return {
13889        value,
13890        done
13891      };
13892    }
13893    return {
13894      value: node_stream_getArrayBuffer(value),
13895      done: false
13896    };
13897  }
13898  cancel(reason) {
13899    this._reader?.cancel(reason);
13900  }
13901}
13902
13903;// ./src/display/pdf_objects.js
13904const INITIAL_DATA = Symbol("INITIAL_DATA");
13905class PDFObjects {
13906  #objs = Object.create(null);
13907  #ensureObj(objId) {
13908    return this.#objs[objId] ||= {
13909      ...Promise.withResolvers(),
13910      data: INITIAL_DATA
13911    };
13912  }
13913  get(objId, callback = null) {
13914    if (callback) {
13915      const obj = this.#ensureObj(objId);
13916      obj.promise.then(() => callback(obj.data));
13917      return null;
13918    }
13919    const obj = this.#objs[objId];
13920    if (!obj || obj.data === INITIAL_DATA) {
13921      throw new Error(`Requesting object that isn't resolved yet ${objId}.`);
13922    }
13923    return obj.data;
13924  }
vendor: 5,997 bytes, lines 13925-14134
13925  has(objId) {
13926    const obj = this.#objs[objId];
13927    return !!obj && obj.data !== INITIAL_DATA;
13928  }
13929  delete(objId) {
13930    const obj = this.#objs[objId];
13931    if (!obj || obj.data === INITIAL_DATA) {
13932      return false;
13933    }
13934    delete this.#objs[objId];
13935    return true;
13936  }
13937  resolve(objId, data = null) {
13938    const obj = this.#ensureObj(objId);
13939    obj.data = data;
13940    obj.resolve();
13941  }
13942  clear() {
13943    for (const objId in this.#objs) {
13944      const {
13945        data
13946      } = this.#objs[objId];
13947      data?.bitmap?.close();
13948    }
13949    this.#objs = Object.create(null);
13950  }
13951  *[Symbol.iterator]() {
13952    for (const objId in this.#objs) {
13953      const {
13954        data
13955      } = this.#objs[objId];
13956      if (data === INITIAL_DATA) {
13957        continue;
13958      }
13959      yield [objId, data];
13960    }
13961  }
13962}
13963
13964;// ./src/display/text_layer.js
13965
13966
13967const MAX_TEXT_DIVS_TO_RENDER = 100000;
13968const DEFAULT_FONT_SIZE = 30;
13969class TextLayer {
13970  #capability = Promise.withResolvers();
13971  #container = null;
13972  #disableProcessItems = false;
13973  #fontInspectorEnabled = !!globalThis.FontInspector?.enabled;
13974  #lang = null;
13975  #layoutTextParams = null;
13976  #pageHeight = 0;
13977  #pageWidth = 0;
13978  #reader = null;
13979  #rootContainer = null;
13980  #rotation = 0;
13981  #scale = 0;
13982  #styleCache = Object.create(null);
13983  #textContentItemsStr = [];
13984  #textContentSource = null;
13985  #textDivs = [];
13986  #textDivProperties = new WeakMap();
13987  #transform = null;
13988  static #ascentCache = new Map();
13989  static #canvasContexts = new Map();
13990  static #canvasCtxFonts = new WeakMap();
13991  static #minFontSize = null;
13992  static #pendingTextLayers = new Set();
13993  constructor({
13994    textContentSource,
13995    container,
13996    viewport
13997  }) {
13998    if (textContentSource instanceof ReadableStream) {
13999      this.#textContentSource = textContentSource;
14000    } else if (typeof textContentSource === "object") {
14001      this.#textContentSource = new ReadableStream({
14002        start(controller) {
14003          controller.enqueue(textContentSource);
14004          controller.close();
14005        }
14006      });
14007    } else {
14008      throw new Error('No "textContentSource" parameter specified.');
14009    }
14010    this.#container = this.#rootContainer = container;
14011    this.#scale = viewport.scale * OutputScale.pixelRatio;
14012    this.#rotation = viewport.rotation;
14013    this.#layoutTextParams = {
14014      div: null,
14015      properties: null,
14016      ctx: null
14017    };
14018    const {
14019      pageWidth,
14020      pageHeight,
14021      pageX,
14022      pageY
14023    } = viewport.rawDims;
14024    this.#transform = [1, 0, 0, -1, -pageX, pageY + pageHeight];
14025    this.#pageWidth = pageWidth;
14026    this.#pageHeight = pageHeight;
14027    TextLayer.#ensureMinFontSizeComputed();
14028    container.style.setProperty("--min-font-size", TextLayer.#minFontSize);
14029    setLayerDimensions(container, viewport);
14030    this.#capability.promise.finally(() => {
14031      TextLayer.#pendingTextLayers.delete(this);
14032      this.#layoutTextParams = null;
14033      this.#styleCache = null;
14034    }).catch(() => {});
14035  }
14036  static get fontFamilyMap() {
14037    const {
14038      isWindows,
14039      isFirefox
14040    } = util_FeatureTest.platform;
14041    return shadow(this, "fontFamilyMap", new Map([["sans-serif", `${isWindows && isFirefox ? "Calibri, " : ""}sans-serif`], ["monospace", `${isWindows && isFirefox ? "Lucida Console, " : ""}monospace`]]));
14042  }
14043  render() {
14044    const pump = () => {
14045      this.#reader.read().then(({
14046        value,
14047        done
14048      }) => {
14049        if (done) {
14050          this.#capability.resolve();
14051          return;
14052        }
14053        this.#lang ??= value.lang;
14054        Object.assign(this.#styleCache, value.styles);
14055        this.#processItems(value.items);
14056        pump();
14057      }, this.#capability.reject);
14058    };
14059    this.#reader = this.#textContentSource.getReader();
14060    TextLayer.#pendingTextLayers.add(this);
14061    pump();
14062    return this.#capability.promise;
14063  }
14064  update({
14065    viewport,
14066    onBefore = null
14067  }) {
14068    const scale = viewport.scale * OutputScale.pixelRatio;
14069    const rotation = viewport.rotation;
14070    if (rotation !== this.#rotation) {
14071      onBefore?.();
14072      this.#rotation = rotation;
14073      setLayerDimensions(this.#rootContainer, {
14074        rotation
14075      });
14076    }
14077    if (scale !== this.#scale) {
14078      onBefore?.();
14079      this.#scale = scale;
14080      const params = {
14081        div: null,
14082        properties: null,
14083        ctx: TextLayer.#getCtx(this.#lang)
14084      };
14085      for (const div of this.#textDivs) {
14086        params.properties = this.#textDivProperties.get(div);
14087        params.div = div;
14088        this.#layout(params);
14089      }
14090    }
14091  }
14092  cancel() {
14093    const abortEx = new AbortException("TextLayer task cancelled.");
14094    this.#reader?.cancel(abortEx).catch(() => {});
14095    this.#reader = null;
14096    this.#capability.reject(abortEx);
14097  }
14098  get textDivs() {
14099    return this.#textDivs;
14100  }
14101  get textContentItemsStr() {
14102    return this.#textContentItemsStr;
14103  }
14104  #processItems(items) {
14105    if (this.#disableProcessItems) {
14106      return;
14107    }
14108    this.#layoutTextParams.ctx ??= TextLayer.#getCtx(this.#lang);
14109    const textDivs = this.#textDivs,
14110      textContentItemsStr = this.#textContentItemsStr;
14111    for (const item of items) {
14112      if (textDivs.length > MAX_TEXT_DIVS_TO_RENDER) {
14113        warn("Ignoring additional textDivs for performance reasons.");
14114        this.#disableProcessItems = true;
14115        return;
14116      }
14117      if (item.str === undefined) {
14118        if (item.type === "beginMarkedContentProps" || item.type === "beginMarkedContent") {
14119          const parent = this.#container;
14120          this.#container = document.createElement("span");
14121          this.#container.classList.add("markedContent");
14122          if (item.id) {
14123            this.#container.setAttribute("id", `${item.id}`);
14124          }
14125          if (item.tag === "Artifact") {
14126            this.#container.ariaHidden = true;
14127          }
14128          parent.append(this.#container);
14129        } else if (item.type === "endMarkedContent") {
14130          this.#container = this.#container.parentNode;
14131        }
14132        continue;
14133      }
14134      textContentItemsStr.push(item.str);
vendor: 5,703 bytes, lines 14135-14311
14135      this.#appendText(item);
14136    }
14137  }
14138  #appendText(geom) {
14139    const textDiv = document.createElement("span");
14140    const textDivProperties = {
14141      angle: 0,
14142      canvasWidth: 0,
14143      hasText: geom.str !== "",
14144      hasEOL: geom.hasEOL,
14145      fontSize: 0
14146    };
14147    this.#textDivs.push(textDiv);
14148    const tx = Util.transform(this.#transform, geom.transform);
14149    let angle = Math.atan2(tx[1], tx[0]);
14150    const style = this.#styleCache[geom.fontName];
14151    if (style.vertical) {
14152      angle += Math.PI / 2;
14153    }
14154    let fontFamily = this.#fontInspectorEnabled && style.fontSubstitution || style.fontFamily;
14155    fontFamily = TextLayer.fontFamilyMap.get(fontFamily) || fontFamily;
14156    const fontHeight = Math.hypot(tx[2], tx[3]);
14157    const fontAscent = fontHeight * TextLayer.#getAscent(fontFamily, style, this.#lang);
14158    let left, top;
14159    if (angle === 0) {
14160      left = tx[4];
14161      top = tx[5] - fontAscent;
14162    } else {
14163      left = tx[4] + fontAscent * Math.sin(angle);
14164      top = tx[5] - fontAscent * Math.cos(angle);
14165    }
14166    const divStyle = textDiv.style;
14167    divStyle.left = `${(100 * left / this.#pageWidth).toFixed(2)}%`;
14168    divStyle.top = `${(100 * top / this.#pageHeight).toFixed(2)}%`;
14169    divStyle.setProperty("--font-height", `${fontHeight.toFixed(2)}px`);
14170    divStyle.fontFamily = fontFamily;
14171    textDivProperties.fontSize = fontHeight;
14172    textDiv.setAttribute("role", "presentation");
14173    textDiv.textContent = geom.str;
14174    textDiv.dir = geom.dir;
14175    if (this.#fontInspectorEnabled) {
14176      textDiv.dataset.fontName = style.fontSubstitutionLoadedName || geom.fontName;
14177    }
14178    if (angle !== 0) {
14179      textDivProperties.angle = angle * (180 / Math.PI);
14180    }
14181    let shouldScaleText = false;
14182    if (geom.str.length > 1) {
14183      shouldScaleText = true;
14184    } else if (geom.str !== " " && geom.transform[0] !== geom.transform[3]) {
14185      const absScaleX = Math.abs(geom.transform[0]),
14186        absScaleY = Math.abs(geom.transform[3]);
14187      if (absScaleX !== absScaleY && Math.max(absScaleX, absScaleY) / Math.min(absScaleX, absScaleY) > 1.5) {
14188        shouldScaleText = true;
14189      }
14190    }
14191    if (shouldScaleText) {
14192      textDivProperties.canvasWidth = style.vertical ? geom.height : geom.width;
14193    }
14194    this.#textDivProperties.set(textDiv, textDivProperties);
14195    this.#layoutTextParams.div = textDiv;
14196    this.#layoutTextParams.properties = textDivProperties;
14197    this.#layout(this.#layoutTextParams);
14198    if (textDivProperties.hasText) {
14199      this.#container.append(textDiv);
14200    }
14201    if (textDivProperties.hasEOL) {
14202      const br = document.createElement("br");
14203      br.setAttribute("role", "presentation");
14204      this.#container.append(br);
14205    }
14206  }
14207  #layout(params) {
14208    const {
14209      div,
14210      properties,
14211      ctx
14212    } = params;
14213    const {
14214      style
14215    } = div;
14216    if (properties.canvasWidth !== 0 && properties.hasText) {
14217      const {
14218        fontFamily
14219      } = style;
14220      const {
14221        canvasWidth,
14222        fontSize
14223      } = properties;
14224      TextLayer.#ensureCtxFont(ctx, fontSize * this.#scale, fontFamily);
14225      const {
14226        width
14227      } = ctx.measureText(div.textContent);
14228      if (width > 0) {
14229        style.setProperty("--scale-x", canvasWidth * this.#scale / width);
14230      }
14231    }
14232    if (properties.angle !== 0) {
14233      style.setProperty("--rotate", `${properties.angle}deg`);
14234    }
14235  }
14236  static cleanup() {
14237    if (this.#pendingTextLayers.size > 0) {
14238      return;
14239    }
14240    this.#ascentCache.clear();
14241    for (const {
14242      canvas
14243    } of this.#canvasContexts.values()) {
14244      canvas.remove();
14245    }
14246    this.#canvasContexts.clear();
14247  }
14248  static #getCtx(lang = null) {
14249    let ctx = this.#canvasContexts.get(lang ||= "");
14250    if (!ctx) {
14251      const canvas = document.createElement("canvas");
14252      canvas.className = "hiddenCanvasElement";
14253      canvas.lang = lang;
14254      document.body.append(canvas);
14255      ctx = canvas.getContext("2d", {
14256        alpha: false,
14257        willReadFrequently: true
14258      });
14259      this.#canvasContexts.set(lang, ctx);
14260      this.#canvasCtxFonts.set(ctx, {
14261        size: 0,
14262        family: ""
14263      });
14264    }
14265    return ctx;
14266  }
14267  static #ensureCtxFont(ctx, size, family) {
14268    const cached = this.#canvasCtxFonts.get(ctx);
14269    if (size === cached.size && family === cached.family) {
14270      return;
14271    }
14272    ctx.font = `${size}px ${family}`;
14273    cached.size = size;
14274    cached.family = family;
14275  }
14276  static #ensureMinFontSizeComputed() {
14277    if (this.#minFontSize !== null) {
14278      return;
14279    }
14280    const div = document.createElement("div");
14281    div.style.opacity = 0;
14282    div.style.lineHeight = 1;
14283    div.style.fontSize = "1px";
14284    div.style.position = "absolute";
14285    div.textContent = "X";
14286    document.body.append(div);
14287    this.#minFontSize = div.getBoundingClientRect().height;
14288    div.remove();
14289  }
14290  static #getAscent(fontFamily, style, lang) {
14291    const cachedAscent = this.#ascentCache.get(fontFamily);
14292    if (cachedAscent) {
14293      return cachedAscent;
14294    }
14295    const ctx = this.#getCtx(lang);
14296    ctx.canvas.width = ctx.canvas.height = DEFAULT_FONT_SIZE;
14297    this.#ensureCtxFont(ctx, DEFAULT_FONT_SIZE, fontFamily);
14298    const metrics = ctx.measureText("");
14299    const ascent = metrics.fontBoundingBoxAscent;
14300    const descent = Math.abs(metrics.fontBoundingBoxDescent);
14301    ctx.canvas.width = ctx.canvas.height = 0;
14302    let ratio = 0.8;
14303    if (ascent) {
14304      ratio = ascent / (ascent + descent);
14305    } else {
14306      if (util_FeatureTest.platform.isFirefox) {
14307        warn("Enable the `dom.textMetrics.fontBoundingBox.enabled` preference " + "in `about:config` to improve TextLayer rendering.");
14308      }
14309      if (style.ascent) {
14310        ratio = style.ascent;
14311      }
vendor: 22,013 bytes, lines 14311-15031
14311 else if (style.descent) {
14312        ratio = 1 + style.descent;
14313      }
14314    }
14315    this.#ascentCache.set(fontFamily, ratio);
14316    return ratio;
14317  }
14318}
14319
14320;// ./src/display/api.js
14321
14322
14323
14324
14325
14326
14327
14328
14329
14330
14331
14332
14333
14334
14335
14336
14337
14338
14339
14340
14341
14342
14343
14344
14345
14346const RENDERING_CANCELLED_TIMEOUT = 100;
14347function getDocument(src = {}) {
14348  if (typeof src === "string" || src instanceof URL) {
14349    src = {
14350      url: src
14351    };
14352  } else if (src instanceof ArrayBuffer || ArrayBuffer.isView(src)) {
14353    src = {
14354      data: src
14355    };
14356  }
14357  const task = new PDFDocumentLoadingTask();
14358  const {
14359    docId
14360  } = task;
14361  const url = src.url ? getUrlProp(src.url) : null;
14362  const data = src.data ? getDataProp(src.data) : null;
14363  const httpHeaders = src.httpHeaders || null;
14364  const withCredentials = src.withCredentials === true;
14365  const password = src.password ?? null;
14366  const rangeTransport = src.range instanceof PDFDataRangeTransport ? src.range : null;
14367  const rangeChunkSize = Number.isInteger(src.rangeChunkSize) && src.rangeChunkSize > 0 ? src.rangeChunkSize : 2 ** 16;
14368  let worker = src.worker instanceof PDFWorker ? src.worker : null;
14369  const verbosity = src.verbosity;
14370  const docBaseUrl = typeof src.docBaseUrl === "string" && !isDataScheme(src.docBaseUrl) ? src.docBaseUrl : null;
14371  const cMapUrl = getFactoryUrlProp(src.cMapUrl);
14372  const cMapPacked = src.cMapPacked !== false;
14373  const CMapReaderFactory = src.CMapReaderFactory || (isNodeJS ? NodeCMapReaderFactory : DOMCMapReaderFactory);
14374  const iccUrl = getFactoryUrlProp(src.iccUrl);
14375  const standardFontDataUrl = getFactoryUrlProp(src.standardFontDataUrl);
14376  const StandardFontDataFactory = src.StandardFontDataFactory || (isNodeJS ? NodeStandardFontDataFactory : DOMStandardFontDataFactory);
14377  const wasmUrl = getFactoryUrlProp(src.wasmUrl);
14378  const WasmFactory = src.WasmFactory || (isNodeJS ? NodeWasmFactory : DOMWasmFactory);
14379  const ignoreErrors = src.stopAtErrors !== true;
14380  const maxImageSize = Number.isInteger(src.maxImageSize) && src.maxImageSize > -1 ? src.maxImageSize : -1;
14381  const isEvalSupported = src.isEvalSupported !== false;
14382  const isOffscreenCanvasSupported = typeof src.isOffscreenCanvasSupported === "boolean" ? src.isOffscreenCanvasSupported : !isNodeJS;
14383  const isImageDecoderSupported = typeof src.isImageDecoderSupported === "boolean" ? src.isImageDecoderSupported : !isNodeJS && (util_FeatureTest.platform.isFirefox || !globalThis.chrome);
14384  const canvasMaxAreaInBytes = Number.isInteger(src.canvasMaxAreaInBytes) ? src.canvasMaxAreaInBytes : -1;
14385  const disableFontFace = typeof src.disableFontFace === "boolean" ? src.disableFontFace : isNodeJS;
14386  const fontExtraProperties = src.fontExtraProperties === true;
14387  const enableXfa = src.enableXfa === true;
14388  const ownerDocument = src.ownerDocument || globalThis.document;
14389  const disableRange = src.disableRange === true;
14390  const disableStream = src.disableStream === true;
14391  const disableAutoFetch = src.disableAutoFetch === true;
14392  const pdfBug = src.pdfBug === true;
14393  const CanvasFactory = src.CanvasFactory || (isNodeJS ? NodeCanvasFactory : DOMCanvasFactory);
14394  const FilterFactory = src.FilterFactory || (isNodeJS ? NodeFilterFactory : DOMFilterFactory);
14395  const enableHWA = src.enableHWA === true;
14396  const useWasm = src.useWasm !== false;
14397  const length = rangeTransport ? rangeTransport.length : src.length ?? NaN;
14398  const useSystemFonts = typeof src.useSystemFonts === "boolean" ? src.useSystemFonts : !isNodeJS && !disableFontFace;
14399  const useWorkerFetch = typeof src.useWorkerFetch === "boolean" ? src.useWorkerFetch : !!(CMapReaderFactory === DOMCMapReaderFactory && StandardFontDataFactory === DOMStandardFontDataFactory && WasmFactory === DOMWasmFactory && cMapUrl && standardFontDataUrl && wasmUrl && isValidFetchUrl(cMapUrl, document.baseURI) && isValidFetchUrl(standardFontDataUrl, document.baseURI) && isValidFetchUrl(wasmUrl, document.baseURI));
14400  const styleElement = null;
14401  setVerbosityLevel(verbosity);
14402  const transportFactory = {
14403    canvasFactory: new CanvasFactory({
14404      ownerDocument,
14405      enableHWA
14406    }),
14407    filterFactory: new FilterFactory({
14408      docId,
14409      ownerDocument
14410    }),
14411    cMapReaderFactory: useWorkerFetch ? null : new CMapReaderFactory({
14412      baseUrl: cMapUrl,
14413      isCompressed: cMapPacked
14414    }),
14415    standardFontDataFactory: useWorkerFetch ? null : new StandardFontDataFactory({
14416      baseUrl: standardFontDataUrl
14417    }),
14418    wasmFactory: useWorkerFetch ? null : new WasmFactory({
14419      baseUrl: wasmUrl
14420    })
14421  };
14422  if (!worker) {
14423    worker = PDFWorker.create({
14424      verbosity,
14425      port: GlobalWorkerOptions.workerPort
14426    });
14427    task._worker = worker;
14428  }
14429  const docParams = {
14430    docId,
14431    apiVersion: "5.4.624",
14432    data,
14433    password,
14434    disableAutoFetch,
14435    rangeChunkSize,
14436    length,
14437    docBaseUrl,
14438    enableXfa,
14439    evaluatorOptions: {
14440      maxImageSize,
14441      disableFontFace,
14442      ignoreErrors,
14443      isEvalSupported,
14444      isOffscreenCanvasSupported,
14445      isImageDecoderSupported,
14446      canvasMaxAreaInBytes,
14447      fontExtraProperties,
14448      useSystemFonts,
14449      useWasm,
14450      useWorkerFetch,
14451      cMapUrl,
14452      iccUrl,
14453      standardFontDataUrl,
14454      wasmUrl
14455    }
14456  };
14457  const transportParams = {
14458    ownerDocument,
14459    pdfBug,
14460    styleElement,
14461    enableHWA,
14462    loadingParams: {
14463      disableAutoFetch,
14464      enableXfa
14465    }
14466  };
14467  worker.promise.then(function () {
14468    if (task.destroyed) {
14469      throw new Error("Loading aborted");
14470    }
14471    if (worker.destroyed) {
14472      throw new Error("Worker was destroyed");
14473    }
14474    const workerIdPromise = worker.messageHandler.sendWithPromise("GetDocRequest", docParams, data ? [data.buffer] : null);
14475    let networkStream;
14476    if (rangeTransport) {
14477      networkStream = new PDFDataTransportStream({
14478        pdfDataRangeTransport: rangeTransport,
14479        disableRange,
14480        disableStream
14481      });
14482    } else if (!data) {
14483      if (!url) {
14484        throw new Error("getDocument - no `url` parameter provided.");
14485      }
14486      const NetworkStream = isValidFetchUrl(url) ? PDFFetchStream : isNodeJS ? PDFNodeStream : PDFNetworkStream;
14487      networkStream = new NetworkStream({
14488        url,
14489        length,
14490        httpHeaders,
14491        withCredentials,
14492        rangeChunkSize,
14493        disableRange,
14494        disableStream
14495      });
14496    }
14497    return workerIdPromise.then(workerId => {
14498      if (task.destroyed) {
14499        throw new Error("Loading aborted");
14500      }
14501      if (worker.destroyed) {
14502        throw new Error("Worker was destroyed");
14503      }
14504      const messageHandler = new MessageHandler(docId, workerId, worker.port);
14505      const transport = new WorkerTransport(messageHandler, task, networkStream, transportParams, transportFactory);
14506      task._transport = transport;
14507      messageHandler.send("Ready", null);
14508    });
14509  }).catch(task._capability.reject);
14510  return task;
14511}
14512class PDFDocumentLoadingTask {
14513  static #docId = 0;
14514  _capability = Promise.withResolvers();
14515  _transport = null;
14516  _worker = null;
14517  docId = `d${PDFDocumentLoadingTask.#docId++}`;
14518  destroyed = false;
14519  onPassword = null;
14520  onProgress = null;
14521  get promise() {
14522    return this._capability.promise;
14523  }
14524  async destroy() {
14525    this.destroyed = true;
14526    try {
14527      if (this._worker?.port) {
14528        this._worker._pendingDestroy = true;
14529      }
14530      await this._transport?.destroy();
14531    } catch (ex) {
14532      if (this._worker?.port) {
14533        delete this._worker._pendingDestroy;
14534      }
14535      throw ex;
14536    }
14537    this._transport = null;
14538    this._worker?.destroy();
14539    this._worker = null;
14540  }
14541  async getData() {
14542    return this._transport.getData();
14543  }
14544}
14545class PDFDataRangeTransport {
14546  #capability = Promise.withResolvers();
14547  #progressiveDoneListeners = [];
14548  #progressiveReadListeners = [];
14549  #progressListeners = [];
14550  #rangeListeners = [];
14551  constructor(length, initialData, progressiveDone = false, contentDispositionFilename = null) {
14552    this.length = length;
14553    this.initialData = initialData;
14554    this.progressiveDone = progressiveDone;
14555    this.contentDispositionFilename = contentDispositionFilename;
14556  }
14557  addRangeListener(listener) {
14558    this.#rangeListeners.push(listener);
14559  }
14560  addProgressListener(listener) {
14561    this.#progressListeners.push(listener);
14562  }
14563  addProgressiveReadListener(listener) {
14564    this.#progressiveReadListeners.push(listener);
14565  }
14566  addProgressiveDoneListener(listener) {
14567    this.#progressiveDoneListeners.push(listener);
14568  }
14569  onDataRange(begin, chunk) {
14570    for (const listener of this.#rangeListeners) {
14571      listener(begin, chunk);
14572    }
14573  }
14574  onDataProgress(loaded, total) {
14575    this.#capability.promise.then(() => {
14576      for (const listener of this.#progressListeners) {
14577        listener(loaded, total);
14578      }
14579    });
14580  }
14581  onDataProgressiveRead(chunk) {
14582    this.#capability.promise.then(() => {
14583      for (const listener of this.#progressiveReadListeners) {
14584        listener(chunk);
14585      }
14586    });
14587  }
14588  onDataProgressiveDone() {
14589    this.#capability.promise.then(() => {
14590      for (const listener of this.#progressiveDoneListeners) {
14591        listener();
14592      }
14593    });
14594  }
14595  transportReady() {
14596    this.#capability.resolve();
14597  }
14598  requestDataRange(begin, end) {
14599    unreachable("Abstract method PDFDataRangeTransport.requestDataRange");
14600  }
14601  abort() {}
14602}
14603class PDFDocumentProxy {
14604  constructor(pdfInfo, transport) {
14605    this._pdfInfo = pdfInfo;
14606    this._transport = transport;
14607  }
14608  get annotationStorage() {
14609    return this._transport.annotationStorage;
14610  }
14611  get canvasFactory() {
14612    return this._transport.canvasFactory;
14613  }
14614  get filterFactory() {
14615    return this._transport.filterFactory;
14616  }
14617  get numPages() {
14618    return this._pdfInfo.numPages;
14619  }
14620  get fingerprints() {
14621    return this._pdfInfo.fingerprints;
14622  }
14623  get isPureXfa() {
14624    return shadow(this, "isPureXfa", !!this._transport._htmlForXfa);
14625  }
14626  get allXfaHtml() {
14627    return this._transport._htmlForXfa;
14628  }
14629  getPage(pageNumber) {
14630    return this._transport.getPage(pageNumber);
14631  }
14632  getPageIndex(ref) {
14633    return this._transport.getPageIndex(ref);
14634  }
14635  getDestinations() {
14636    return this._transport.getDestinations();
14637  }
14638  getDestination(id) {
14639    return this._transport.getDestination(id);
14640  }
14641  getPageLabels() {
14642    return this._transport.getPageLabels();
14643  }
14644  getPageLayout() {
14645    return this._transport.getPageLayout();
14646  }
14647  getPageMode() {
14648    return this._transport.getPageMode();
14649  }
14650  getViewerPreferences() {
14651    return this._transport.getViewerPreferences();
14652  }
14653  getOpenAction() {
14654    return this._transport.getOpenAction();
14655  }
14656  getAttachments() {
14657    return this._transport.getAttachments();
14658  }
14659  getAnnotationsByType(types, pageIndexesToSkip) {
14660    return this._transport.getAnnotationsByType(types, pageIndexesToSkip);
14661  }
14662  getJSActions() {
14663    return this._transport.getDocJSActions();
14664  }
14665  getOutline() {
14666    return this._transport.getOutline();
14667  }
14668  getOptionalContentConfig({
14669    intent = "display"
14670  } = {}) {
14671    const {
14672      renderingIntent
14673    } = this._transport.getRenderingIntent(intent);
14674    return this._transport.getOptionalContentConfig(renderingIntent);
14675  }
14676  getPermissions() {
14677    return this._transport.getPermissions();
14678  }
14679  getMetadata() {
14680    return this._transport.getMetadata();
14681  }
14682  getMarkInfo() {
14683    return this._transport.getMarkInfo();
14684  }
14685  getData() {
14686    return this._transport.getData();
14687  }
14688  saveDocument() {
14689    return this._transport.saveDocument();
14690  }
14691  extractPages(pageInfos) {
14692    return this._transport.extractPages(pageInfos);
14693  }
14694  getDownloadInfo() {
14695    return this._transport.downloadInfoCapability.promise;
14696  }
14697  cleanup(keepLoadedFonts = false) {
14698    return this._transport.startCleanup(keepLoadedFonts || this.isPureXfa);
14699  }
14700  destroy() {
14701    return this.loadingTask.destroy();
14702  }
14703  cachedPageNumber(ref) {
14704    return this._transport.cachedPageNumber(ref);
14705  }
14706  get loadingParams() {
14707    return this._transport.loadingParams;
14708  }
14709  get loadingTask() {
14710    return this._transport.loadingTask;
14711  }
14712  getFieldObjects() {
14713    return this._transport.getFieldObjects();
14714  }
14715  hasJSActions() {
14716    return this._transport.hasJSActions();
14717  }
14718  getCalculationOrderIds() {
14719    return this._transport.getCalculationOrderIds();
14720  }
14721}
14722class PDFPageProxy {
14723  #pendingCleanup = false;
14724  #pagesMapper = PagesMapper.instance;
14725  constructor(pageIndex, pageInfo, transport, pdfBug = false) {
14726    this._pageIndex = pageIndex;
14727    this._pageInfo = pageInfo;
14728    this._transport = transport;
14729    this._stats = pdfBug ? new StatTimer() : null;
14730    this._pdfBug = pdfBug;
14731    this.commonObjs = transport.commonObjs;
14732    this.objs = new PDFObjects();
14733    this._intentStates = new Map();
14734    this.destroyed = false;
14735    this.recordedBBoxes = null;
14736  }
14737  get pageNumber() {
14738    return this._pageIndex + 1;
14739  }
14740  set pageNumber(value) {
14741    this._pageIndex = value - 1;
14742  }
14743  get rotate() {
14744    return this._pageInfo.rotate;
14745  }
14746  get ref() {
14747    return this._pageInfo.ref;
14748  }
14749  get userUnit() {
14750    return this._pageInfo.userUnit;
14751  }
14752  get view() {
14753    return this._pageInfo.view;
14754  }
14755  getViewport({
14756    scale,
14757    rotation = this.rotate,
14758    offsetX = 0,
14759    offsetY = 0,
14760    dontFlip = false
14761  } = {}) {
14762    return new PageViewport({
14763      viewBox: this.view,
14764      userUnit: this.userUnit,
14765      scale,
14766      rotation,
14767      offsetX,
14768      offsetY,
14769      dontFlip
14770    });
14771  }
14772  getAnnotations({
14773    intent = "display"
14774  } = {}) {
14775    const {
14776      renderingIntent
14777    } = this._transport.getRenderingIntent(intent);
14778    return this._transport.getAnnotations(this._pageIndex, renderingIntent);
14779  }
14780  getJSActions() {
14781    return this._transport.getPageJSActions(this._pageIndex);
14782  }
14783  get filterFactory() {
14784    return this._transport.filterFactory;
14785  }
14786  get isPureXfa() {
14787    return shadow(this, "isPureXfa", !!this._transport._htmlForXfa);
14788  }
14789  async getXfa() {
14790    return this._transport._htmlForXfa?.children[this._pageIndex] || null;
14791  }
14792  render({
14793    canvasContext,
14794    canvas = canvasContext.canvas,
14795    viewport,
14796    intent = "display",
14797    annotationMode = AnnotationMode.ENABLE,
14798    transform = null,
14799    background = null,
14800    optionalContentConfigPromise = null,
14801    annotationCanvasMap = null,
14802    pageColors = null,
14803    printAnnotationStorage = null,
14804    isEditing = false,
14805    recordOperations = false,
14806    operationsFilter = null
14807  }) {
14808    this._stats?.time("Overall");
14809    const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage, isEditing);
14810    const {
14811      renderingIntent,
14812      cacheKey
14813    } = intentArgs;
14814    this.#pendingCleanup = false;
14815    optionalContentConfigPromise ||= this._transport.getOptionalContentConfig(renderingIntent);
14816    let intentState = this._intentStates.get(cacheKey);
14817    if (!intentState) {
14818      intentState = Object.create(null);
14819      this._intentStates.set(cacheKey, intentState);
14820    }
14821    if (intentState.streamReaderCancelTimeout) {
14822      clearTimeout(intentState.streamReaderCancelTimeout);
14823      intentState.streamReaderCancelTimeout = null;
14824    }
14825    const intentPrint = !!(renderingIntent & RenderingIntentFlag.PRINT);
14826    if (!intentState.displayReadyCapability) {
14827      intentState.displayReadyCapability = Promise.withResolvers();
14828      intentState.operatorList = {
14829        fnArray: [],
14830        argsArray: [],
14831        lastChunk: false,
14832        separateAnnots: null
14833      };
14834      this._stats?.time("Page Request");
14835      this._pumpOperatorList(intentArgs);
14836    }
14837    const recordForDebugger = Boolean(this._pdfBug && globalThis.StepperManager?.enabled);
14838    const shouldRecordOperations = !this.recordedBBoxes && (recordOperations || recordForDebugger);
14839    const complete = error => {
14840      intentState.renderTasks.delete(internalRenderTask);
14841      if (shouldRecordOperations) {
14842        const recordedBBoxes = internalRenderTask.gfx?.dependencyTracker.take();
14843        if (recordedBBoxes) {
14844          if (internalRenderTask.stepper) {
14845            internalRenderTask.stepper.setOperatorBBoxes(recordedBBoxes, internalRenderTask.gfx.dependencyTracker.takeDebugMetadata());
14846          }
14847          if (recordOperations) {
14848            this.recordedBBoxes = recordedBBoxes;
14849          }
14850        }
14851      }
14852      if (intentPrint) {
14853        this.#pendingCleanup = true;
14854      }
14855      this.#tryCleanup();
14856      if (error) {
14857        internalRenderTask.capability.reject(error);
14858        this._abortOperatorList({
14859          intentState,
14860          reason: error instanceof Error ? error : new Error(error)
14861        });
14862      } else {
14863        internalRenderTask.capability.resolve();
14864      }
14865      if (this._stats) {
14866        this._stats.timeEnd("Rendering");
14867        this._stats.timeEnd("Overall");
14868        if (globalThis.Stats?.enabled) {
14869          globalThis.Stats.add(this.pageNumber, this._stats);
14870        }
14871      }
14872    };
14873    const internalRenderTask = new InternalRenderTask({
14874      callback: complete,
14875      params: {
14876        canvas,
14877        canvasContext,
14878        dependencyTracker: shouldRecordOperations ? new CanvasDependencyTracker(canvas, intentState.operatorList.length, recordForDebugger) : null,
14879        viewport,
14880        transform,
14881        background
14882      },
14883      objs: this.objs,
14884      commonObjs: this.commonObjs,
14885      annotationCanvasMap,
14886      operatorList: intentState.operatorList,
14887      pageIndex: this._pageIndex,
14888      canvasFactory: this._transport.canvasFactory,
14889      filterFactory: this._transport.filterFactory,
14890      useRequestAnimationFrame: !intentPrint,
14891      pdfBug: this._pdfBug,
14892      pageColors,
14893      enableHWA: this._transport.enableHWA,
14894      operationsFilter
14895    });
14896    (intentState.renderTasks ||= new Set()).add(internalRenderTask);
14897    const renderTask = internalRenderTask.task;
14898    Promise.all([intentState.displayReadyCapability.promise, optionalContentConfigPromise]).then(([transparency, optionalContentConfig]) => {
14899      if (this.destroyed) {
14900        complete();
14901        return;
14902      }
14903      this._stats?.time("Rendering");
14904      if (!(optionalContentConfig.renderingIntent & renderingIntent)) {
14905        throw new Error("Must use the same `intent`-argument when calling the `PDFPageProxy.render` " + "and `PDFDocumentProxy.getOptionalContentConfig` methods.");
14906      }
14907      internalRenderTask.initializeGraphics({
14908        transparency,
14909        optionalContentConfig
14910      });
14911      internalRenderTask.operatorListChanged();
14912    }).catch(complete);
14913    return renderTask;
14914  }
14915  getOperatorList({
14916    intent = "display",
14917    annotationMode = AnnotationMode.ENABLE,
14918    printAnnotationStorage = null,
14919    isEditing = false
14920  } = {}) {
14921    function operatorListChanged() {
14922      if (intentState.operatorList.lastChunk) {
14923        intentState.opListReadCapability.resolve(intentState.operatorList);
14924        intentState.renderTasks.delete(opListTask);
14925      }
14926    }
14927    const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage, isEditing, true);
14928    let intentState = this._intentStates.get(intentArgs.cacheKey);
14929    if (!intentState) {
14930      intentState = Object.create(null);
14931      this._intentStates.set(intentArgs.cacheKey, intentState);
14932    }
14933    let opListTask;
14934    if (!intentState.opListReadCapability) {
14935      opListTask = Object.create(null);
14936      opListTask.operatorListChanged = operatorListChanged;
14937      intentState.opListReadCapability = Promise.withResolvers();
14938      (intentState.renderTasks ||= new Set()).add(opListTask);
14939      intentState.operatorList = {
14940        fnArray: [],
14941        argsArray: [],
14942        lastChunk: false,
14943        separateAnnots: null
14944      };
14945      this._stats?.time("Page Request");
14946      this._pumpOperatorList(intentArgs);
14947    }
14948    return intentState.opListReadCapability.promise;
14949  }
14950  streamTextContent({
14951    includeMarkedContent = false,
14952    disableNormalization = false
14953  } = {}) {
14954    const TEXT_CONTENT_CHUNK_SIZE = 100;
14955    return this._transport.messageHandler.sendWithStream("GetTextContent", {
14956      pageId: this.#pagesMapper.getPageId(this._pageIndex + 1) - 1,
14957      pageIndex: this._pageIndex,
14958      includeMarkedContent: includeMarkedContent === true,
14959      disableNormalization: disableNormalization === true
14960    }, {
14961      highWaterMark: TEXT_CONTENT_CHUNK_SIZE,
14962      size(textContent) {
14963        return textContent.items.length;
14964      }
14965    });
14966  }
14967  getTextContent(params = {}) {
14968    if (this._transport._htmlForXfa) {
14969      return this.getXfa().then(xfa => XfaText.textContent(xfa));
14970    }
14971    const readableStream = this.streamTextContent(params);
14972    return new Promise(function (resolve, reject) {
14973      function pump() {
14974        reader.read().then(function ({
14975          value,
14976          done
14977        }) {
14978          if (done) {
14979            resolve(textContent);
14980            return;
14981          }
14982          textContent.lang ??= value.lang;
14983          Object.assign(textContent.styles, value.styles);
14984          textContent.items.push(...value.items);
14985          pump();
14986        }, reject);
14987      }
14988      const reader = readableStream.getReader();
14989      const textContent = {
14990        items: [],
14991        styles: Object.create(null),
14992        lang: null
14993      };
14994      pump();
14995    });
14996  }
14997  getStructTree() {
14998    return this._transport.getStructTree(this._pageIndex);
14999  }
15000  _destroy() {
15001    this.destroyed = true;
15002    const waitOn = [];
15003    for (const intentState of this._intentStates.values()) {
15004      this._abortOperatorList({
15005        intentState,
15006        reason: new Error("Page was destroyed."),
15007        force: true
15008      });
15009      if (intentState.opListReadCapability) {
15010        continue;
15011      }
15012      for (const internalRenderTask of intentState.renderTasks) {
15013        waitOn.push(internalRenderTask.completed);
15014        internalRenderTask.cancel();
15015      }
15016    }
15017    this.objs.clear();
15018    this.#pendingCleanup = false;
15019    return Promise.all(waitOn);
15020  }
15021  cleanup(resetStats = false) {
15022    this.#pendingCleanup = true;
15023    const success = this.#tryCleanup();
15024    if (resetStats && success) {
15025      this._stats &&= new StatTimer();
15026    }
15027    return success;
15028  }
15029  #tryCleanup() {
15030    if (!this.#pendingCleanup || this.destroyed) {
15031      return false;
vendor: 32,691 bytes, lines 15032-16063
15032    }
15033    for (const {
15034      renderTasks,
15035      operatorList
15036    } of this._intentStates.values()) {
15037      if (renderTasks.size > 0 || !operatorList.lastChunk) {
15038        return false;
15039      }
15040    }
15041    this._intentStates.clear();
15042    this.objs.clear();
15043    this.#pendingCleanup = false;
15044    return true;
15045  }
15046  _startRenderPage(transparency, cacheKey) {
15047    const intentState = this._intentStates.get(cacheKey);
15048    if (!intentState) {
15049      return;
15050    }
15051    this._stats?.timeEnd("Page Request");
15052    intentState.displayReadyCapability?.resolve(transparency);
15053  }
15054  _renderPageChunk(operatorListChunk, intentState) {
15055    for (let i = 0, ii = operatorListChunk.length; i < ii; i++) {
15056      intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
15057      intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
15058    }
15059    intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
15060    intentState.operatorList.separateAnnots = operatorListChunk.separateAnnots;
15061    for (const internalRenderTask of intentState.renderTasks) {
15062      internalRenderTask.operatorListChanged();
15063    }
15064    if (operatorListChunk.lastChunk) {
15065      this.#tryCleanup();
15066    }
15067  }
15068  _pumpOperatorList({
15069    renderingIntent,
15070    cacheKey,
15071    annotationStorageSerializable,
15072    modifiedIds
15073  }) {
15074    const {
15075      map,
15076      transfer
15077    } = annotationStorageSerializable;
15078    const readableStream = this._transport.messageHandler.sendWithStream("GetOperatorList", {
15079      pageId: this.#pagesMapper.getPageId(this._pageIndex + 1) - 1,
15080      pageIndex: this._pageIndex,
15081      intent: renderingIntent,
15082      cacheKey,
15083      annotationStorage: map,
15084      modifiedIds
15085    }, transfer);
15086    const reader = readableStream.getReader();
15087    const intentState = this._intentStates.get(cacheKey);
15088    intentState.streamReader = reader;
15089    const pump = () => {
15090      reader.read().then(({
15091        value,
15092        done
15093      }) => {
15094        if (done) {
15095          intentState.streamReader = null;
15096          return;
15097        }
15098        if (this._transport.destroyed) {
15099          return;
15100        }
15101        this._renderPageChunk(value, intentState);
15102        pump();
15103      }, reason => {
15104        intentState.streamReader = null;
15105        if (this._transport.destroyed) {
15106          return;
15107        }
15108        if (intentState.operatorList) {
15109          intentState.operatorList.lastChunk = true;
15110          for (const internalRenderTask of intentState.renderTasks) {
15111            internalRenderTask.operatorListChanged();
15112          }
15113          this.#tryCleanup();
15114        }
15115        if (intentState.displayReadyCapability) {
15116          intentState.displayReadyCapability.reject(reason);
15117        } else if (intentState.opListReadCapability) {
15118          intentState.opListReadCapability.reject(reason);
15119        } else {
15120          throw reason;
15121        }
15122      });
15123    };
15124    pump();
15125  }
15126  _abortOperatorList({
15127    intentState,
15128    reason,
15129    force = false
15130  }) {
15131    if (!intentState.streamReader) {
15132      return;
15133    }
15134    if (intentState.streamReaderCancelTimeout) {
15135      clearTimeout(intentState.streamReaderCancelTimeout);
15136      intentState.streamReaderCancelTimeout = null;
15137    }
15138    if (!force) {
15139      if (intentState.renderTasks.size > 0) {
15140        return;
15141      }
15142      if (reason instanceof RenderingCancelledException) {
15143        let delay = RENDERING_CANCELLED_TIMEOUT;
15144        if (reason.extraDelay > 0 && reason.extraDelay < 1000) {
15145          delay += reason.extraDelay;
15146        }
15147        intentState.streamReaderCancelTimeout = setTimeout(() => {
15148          intentState.streamReaderCancelTimeout = null;
15149          this._abortOperatorList({
15150            intentState,
15151            reason,
15152            force: true
15153          });
15154        }, delay);
15155        return;
15156      }
15157    }
15158    intentState.streamReader.cancel(new AbortException(reason.message)).catch(() => {});
15159    intentState.streamReader = null;
15160    if (this._transport.destroyed) {
15161      return;
15162    }
15163    for (const [curCacheKey, curIntentState] of this._intentStates) {
15164      if (curIntentState === intentState) {
15165        this._intentStates.delete(curCacheKey);
15166        break;
15167      }
15168    }
15169    this.cleanup();
15170  }
15171  get stats() {
15172    return this._stats;
15173  }
15174}
15175class PDFWorker {
15176  #capability = Promise.withResolvers();
15177  #messageHandler = null;
15178  #port = null;
15179  #webWorker = null;
15180  static #fakeWorkerId = 0;
15181  static #isWorkerDisabled = false;
15182  static #workerPorts = new WeakMap();
15183  static {
15184    if (isNodeJS) {
15185      this.#isWorkerDisabled = true;
15186      GlobalWorkerOptions.workerSrc ||= "./pdf.worker.mjs";
15187    }
15188    this._isSameOrigin = (baseUrl, otherUrl) => {
15189      const base = URL.parse(baseUrl);
15190      if (!base?.origin || base.origin === "null") {
15191        return false;
15192      }
15193      const other = new URL(otherUrl, base);
15194      return base.origin === other.origin;
15195    };
15196    this._createCDNWrapper = url => {
15197      const wrapper = `await import("${url}");`;
15198      return URL.createObjectURL(new Blob([wrapper], {
15199        type: "text/javascript"
15200      }));
15201    };
15202    this.fromPort = params => {
15203      deprecated("`PDFWorker.fromPort` - please use `PDFWorker.create` instead.");
15204      if (!params?.port) {
15205        throw new Error("PDFWorker.fromPort - invalid method signature.");
15206      }
15207      return this.create(params);
15208    };
15209  }
15210  constructor({
15211    name = null,
15212    port = null,
15213    verbosity = getVerbosityLevel()
15214  } = {}) {
15215    this.name = name;
15216    this.destroyed = false;
15217    this.verbosity = verbosity;
15218    if (port) {
15219      if (PDFWorker.#workerPorts.has(port)) {
15220        throw new Error("Cannot use more than one PDFWorker per port.");
15221      }
15222      PDFWorker.#workerPorts.set(port, this);
15223      this.#initializeFromPort(port);
15224    } else {
15225      this.#initialize();
15226    }
15227  }
15228  get promise() {
15229    return this.#capability.promise;
15230  }
15231  #resolve() {
15232    this.#capability.resolve();
15233    this.#messageHandler.send("configure", {
15234      verbosity: this.verbosity
15235    });
15236  }
15237  get port() {
15238    return this.#port;
15239  }
15240  get messageHandler() {
15241    return this.#messageHandler;
15242  }
15243  #initializeFromPort(port) {
15244    this.#port = port;
15245    this.#messageHandler = new MessageHandler("main", "worker", port);
15246    this.#messageHandler.on("ready", () => {});
15247    this.#resolve();
15248  }
15249  #initialize() {
15250    if (PDFWorker.#isWorkerDisabled || PDFWorker.#mainThreadWorkerMessageHandler) {
15251      this.#setupFakeWorker();
15252      return;
15253    }
15254    let {
15255      workerSrc
15256    } = PDFWorker;
15257    try {
15258      if (!PDFWorker._isSameOrigin(window.location, workerSrc)) {
15259        workerSrc = PDFWorker._createCDNWrapper(new URL(workerSrc, window.location).href);
15260      }
15261      const worker = new Worker(workerSrc, {
15262        type: "module"
15263      });
15264      const messageHandler = new MessageHandler("main", "worker", worker);
15265      const terminateEarly = () => {
15266        ac.abort();
15267        messageHandler.destroy();
15268        worker.terminate();
15269        if (this.destroyed) {
15270          this.#capability.reject(new Error("Worker was destroyed"));
15271        } else {
15272          this.#setupFakeWorker();
15273        }
15274      };
15275      const ac = new AbortController();
15276      worker.addEventListener("error", () => {
15277        if (!this.#webWorker) {
15278          terminateEarly();
15279        }
15280      }, {
15281        signal: ac.signal
15282      });
15283      messageHandler.on("test", data => {
15284        ac.abort();
15285        if (this.destroyed || !data) {
15286          terminateEarly();
15287          return;
15288        }
15289        this.#messageHandler = messageHandler;
15290        this.#port = worker;
15291        this.#webWorker = worker;
15292        this.#resolve();
15293      });
15294      messageHandler.on("ready", data => {
15295        ac.abort();
15296        if (this.destroyed) {
15297          terminateEarly();
15298          return;
15299        }
15300        try {
15301          sendTest();
15302        } catch {
15303          this.#setupFakeWorker();
15304        }
15305      });
15306      const sendTest = () => {
15307        const testObj = new Uint8Array();
15308        messageHandler.send("test", testObj, [testObj.buffer]);
15309      };
15310      sendTest();
15311      return;
15312    } catch {
15313      info("The worker has been disabled.");
15314    }
15315    this.#setupFakeWorker();
15316  }
15317  #setupFakeWorker() {
15318    if (!PDFWorker.#isWorkerDisabled) {
15319      warn("Setting up fake worker.");
15320      PDFWorker.#isWorkerDisabled = true;
15321    }
15322    PDFWorker._setupFakeWorkerGlobal.then(WorkerMessageHandler => {
15323      if (this.destroyed) {
15324        this.#capability.reject(new Error("Worker was destroyed"));
15325        return;
15326      }
15327      const port = new LoopbackPort();
15328      this.#port = port;
15329      const id = `fake${PDFWorker.#fakeWorkerId++}`;
15330      const workerHandler = new MessageHandler(id + "_worker", id, port);
15331      WorkerMessageHandler.setup(workerHandler, port);
15332      this.#messageHandler = new MessageHandler(id, id + "_worker", port);
15333      this.#resolve();
15334    }).catch(reason => {
15335      this.#capability.reject(new Error(`Setting up fake worker failed: "${reason.message}".`));
15336    });
15337  }
15338  destroy() {
15339    this.destroyed = true;
15340    this.#webWorker?.terminate();
15341    this.#webWorker = null;
15342    PDFWorker.#workerPorts.delete(this.#port);
15343    this.#port = null;
15344    this.#messageHandler?.destroy();
15345    this.#messageHandler = null;
15346  }
15347  static create(params) {
15348    const cachedPort = this.#workerPorts.get(params?.port);
15349    if (cachedPort) {
15350      if (cachedPort._pendingDestroy) {
15351        throw new Error("PDFWorker.create - the worker is being destroyed.\n" + "Please remember to await `PDFDocumentLoadingTask.destroy()`-calls.");
15352      }
15353      return cachedPort;
15354    }
15355    return new PDFWorker(params);
15356  }
15357  static get workerSrc() {
15358    if (GlobalWorkerOptions.workerSrc) {
15359      return GlobalWorkerOptions.workerSrc;
15360    }
15361    throw new Error('No "GlobalWorkerOptions.workerSrc" specified.');
15362  }
15363  static get #mainThreadWorkerMessageHandler() {
15364    try {
15365      return globalThis.pdfjsWorker?.WorkerMessageHandler || null;
15366    } catch {
15367      return null;
15368    }
15369  }
15370  static get _setupFakeWorkerGlobal() {
15371    const loader = async () => {
15372      if (this.#mainThreadWorkerMessageHandler) {
15373        return this.#mainThreadWorkerMessageHandler;
15374      }
15375      const worker = await import(
15376      /*webpackIgnore: true*/
15377      /*@vite-ignore*/
15378      this.workerSrc);
15379      return worker.WorkerMessageHandler;
15380    };
15381    return shadow(this, "_setupFakeWorkerGlobal", loader());
15382  }
15383}
15384class WorkerTransport {
15385  downloadInfoCapability = Promise.withResolvers();
15386  #fullReader = null;
15387  #methodPromises = new Map();
15388  #networkStream = null;
15389  #pageCache = new Map();
15390  #pagePromises = new Map();
15391  #pageRefCache = new Map();
15392  #passwordCapability = null;
15393  #pagesMapper = PagesMapper.instance;
15394  constructor(messageHandler, loadingTask, networkStream, params, factory) {
15395    this.messageHandler = messageHandler;
15396    this.loadingTask = loadingTask;
15397    this.#networkStream = networkStream;
15398    this.commonObjs = new PDFObjects();
15399    this.fontLoader = new FontLoader({
15400      ownerDocument: params.ownerDocument,
15401      styleElement: params.styleElement
15402    });
15403    this.enableHWA = params.enableHWA;
15404    this.loadingParams = params.loadingParams;
15405    this._params = params;
15406    this.canvasFactory = factory.canvasFactory;
15407    this.filterFactory = factory.filterFactory;
15408    this.cMapReaderFactory = factory.cMapReaderFactory;
15409    this.standardFontDataFactory = factory.standardFontDataFactory;
15410    this.wasmFactory = factory.wasmFactory;
15411    this.destroyed = false;
15412    this.destroyCapability = null;
15413    this.setupMessageHandler();
15414    this.#pagesMapper.addListener(this.#updateCaches.bind(this));
15415  }
15416  #updateCaches() {
15417    const newPageCache = new Map();
15418    const newPromiseCache = new Map();
15419    for (let i = 0, ii = this.#pagesMapper.pagesNumber; i < ii; i++) {
15420      const prevPageIndex = this.#pagesMapper.getPrevPageNumber(i + 1) - 1;
15421      const page = this.#pageCache.get(prevPageIndex);
15422      if (page) {
15423        newPageCache.set(i, page);
15424      }
15425      const promise = this.#pagePromises.get(prevPageIndex);
15426      if (promise) {
15427        newPromiseCache.set(i, promise);
15428      }
15429    }
15430    this.#pageCache = newPageCache;
15431    this.#pagePromises = newPromiseCache;
15432  }
15433  #cacheSimpleMethod(name, data = null) {
15434    const cachedPromise = this.#methodPromises.get(name);
15435    if (cachedPromise) {
15436      return cachedPromise;
15437    }
15438    const promise = this.messageHandler.sendWithPromise(name, data);
15439    this.#methodPromises.set(name, promise);
15440    return promise;
15441  }
15442  #onProgress({
15443    loaded,
15444    total
15445  }) {
15446    this.loadingTask.onProgress?.({
15447      loaded,
15448      total,
15449      percent: MathClamp(Math.round(loaded / total * 100), 0, 100)
15450    });
15451  }
15452  get annotationStorage() {
15453    return shadow(this, "annotationStorage", new AnnotationStorage());
15454  }
15455  getRenderingIntent(intent, annotationMode = AnnotationMode.ENABLE, printAnnotationStorage = null, isEditing = false, isOpList = false) {
15456    let renderingIntent = RenderingIntentFlag.DISPLAY;
15457    let annotationStorageSerializable = SerializableEmpty;
15458    switch (intent) {
15459      case "any":
15460        renderingIntent = RenderingIntentFlag.ANY;
15461        break;
15462      case "display":
15463        break;
15464      case "print":
15465        renderingIntent = RenderingIntentFlag.PRINT;
15466        break;
15467      default:
15468        warn(`getRenderingIntent - invalid intent: ${intent}`);
15469    }
15470    const annotationStorage = renderingIntent & RenderingIntentFlag.PRINT && printAnnotationStorage instanceof PrintAnnotationStorage ? printAnnotationStorage : this.annotationStorage;
15471    switch (annotationMode) {
15472      case AnnotationMode.DISABLE:
15473        renderingIntent += RenderingIntentFlag.ANNOTATIONS_DISABLE;
15474        break;
15475      case AnnotationMode.ENABLE:
15476        break;
15477      case AnnotationMode.ENABLE_FORMS:
15478        renderingIntent += RenderingIntentFlag.ANNOTATIONS_FORMS;
15479        break;
15480      case AnnotationMode.ENABLE_STORAGE:
15481        renderingIntent += RenderingIntentFlag.ANNOTATIONS_STORAGE;
15482        annotationStorageSerializable = annotationStorage.serializable;
15483        break;
15484      default:
15485        warn(`getRenderingIntent - invalid annotationMode: ${annotationMode}`);
15486    }
15487    if (isEditing) {
15488      renderingIntent += RenderingIntentFlag.IS_EDITING;
15489    }
15490    if (isOpList) {
15491      renderingIntent += RenderingIntentFlag.OPLIST;
15492    }
15493    const {
15494      ids: modifiedIds,
15495      hash: modifiedIdsHash
15496    } = annotationStorage.modifiedIds;
15497    const cacheKeyBuf = [renderingIntent, annotationStorageSerializable.hash, modifiedIdsHash];
15498    return {
15499      renderingIntent,
15500      cacheKey: cacheKeyBuf.join("_"),
15501      annotationStorageSerializable,
15502      modifiedIds
15503    };
15504  }
15505  destroy() {
15506    if (this.destroyCapability) {
15507      return this.destroyCapability.promise;
15508    }
15509    this.destroyed = true;
15510    this.destroyCapability = Promise.withResolvers();
15511    this.#passwordCapability?.reject(new Error("Worker was destroyed during onPassword callback"));
15512    const waitOn = [];
15513    for (const page of this.#pageCache.values()) {
15514      waitOn.push(page._destroy());
15515    }
15516    this.#pageCache.clear();
15517    this.#pagePromises.clear();
15518    this.#pageRefCache.clear();
15519    if (this.hasOwnProperty("annotationStorage")) {
15520      this.annotationStorage.resetModified();
15521    }
15522    const terminated = this.messageHandler.sendWithPromise("Terminate", null);
15523    waitOn.push(terminated);
15524    Promise.all(waitOn).then(() => {
15525      this.commonObjs.clear();
15526      this.fontLoader.clear();
15527      this.#methodPromises.clear();
15528      this.filterFactory.destroy();
15529      TextLayer.cleanup();
15530      this.#networkStream?.cancelAllRequests(new AbortException("Worker was terminated."));
15531      this.messageHandler?.destroy();
15532      this.messageHandler = null;
15533      this.destroyCapability.resolve();
15534    }, this.destroyCapability.reject);
15535    return this.destroyCapability.promise;
15536  }
15537  setupMessageHandler() {
15538    const {
15539      messageHandler,
15540      loadingTask
15541    } = this;
15542    messageHandler.on("GetReader", (data, sink) => {
15543      assert(this.#networkStream, "GetReader - no `BasePDFStream` instance available.");
15544      this.#fullReader = this.#networkStream.getFullReader();
15545      this.#fullReader.onProgress = evt => this.#onProgress(evt);
15546      sink.onPull = () => {
15547        this.#fullReader.read().then(function ({
15548          value,
15549          done
15550        }) {
15551          if (done) {
15552            sink.close();
15553            return;
15554          }
15555          assert(value instanceof ArrayBuffer, "GetReader - expected an ArrayBuffer.");
15556          sink.enqueue(new Uint8Array(value), 1, [value]);
15557        }).catch(reason => {
15558          sink.error(reason);
15559        });
15560      };
15561      sink.onCancel = reason => {
15562        this.#fullReader.cancel(reason);
15563        sink.ready.catch(readyReason => {
15564          if (this.destroyed) {
15565            return;
15566          }
15567          throw readyReason;
15568        });
15569      };
15570    });
15571    messageHandler.on("ReaderHeadersReady", async data => {
15572      await this.#fullReader.headersReady;
15573      const {
15574        isStreamingSupported,
15575        isRangeSupported,
15576        contentLength
15577      } = this.#fullReader;
15578      if (isStreamingSupported && isRangeSupported) {
15579        this.#fullReader.onProgress = null;
15580      }
15581      return {
15582        isStreamingSupported,
15583        isRangeSupported,
15584        contentLength
15585      };
15586    });
15587    messageHandler.on("GetRangeReader", (data, sink) => {
15588      assert(this.#networkStream, "GetRangeReader - no `BasePDFStream` instance available.");
15589      const rangeReader = this.#networkStream.getRangeReader(data.begin, data.end);
15590      if (!rangeReader) {
15591        sink.close();
15592        return;
15593      }
15594      sink.onPull = () => {
15595        rangeReader.read().then(function ({
15596          value,
15597          done
15598        }) {
15599          if (done) {
15600            sink.close();
15601            return;
15602          }
15603          assert(value instanceof ArrayBuffer, "GetRangeReader - expected an ArrayBuffer.");
15604          sink.enqueue(new Uint8Array(value), 1, [value]);
15605        }).catch(reason => {
15606          sink.error(reason);
15607        });
15608      };
15609      sink.onCancel = reason => {
15610        rangeReader.cancel(reason);
15611        sink.ready.catch(readyReason => {
15612          if (this.destroyed) {
15613            return;
15614          }
15615          throw readyReason;
15616        });
15617      };
15618    });
15619    messageHandler.on("GetDoc", ({
15620      pdfInfo
15621    }) => {
15622      this.#pagesMapper.pagesNumber = pdfInfo.numPages;
15623      this._numPages = pdfInfo.numPages;
15624      this._htmlForXfa = pdfInfo.htmlForXfa;
15625      delete pdfInfo.htmlForXfa;
15626      loadingTask._capability.resolve(new PDFDocumentProxy(pdfInfo, this));
15627    });
15628    messageHandler.on("DocException", ex => {
15629      loadingTask._capability.reject(wrapReason(ex));
15630    });
15631    messageHandler.on("PasswordRequest", ex => {
15632      this.#passwordCapability = Promise.withResolvers();
15633      try {
15634        if (!loadingTask.onPassword) {
15635          throw wrapReason(ex);
15636        }
15637        const updatePassword = password => {
15638          if (password instanceof Error) {
15639            this.#passwordCapability.reject(password);
15640          } else {
15641            this.#passwordCapability.resolve({
15642              password
15643            });
15644          }
15645        };
15646        loadingTask.onPassword(updatePassword, ex.code);
15647      } catch (err) {
15648        this.#passwordCapability.reject(err);
15649      }
15650      return this.#passwordCapability.promise;
15651    });
15652    messageHandler.on("DataLoaded", data => {
15653      this.#onProgress({
15654        loaded: data.length,
15655        total: data.length
15656      });
15657      this.downloadInfoCapability.resolve(data);
15658    });
15659    messageHandler.on("StartRenderPage", data => {
15660      if (this.destroyed) {
15661        return;
15662      }
15663      const page = this.#pageCache.get(data.pageIndex);
15664      page._startRenderPage(data.transparency, data.cacheKey);
15665    });
15666    messageHandler.on("commonobj", ([id, type, exportedData]) => {
15667      if (this.destroyed) {
15668        return null;
15669      }
15670      if (this.commonObjs.has(id)) {
15671        return null;
15672      }
15673      switch (type) {
15674        case "Font":
15675          if ("error" in exportedData) {
15676            const exportedError = exportedData.error;
15677            warn(`Error during font loading: ${exportedError}`);
15678            this.commonObjs.resolve(id, exportedError);
15679            break;
15680          }
15681          const fontData = new FontInfo(exportedData);
15682          const inspectFont = this._params.pdfBug && globalThis.FontInspector?.enabled ? (font, url) => globalThis.FontInspector.fontAdded(font, url) : null;
15683          const font = new FontFaceObject(fontData, inspectFont, exportedData.extra, exportedData.charProcOperatorList);
15684          this.fontLoader.bind(font).catch(() => messageHandler.sendWithPromise("FontFallback", {
15685            id
15686          })).finally(() => {
15687            if (!font.fontExtraProperties && font.data) {
15688              font.clearData();
15689            }
15690            this.commonObjs.resolve(id, font);
15691          });
15692          break;
15693        case "CopyLocalImage":
15694          const {
15695            imageRef
15696          } = exportedData;
15697          assert(imageRef, "The imageRef must be defined.");
15698          for (const pageProxy of this.#pageCache.values()) {
15699            for (const [, data] of pageProxy.objs) {
15700              if (data?.ref !== imageRef) {
15701                continue;
15702              }
15703              if (!data.dataLen) {
15704                return null;
15705              }
15706              this.commonObjs.resolve(id, structuredClone(data));
15707              return data.dataLen;
15708            }
15709          }
15710          break;
15711        case "FontPath":
15712          this.commonObjs.resolve(id, new FontPathInfo(exportedData));
15713          break;
15714        case "Image":
15715          this.commonObjs.resolve(id, exportedData);
15716          break;
15717        case "Pattern":
15718          const pattern = new PatternInfo(exportedData);
15719          this.commonObjs.resolve(id, pattern.getIR());
15720          break;
15721        default:
15722          throw new Error(`Got unknown common object type ${type}`);
15723      }
15724      return null;
15725    });
15726    messageHandler.on("obj", ([id, pageIndex, type, imageData]) => {
15727      if (this.destroyed) {
15728        return;
15729      }
15730      const pageProxy = this.#pageCache.get(pageIndex);
15731      if (pageProxy.objs.has(id)) {
15732        return;
15733      }
15734      if (pageProxy._intentStates.size === 0) {
15735        imageData?.bitmap?.close();
15736        return;
15737      }
15738      switch (type) {
15739        case "Image":
15740        case "Pattern":
15741          pageProxy.objs.resolve(id, imageData);
15742          break;
15743        default:
15744          throw new Error(`Got unknown object type ${type}`);
15745      }
15746    });
15747    messageHandler.on("DocProgress", data => {
15748      if (this.destroyed) {
15749        return;
15750      }
15751      this.#onProgress(data);
15752    });
15753    messageHandler.on("FetchBinaryData", async data => {
15754      if (this.destroyed) {
15755        throw new Error("Worker was destroyed.");
15756      }
15757      const factory = this[data.type];
15758      if (!factory) {
15759        throw new Error(`${data.type} not initialized, see the \`useWorkerFetch\` parameter.`);
15760      }
15761      return factory.fetch(data);
15762    });
15763  }
15764  getData() {
15765    return this.messageHandler.sendWithPromise("GetData", null);
15766  }
15767  saveDocument() {
15768    if (this.annotationStorage.size <= 0) {
15769      warn("saveDocument called while `annotationStorage` is empty, " + "please use the getData-method instead.");
15770    }
15771    const {
15772      map,
15773      transfer
15774    } = this.annotationStorage.serializable;
15775    return this.messageHandler.sendWithPromise("SaveDocument", {
15776      isPureXfa: !!this._htmlForXfa,
15777      numPages: this._numPages,
15778      annotationStorage: map,
15779      filename: this.#fullReader?.filename ?? null
15780    }, transfer).finally(() => {
15781      this.annotationStorage.resetModified();
15782    });
15783  }
15784  extractPages(pageInfos) {
15785    return this.messageHandler.sendWithPromise("ExtractPages", {
15786      pageInfos
15787    });
15788  }
15789  getPage(pageNumber) {
15790    if (!Number.isInteger(pageNumber) || pageNumber <= 0 || pageNumber > this.#pagesMapper.pagesNumber) {
15791      return Promise.reject(new Error("Invalid page request."));
15792    }
15793    const pageIndex = pageNumber - 1;
15794    const newPageIndex = this.#pagesMapper.getPageId(pageNumber) - 1;
15795    const cachedPromise = this.#pagePromises.get(pageIndex);
15796    if (cachedPromise) {
15797      return cachedPromise;
15798    }
15799    const promise = this.messageHandler.sendWithPromise("GetPage", {
15800      pageIndex: newPageIndex
15801    }).then(pageInfo => {
15802      if (this.destroyed) {
15803        throw new Error("Transport destroyed");
15804      }
15805      if (pageInfo.refStr) {
15806        this.#pageRefCache.set(pageInfo.refStr, newPageIndex);
15807      }
15808      const page = new PDFPageProxy(pageIndex, pageInfo, this, this._params.pdfBug);
15809      this.#pageCache.set(pageIndex, page);
15810      return page;
15811    });
15812    this.#pagePromises.set(pageIndex, promise);
15813    return promise;
15814  }
15815  async getPageIndex(ref) {
15816    if (!isRefProxy(ref)) {
15817      throw new Error("Invalid pageIndex request.");
15818    }
15819    const index = await this.messageHandler.sendWithPromise("GetPageIndex", {
15820      num: ref.num,
15821      gen: ref.gen
15822    });
15823    return this.#pagesMapper.getPageNumber(index + 1) - 1;
15824  }
15825  getAnnotations(pageIndex, intent) {
15826    return this.messageHandler.sendWithPromise("GetAnnotations", {
15827      pageIndex: this.#pagesMapper.getPageId(pageIndex + 1) - 1,
15828      intent
15829    });
15830  }
15831  getFieldObjects() {
15832    return this.#cacheSimpleMethod("GetFieldObjects");
15833  }
15834  hasJSActions() {
15835    return this.#cacheSimpleMethod("HasJSActions");
15836  }
15837  getCalculationOrderIds() {
15838    return this.messageHandler.sendWithPromise("GetCalculationOrderIds", null);
15839  }
15840  getDestinations() {
15841    return this.messageHandler.sendWithPromise("GetDestinations", null);
15842  }
15843  getDestination(id) {
15844    if (typeof id !== "string") {
15845      return Promise.reject(new Error("Invalid destination request."));
15846    }
15847    return this.messageHandler.sendWithPromise("GetDestination", {
15848      id
15849    });
15850  }
15851  getPageLabels() {
15852    return this.messageHandler.sendWithPromise("GetPageLabels", null);
15853  }
15854  getPageLayout() {
15855    return this.messageHandler.sendWithPromise("GetPageLayout", null);
15856  }
15857  getPageMode() {
15858    return this.messageHandler.sendWithPromise("GetPageMode", null);
15859  }
15860  getViewerPreferences() {
15861    return this.messageHandler.sendWithPromise("GetViewerPreferences", null);
15862  }
15863  getOpenAction() {
15864    return this.messageHandler.sendWithPromise("GetOpenAction", null);
15865  }
15866  getAttachments() {
15867    return this.messageHandler.sendWithPromise("GetAttachments", null);
15868  }
15869  getAnnotationsByType(types, pageIndexesToSkip) {
15870    return this.messageHandler.sendWithPromise("GetAnnotationsByType", {
15871      types,
15872      pageIndexesToSkip
15873    });
15874  }
15875  getDocJSActions() {
15876    return this.#cacheSimpleMethod("GetDocJSActions");
15877  }
15878  getPageJSActions(pageIndex) {
15879    return this.messageHandler.sendWithPromise("GetPageJSActions", {
15880      pageIndex: this.#pagesMapper.getPageId(pageIndex + 1) - 1
15881    });
15882  }
15883  getStructTree(pageIndex) {
15884    return this.messageHandler.sendWithPromise("GetStructTree", {
15885      pageIndex: this.#pagesMapper.getPageId(pageIndex + 1) - 1
15886    });
15887  }
15888  getOutline() {
15889    return this.messageHandler.sendWithPromise("GetOutline", null);
15890  }
15891  getOptionalContentConfig(renderingIntent) {
15892    return this.#cacheSimpleMethod("GetOptionalContentConfig").then(data => new OptionalContentConfig(data, renderingIntent));
15893  }
15894  getPermissions() {
15895    return this.messageHandler.sendWithPromise("GetPermissions", null);
15896  }
15897  getMetadata() {
15898    const name = "GetMetadata",
15899      cachedPromise = this.#methodPromises.get(name);
15900    if (cachedPromise) {
15901      return cachedPromise;
15902    }
15903    const promise = this.messageHandler.sendWithPromise(name, null).then(results => ({
15904      info: results[0],
15905      metadata: results[1] ? new Metadata(results[1]) : null,
15906      contentDispositionFilename: this.#fullReader?.filename ?? null,
15907      contentLength: this.#fullReader?.contentLength ?? null,
15908      hasStructTree: results[2]
15909    }));
15910    this.#methodPromises.set(name, promise);
15911    return promise;
15912  }
15913  getMarkInfo() {
15914    return this.messageHandler.sendWithPromise("GetMarkInfo", null);
15915  }
15916  async startCleanup(keepLoadedFonts = false) {
15917    if (this.destroyed) {
15918      return;
15919    }
15920    await this.messageHandler.sendWithPromise("Cleanup", null);
15921    for (const page of this.#pageCache.values()) {
15922      const cleanupSuccessful = page.cleanup();
15923      if (!cleanupSuccessful) {
15924        throw new Error(`startCleanup: Page ${page.pageNumber} is currently rendering.`);
15925      }
15926    }
15927    this.commonObjs.clear();
15928    if (!keepLoadedFonts) {
15929      this.fontLoader.clear();
15930    }
15931    this.#methodPromises.clear();
15932    this.filterFactory.destroy(true);
15933    TextLayer.cleanup();
15934  }
15935  cachedPageNumber(ref) {
15936    if (!isRefProxy(ref)) {
15937      return null;
15938    }
15939    const refStr = ref.gen === 0 ? `${ref.num}R` : `${ref.num}R${ref.gen}`;
15940    const pageIndex = this.#pageRefCache.get(refStr);
15941    return pageIndex >= 0 ? this.#pagesMapper.getPageNumber(pageIndex + 1) : null;
15942  }
15943}
15944class RenderTask {
15945  _internalRenderTask = null;
15946  onContinue = null;
15947  onError = null;
15948  constructor(internalRenderTask) {
15949    this._internalRenderTask = internalRenderTask;
15950  }
15951  get promise() {
15952    return this._internalRenderTask.capability.promise;
15953  }
15954  cancel(extraDelay = 0) {
15955    this._internalRenderTask.cancel(null, extraDelay);
15956  }
15957  get separateAnnots() {
15958    const {
15959      separateAnnots
15960    } = this._internalRenderTask.operatorList;
15961    if (!separateAnnots) {
15962      return false;
15963    }
15964    const {
15965      annotationCanvasMap
15966    } = this._internalRenderTask;
15967    return separateAnnots.form || separateAnnots.canvas && annotationCanvasMap?.size > 0;
15968  }
15969}
15970class InternalRenderTask {
15971  #rAF = null;
15972  static #canvasInUse = new WeakSet();
15973  constructor({
15974    callback,
15975    params,
15976    objs,
15977    commonObjs,
15978    annotationCanvasMap,
15979    operatorList,
15980    pageIndex,
15981    canvasFactory,
15982    filterFactory,
15983    useRequestAnimationFrame = false,
15984    pdfBug = false,
15985    pageColors = null,
15986    enableHWA = false,
15987    operationsFilter = null
15988  }) {
15989    this.callback = callback;
15990    this.params = params;
15991    this.objs = objs;
15992    this.commonObjs = commonObjs;
15993    this.annotationCanvasMap = annotationCanvasMap;
15994    this.operatorListIdx = null;
15995    this.operatorList = operatorList;
15996    this._pageIndex = pageIndex;
15997    this.canvasFactory = canvasFactory;
15998    this.filterFactory = filterFactory;
15999    this._pdfBug = pdfBug;
16000    this.pageColors = pageColors;
16001    this.running = false;
16002    this.graphicsReadyCallback = null;
16003    this.graphicsReady = false;
16004    this._useRequestAnimationFrame = useRequestAnimationFrame === true && typeof window !== "undefined";
16005    this.cancelled = false;
16006    this.capability = Promise.withResolvers();
16007    this.task = new RenderTask(this);
16008    this._cancelBound = this.cancel.bind(this);
16009    this._continueBound = this._continue.bind(this);
16010    this._scheduleNextBound = this._scheduleNext.bind(this);
16011    this._nextBound = this._next.bind(this);
16012    this._canvas = params.canvas;
16013    this._canvasContext = params.canvas ? null : params.canvasContext;
16014    this._enableHWA = enableHWA;
16015    this._dependencyTracker = params.dependencyTracker;
16016    this._operationsFilter = operationsFilter;
16017  }
16018  get completed() {
16019    return this.capability.promise.catch(function () {});
16020  }
16021  initializeGraphics({
16022    transparency = false,
16023    optionalContentConfig
16024  }) {
16025    if (this.cancelled) {
16026      return;
16027    }
16028    if (this._canvas) {
16029      if (InternalRenderTask.#canvasInUse.has(this._canvas)) {
16030        throw new Error("Cannot use the same canvas during multiple render() operations. " + "Use different canvas or ensure previous operations were " + "cancelled or completed.");
16031      }
16032      InternalRenderTask.#canvasInUse.add(this._canvas);
16033    }
16034    if (this._pdfBug && globalThis.StepperManager?.enabled) {
16035      this.stepper = globalThis.StepperManager.create(this._pageIndex);
16036      this.stepper.init(this.operatorList);
16037      this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
16038    }
16039    const {
16040      viewport,
16041      transform,
16042      background,
16043      dependencyTracker
16044    } = this.params;
16045    const canvasContext = this._canvasContext || this._canvas.getContext("2d", {
16046      alpha: false,
16047      willReadFrequently: !this._enableHWA
16048    });
16049    this.gfx = new CanvasGraphics(canvasContext, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, {
16050      optionalContentConfig
16051    }, this.annotationCanvasMap, this.pageColors, dependencyTracker);
16052    this.gfx.beginDrawing({
16053      transform,
16054      viewport,
16055      transparency,
16056      background
16057    });
16058    this.operatorListIdx = 0;
16059    this.graphicsReady = true;
16060    this.graphicsReadyCallback?.();
16061  }
16062  cancel(error = null, extraDelay = 0) {
16063    this.running = false;
vendor: 10,072 bytes, lines 16064-16390
16064    this.cancelled = true;
16065    this.gfx?.endDrawing();
16066    if (this.#rAF) {
16067      window.cancelAnimationFrame(this.#rAF);
16068      this.#rAF = null;
16069    }
16070    InternalRenderTask.#canvasInUse.delete(this._canvas);
16071    error ||= new RenderingCancelledException(`Rendering cancelled, page ${this._pageIndex + 1}`, extraDelay);
16072    this.callback(error);
16073    this.task.onError?.(error);
16074  }
16075  operatorListChanged() {
16076    if (!this.graphicsReady) {
16077      this.graphicsReadyCallback ||= this._continueBound;
16078      return;
16079    }
16080    this.gfx.dependencyTracker?.growOperationsCount(this.operatorList.fnArray.length);
16081    this.stepper?.updateOperatorList(this.operatorList);
16082    if (this.running) {
16083      return;
16084    }
16085    this._continue();
16086  }
16087  _continue() {
16088    this.running = true;
16089    if (this.cancelled) {
16090      return;
16091    }
16092    if (this.task.onContinue) {
16093      this.task.onContinue(this._scheduleNextBound);
16094    } else {
16095      this._scheduleNext();
16096    }
16097  }
16098  _scheduleNext() {
16099    if (this._useRequestAnimationFrame) {
16100      this.#rAF = window.requestAnimationFrame(() => {
16101        this.#rAF = null;
16102        this._nextBound().catch(this._cancelBound);
16103      });
16104    } else {
16105      Promise.resolve().then(this._nextBound).catch(this._cancelBound);
16106    }
16107  }
16108  async _next() {
16109    if (this.cancelled) {
16110      return;
16111    }
16112    this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, this.operatorListIdx, this._continueBound, this.stepper, this._operationsFilter);
16113    if (this.operatorListIdx === this.operatorList.argsArray.length) {
16114      this.running = false;
16115      if (this.operatorList.lastChunk) {
16116        this.gfx.endDrawing();
16117        InternalRenderTask.#canvasInUse.delete(this._canvas);
16118        this.callback();
16119      }
16120    }
16121  }
16122}
16123const version = "5.4.624";
16124const build = "384c6208b";
16125
16126;// ./src/display/editor/color_picker.js
16127
16128
16129
16130class ColorPicker {
16131  #button = null;
16132  #buttonSwatch = null;
16133  #defaultColor;
16134  #dropdown = null;
16135  #dropdownWasFromKeyboard = false;
16136  #isMainColorPicker = false;
16137  #editor = null;
16138  #eventBus;
16139  #openDropdownAC = null;
16140  #uiManager = null;
16141  static #l10nColor = null;
16142  static get _keyboardManager() {
16143    return shadow(this, "_keyboardManager", new KeyboardManager([[["Escape", "mac+Escape"], ColorPicker.prototype._hideDropdownFromKeyboard], [[" ", "mac+ "], ColorPicker.prototype._colorSelectFromKeyboard], [["ArrowDown", "ArrowRight", "mac+ArrowDown", "mac+ArrowRight"], ColorPicker.prototype._moveToNext], [["ArrowUp", "ArrowLeft", "mac+ArrowUp", "mac+ArrowLeft"], ColorPicker.prototype._moveToPrevious], [["Home", "mac+Home"], ColorPicker.prototype._moveToBeginning], [["End", "mac+End"], ColorPicker.prototype._moveToEnd]]));
16144  }
16145  constructor({
16146    editor = null,
16147    uiManager = null
16148  }) {
16149    if (editor) {
16150      this.#isMainColorPicker = false;
16151      this.#editor = editor;
16152    } else {
16153      this.#isMainColorPicker = true;
16154    }
16155    this.#uiManager = editor?._uiManager || uiManager;
16156    this.#eventBus = this.#uiManager._eventBus;
16157    this.#defaultColor = editor?.color?.toUpperCase() || this.#uiManager?.highlightColors.values().next().value || "#FFFF98";
16158    ColorPicker.#l10nColor ||= Object.freeze({
16159      blue: "pdfjs-editor-colorpicker-blue",
16160      green: "pdfjs-editor-colorpicker-green",
16161      pink: "pdfjs-editor-colorpicker-pink",
16162      red: "pdfjs-editor-colorpicker-red",
16163      yellow: "pdfjs-editor-colorpicker-yellow"
16164    });
16165  }
16166  renderButton() {
16167    const button = this.#button = document.createElement("button");
16168    button.className = "colorPicker";
16169    button.tabIndex = "0";
16170    button.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-button");
16171    button.ariaHasPopup = "true";
16172    if (this.#editor) {
16173      button.ariaControls = `${this.#editor.id}_colorpicker_dropdown`;
16174    }
16175    const signal = this.#uiManager._signal;
16176    button.addEventListener("click", this.#openDropdown.bind(this), {
16177      signal
16178    });
16179    button.addEventListener("keydown", this.#keyDown.bind(this), {
16180      signal
16181    });
16182    const swatch = this.#buttonSwatch = document.createElement("span");
16183    swatch.className = "swatch";
16184    swatch.ariaHidden = "true";
16185    swatch.style.backgroundColor = this.#defaultColor;
16186    button.append(swatch);
16187    return button;
16188  }
16189  renderMainDropdown() {
16190    const dropdown = this.#dropdown = this.#getDropdownRoot();
16191    dropdown.ariaOrientation = "horizontal";
16192    dropdown.ariaLabelledBy = "highlightColorPickerLabel";
16193    return dropdown;
16194  }
16195  #getDropdownRoot() {
16196    const div = document.createElement("div");
16197    const signal = this.#uiManager._signal;
16198    div.addEventListener("contextmenu", noContextMenu, {
16199      signal
16200    });
16201    div.className = "dropdown";
16202    div.role = "listbox";
16203    div.ariaMultiSelectable = "false";
16204    div.ariaOrientation = "vertical";
16205    div.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-dropdown");
16206    if (this.#editor) {
16207      div.id = `${this.#editor.id}_colorpicker_dropdown`;
16208    }
16209    for (const [name, color] of this.#uiManager.highlightColors) {
16210      const button = document.createElement("button");
16211      button.tabIndex = "0";
16212      button.role = "option";
16213      button.setAttribute("data-color", color);
16214      button.title = name;
16215      button.setAttribute("data-l10n-id", ColorPicker.#l10nColor[name]);
16216      const swatch = document.createElement("span");
16217      button.append(swatch);
16218      swatch.className = "swatch";
16219      swatch.style.backgroundColor = color;
16220      button.ariaSelected = color === this.#defaultColor;
16221      button.addEventListener("click", this.#colorSelect.bind(this, color), {
16222        signal
16223      });
16224      div.append(button);
16225    }
16226    div.addEventListener("keydown", this.#keyDown.bind(this), {
16227      signal
16228    });
16229    return div;
16230  }
16231  #colorSelect(color, event) {
16232    event.stopPropagation();
16233    this.#eventBus.dispatch("switchannotationeditorparams", {
16234      source: this,
16235      type: AnnotationEditorParamsType.HIGHLIGHT_COLOR,
16236      value: color
16237    });
16238    this.updateColor(color);
16239  }
16240  _colorSelectFromKeyboard(event) {
16241    if (event.target === this.#button) {
16242      this.#openDropdown(event);
16243      return;
16244    }
16245    const color = event.target.getAttribute("data-color");
16246    if (!color) {
16247      return;
16248    }
16249    this.#colorSelect(color, event);
16250  }
16251  _moveToNext(event) {
16252    if (!this.#isDropdownVisible) {
16253      this.#openDropdown(event);
16254      return;
16255    }
16256    if (event.target === this.#button) {
16257      this.#dropdown.firstElementChild?.focus();
16258      return;
16259    }
16260    event.target.nextSibling?.focus();
16261  }
16262  _moveToPrevious(event) {
16263    if (event.target === this.#dropdown?.firstElementChild || event.target === this.#button) {
16264      if (this.#isDropdownVisible) {
16265        this._hideDropdownFromKeyboard();
16266      }
16267      return;
16268    }
16269    if (!this.#isDropdownVisible) {
16270      this.#openDropdown(event);
16271    }
16272    event.target.previousSibling?.focus();
16273  }
16274  _moveToBeginning(event) {
16275    if (!this.#isDropdownVisible) {
16276      this.#openDropdown(event);
16277      return;
16278    }
16279    this.#dropdown.firstElementChild?.focus();
16280  }
16281  _moveToEnd(event) {
16282    if (!this.#isDropdownVisible) {
16283      this.#openDropdown(event);
16284      return;
16285    }
16286    this.#dropdown.lastElementChild?.focus();
16287  }
16288  #keyDown(event) {
16289    ColorPicker._keyboardManager.exec(this, event);
16290  }
16291  #openDropdown(event) {
16292    if (this.#isDropdownVisible) {
16293      this.hideDropdown();
16294      return;
16295    }
16296    this.#dropdownWasFromKeyboard = event.detail === 0;
16297    if (!this.#openDropdownAC) {
16298      this.#openDropdownAC = new AbortController();
16299      window.addEventListener("pointerdown", this.#pointerDown.bind(this), {
16300        signal: this.#uiManager.combinedSignal(this.#openDropdownAC)
16301      });
16302    }
16303    this.#button.ariaExpanded = "true";
16304    if (this.#dropdown) {
16305      this.#dropdown.classList.remove("hidden");
16306      return;
16307    }
16308    const root = this.#dropdown = this.#getDropdownRoot();
16309    this.#button.append(root);
16310  }
16311  #pointerDown(event) {
16312    if (this.#dropdown?.contains(event.target)) {
16313      return;
16314    }
16315    this.hideDropdown();
16316  }
16317  hideDropdown() {
16318    this.#dropdown?.classList.add("hidden");
16319    this.#button.ariaExpanded = "false";
16320    this.#openDropdownAC?.abort();
16321    this.#openDropdownAC = null;
16322  }
16323  get #isDropdownVisible() {
16324    return this.#dropdown && !this.#dropdown.classList.contains("hidden");
16325  }
16326  _hideDropdownFromKeyboard() {
16327    if (this.#isMainColorPicker) {
16328      return;
16329    }
16330    if (!this.#isDropdownVisible) {
16331      this.#editor?.unselect();
16332      return;
16333    }
16334    this.hideDropdown();
16335    this.#button.focus({
16336      preventScroll: true,
16337      focusVisible: this.#dropdownWasFromKeyboard
16338    });
16339  }
16340  updateColor(color) {
16341    if (this.#buttonSwatch) {
16342      this.#buttonSwatch.style.backgroundColor = color;
16343    }
16344    if (!this.#dropdown) {
16345      return;
16346    }
16347    const i = this.#uiManager.highlightColors.values();
16348    for (const child of this.#dropdown.children) {
16349      child.ariaSelected = i.next().value === color.toUpperCase();
16350    }
16351  }
16352  destroy() {
16353    this.#button?.remove();
16354    this.#button = null;
16355    this.#buttonSwatch = null;
16356    this.#dropdown?.remove();
16357    this.#dropdown = null;
16358  }
16359}
16360class BasicColorPicker {
16361  #input = null;
16362  #editor = null;
16363  #uiManager = null;
16364  static #l10nColor = null;
16365  constructor(editor) {
16366    this.#editor = editor;
16367    this.#uiManager = editor._uiManager;
16368    BasicColorPicker.#l10nColor ||= Object.freeze({
16369      freetext: "pdfjs-editor-color-picker-free-text-input",
16370      ink: "pdfjs-editor-color-picker-ink-input"
16371    });
16372  }
16373  renderButton() {
16374    if (this.#input) {
16375      return this.#input;
16376    }
16377    const {
16378      editorType,
16379      colorType,
16380      color
16381    } = this.#editor;
16382    const input = this.#input = document.createElement("input");
16383    input.type = "color";
16384    input.value = color || "#000000";
16385    input.className = "basicColorPicker";
16386    input.tabIndex = 0;
16387    input.setAttribute("data-l10n-id", BasicColorPicker.#l10nColor[editorType]);
16388    input.addEventListener("input", () => {
16389      this.#uiManager.updateParams(colorType, input.value);
16390    }, {
vendor: 17,756 bytes, lines 16391-16987
16391      signal: this.#uiManager._signal
16392    });
16393    return input;
16394  }
16395  update(value) {
16396    if (!this.#input) {
16397      return;
16398    }
16399    this.#input.value = value;
16400  }
16401  destroy() {
16402    this.#input?.remove();
16403    this.#input = null;
16404  }
16405  hideDropdown() {}
16406}
16407
16408;// ./src/shared/scripting_utils.js
16409function makeColorComp(n) {
16410  return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, "0");
16411}
16412function scaleAndClamp(x) {
16413  return Math.max(0, Math.min(255, 255 * x));
16414}
16415class ColorConverters {
16416  static CMYK_G([c, y, m, k]) {
16417    return ["G", 1 - Math.min(1, 0.3 * c + 0.59 * m + 0.11 * y + k)];
16418  }
16419  static G_CMYK([g]) {
16420    return ["CMYK", 0, 0, 0, 1 - g];
16421  }
16422  static G_RGB([g]) {
16423    return ["RGB", g, g, g];
16424  }
16425  static G_rgb([g]) {
16426    g = scaleAndClamp(g);
16427    return [g, g, g];
16428  }
16429  static G_HTML([g]) {
16430    const G = makeColorComp(g);
16431    return `#${G}${G}${G}`;
16432  }
16433  static RGB_G([r, g, b]) {
16434    return ["G", 0.3 * r + 0.59 * g + 0.11 * b];
16435  }
16436  static RGB_rgb(color) {
16437    return color.map(scaleAndClamp);
16438  }
16439  static RGB_HTML(color) {
16440    return `#${color.map(makeColorComp).join("")}`;
16441  }
16442  static T_HTML() {
16443    return "#00000000";
16444  }
16445  static T_rgb() {
16446    return [null];
16447  }
16448  static CMYK_RGB([c, y, m, k]) {
16449    return ["RGB", 1 - Math.min(1, c + k), 1 - Math.min(1, m + k), 1 - Math.min(1, y + k)];
16450  }
16451  static CMYK_rgb([c, y, m, k]) {
16452    return [scaleAndClamp(1 - Math.min(1, c + k)), scaleAndClamp(1 - Math.min(1, m + k)), scaleAndClamp(1 - Math.min(1, y + k))];
16453  }
16454  static CMYK_HTML(components) {
16455    const rgb = this.CMYK_RGB(components).slice(1);
16456    return this.RGB_HTML(rgb);
16457  }
16458  static RGB_CMYK([r, g, b]) {
16459    const c = 1 - r;
16460    const m = 1 - g;
16461    const y = 1 - b;
16462    const k = Math.min(c, m, y);
16463    return ["CMYK", c, m, y, k];
16464  }
16465}
16466const DateFormats = (/* unused pure expression or super */ null && (["m/d", "m/d/yy", "mm/dd/yy", "mm/yy", "d-mmm", "d-mmm-yy", "dd-mmm-yy", "yy-mm-dd", "mmm-yy", "mmmm-yy", "mmm d, yyyy", "mmmm d, yyyy", "m/d/yy h:MM tt", "m/d/yy HH:MM"]));
16467const TimeFormats = (/* unused pure expression or super */ null && (["HH:MM", "h:MM tt", "HH:MM:ss", "h:MM:ss tt"]));
16468
16469;// ./src/display/svg_factory.js
16470
16471
16472class BaseSVGFactory {
16473  create(width, height, skipDimensions = false) {
16474    if (width <= 0 || height <= 0) {
16475      throw new Error("Invalid SVG dimensions");
16476    }
16477    const svg = this._createSVG("svg:svg");
16478    svg.setAttribute("version", "1.1");
16479    if (!skipDimensions) {
16480      svg.setAttribute("width", `${width}px`);
16481      svg.setAttribute("height", `${height}px`);
16482    }
16483    svg.setAttribute("preserveAspectRatio", "none");
16484    svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
16485    return svg;
16486  }
16487  createElement(type) {
16488    if (typeof type !== "string") {
16489      throw new Error("Invalid SVG element type");
16490    }
16491    return this._createSVG(type);
16492  }
16493  _createSVG(type) {
16494    unreachable("Abstract method `_createSVG` called.");
16495  }
16496}
16497class DOMSVGFactory extends BaseSVGFactory {
16498  _createSVG(type) {
16499    return document.createElementNS(SVG_NS, type);
16500  }
16501}
16502
16503;// ./src/display/annotation_layer.js
16504
16505
16506
16507
16508
16509const annotation_layer_DEFAULT_FONT_SIZE = 9;
16510const GetElementsByNameSet = new WeakSet();
16511const TIMEZONE_OFFSET = new Date().getTimezoneOffset() * 60 * 1000;
16512class AnnotationElementFactory {
16513  static create(parameters) {
16514    const subtype = parameters.data.annotationType;
16515    switch (subtype) {
16516      case AnnotationType.LINK:
16517        return new LinkAnnotationElement(parameters);
16518      case AnnotationType.TEXT:
16519        return new TextAnnotationElement(parameters);
16520      case AnnotationType.WIDGET:
16521        const fieldType = parameters.data.fieldType;
16522        switch (fieldType) {
16523          case "Tx":
16524            return new TextWidgetAnnotationElement(parameters);
16525          case "Btn":
16526            if (parameters.data.radioButton) {
16527              return new RadioButtonWidgetAnnotationElement(parameters);
16528            } else if (parameters.data.checkBox) {
16529              return new CheckboxWidgetAnnotationElement(parameters);
16530            }
16531            return new PushButtonWidgetAnnotationElement(parameters);
16532          case "Ch":
16533            return new ChoiceWidgetAnnotationElement(parameters);
16534          case "Sig":
16535            return new SignatureWidgetAnnotationElement(parameters);
16536        }
16537        return new WidgetAnnotationElement(parameters);
16538      case AnnotationType.POPUP:
16539        return new PopupAnnotationElement(parameters);
16540      case AnnotationType.FREETEXT:
16541        return new FreeTextAnnotationElement(parameters);
16542      case AnnotationType.LINE:
16543        return new LineAnnotationElement(parameters);
16544      case AnnotationType.SQUARE:
16545        return new SquareAnnotationElement(parameters);
16546      case AnnotationType.CIRCLE:
16547        return new CircleAnnotationElement(parameters);
16548      case AnnotationType.POLYLINE:
16549        return new PolylineAnnotationElement(parameters);
16550      case AnnotationType.CARET:
16551        return new CaretAnnotationElement(parameters);
16552      case AnnotationType.INK:
16553        return new InkAnnotationElement(parameters);
16554      case AnnotationType.POLYGON:
16555        return new PolygonAnnotationElement(parameters);
16556      case AnnotationType.HIGHLIGHT:
16557        return new HighlightAnnotationElement(parameters);
16558      case AnnotationType.UNDERLINE:
16559        return new UnderlineAnnotationElement(parameters);
16560      case AnnotationType.SQUIGGLY:
16561        return new SquigglyAnnotationElement(parameters);
16562      case AnnotationType.STRIKEOUT:
16563        return new StrikeOutAnnotationElement(parameters);
16564      case AnnotationType.STAMP:
16565        return new StampAnnotationElement(parameters);
16566      case AnnotationType.FILEATTACHMENT:
16567        return new FileAttachmentAnnotationElement(parameters);
16568      default:
16569        return new AnnotationElement(parameters);
16570    }
16571  }
16572}
16573class AnnotationElement {
16574  #updates = null;
16575  #hasBorder = false;
16576  #popupElement = null;
16577  constructor(parameters, {
16578    isRenderable = false,
16579    ignoreBorder = false,
16580    createQuadrilaterals = false
16581  } = {}) {
16582    this.isRenderable = isRenderable;
16583    this.data = parameters.data;
16584    this.layer = parameters.layer;
16585    this.linkService = parameters.linkService;
16586    this.downloadManager = parameters.downloadManager;
16587    this.imageResourcesPath = parameters.imageResourcesPath;
16588    this.renderForms = parameters.renderForms;
16589    this.svgFactory = parameters.svgFactory;
16590    this.annotationStorage = parameters.annotationStorage;
16591    this.enableComment = parameters.enableComment;
16592    this.enableScripting = parameters.enableScripting;
16593    this.hasJSActions = parameters.hasJSActions;
16594    this._fieldObjects = parameters.fieldObjects;
16595    this.parent = parameters.parent;
16596    this.hasOwnCommentButton = false;
16597    if (isRenderable) {
16598      this.contentElement = this.container = this._createContainer(ignoreBorder);
16599    }
16600    if (createQuadrilaterals) {
16601      this._createQuadrilaterals();
16602    }
16603  }
16604  static _hasPopupData({
16605    contentsObj,
16606    richText
16607  }) {
16608    return !!(contentsObj?.str || richText?.str);
16609  }
16610  get _isEditable() {
16611    return this.data.isEditable;
16612  }
16613  get hasPopupData() {
16614    return AnnotationElement._hasPopupData(this.data) || this.enableComment && !!this.commentText;
16615  }
16616  get commentData() {
16617    const {
16618      data
16619    } = this;
16620    const editor = this.annotationStorage?.getEditor(data.id);
16621    if (editor) {
16622      return editor.getData();
16623    }
16624    return data;
16625  }
16626  get hasCommentButton() {
16627    return this.enableComment && this.hasPopupElement;
16628  }
16629  get commentButtonPosition() {
16630    const editor = this.annotationStorage?.getEditor(this.data.id);
16631    if (editor) {
16632      return editor.commentButtonPositionInPage;
16633    }
16634    const {
16635      quadPoints,
16636      inkLists,
16637      rect
16638    } = this.data;
16639    let maxX = -Infinity;
16640    let maxY = -Infinity;
16641    if (quadPoints?.length >= 8) {
16642      for (let i = 0; i < quadPoints.length; i += 8) {
16643        if (quadPoints[i + 1] > maxY) {
16644          maxY = quadPoints[i + 1];
16645          maxX = quadPoints[i + 2];
16646        } else if (quadPoints[i + 1] === maxY) {
16647          maxX = Math.max(maxX, quadPoints[i + 2]);
16648        }
16649      }
16650      return [maxX, maxY];
16651    }
16652    if (inkLists?.length >= 1) {
16653      for (const inkList of inkLists) {
16654        for (let i = 0, ii = inkList.length; i < ii; i += 2) {
16655          if (inkList[i + 1] > maxY) {
16656            maxY = inkList[i + 1];
16657            maxX = inkList[i];
16658          } else if (inkList[i + 1] === maxY) {
16659            maxX = Math.max(maxX, inkList[i]);
16660          }
16661        }
16662      }
16663      if (maxX !== Infinity) {
16664        return [maxX, maxY];
16665      }
16666    }
16667    if (rect) {
16668      return [rect[2], rect[3]];
16669    }
16670    return null;
16671  }
16672  _normalizePoint(point) {
16673    const {
16674      page: {
16675        view
16676      },
16677      viewport: {
16678        rawDims: {
16679          pageWidth,
16680          pageHeight,
16681          pageX,
16682          pageY
16683        }
16684      }
16685    } = this.parent;
16686    point[1] = view[3] - point[1] + view[1];
16687    point[0] = 100 * (point[0] - pageX) / pageWidth;
16688    point[1] = 100 * (point[1] - pageY) / pageHeight;
16689    return point;
16690  }
16691  get commentText() {
16692    const {
16693      data
16694    } = this;
16695    return this.annotationStorage.getRawValue(`${AnnotationEditorPrefix}${data.id}`)?.popup?.contents || data.contentsObj?.str || "";
16696  }
16697  set commentText(text) {
16698    const {
16699      data
16700    } = this;
16701    const popup = {
16702      deleted: !text,
16703      contents: text || ""
16704    };
16705    if (!this.annotationStorage.updateEditor(data.id, {
16706      popup
16707    })) {
16708      this.annotationStorage.setValue(`${AnnotationEditorPrefix}${data.id}`, {
16709        id: data.id,
16710        annotationType: data.annotationType,
16711        page: this.parent.page,
16712        popup,
16713        popupRef: data.popupRef,
16714        modificationDate: new Date()
16715      });
16716    }
16717    if (!text) {
16718      this.removePopup();
16719    }
16720  }
16721  removePopup() {
16722    (this.#popupElement?.popup || this.popup)?.remove();
16723    this.#popupElement = this.popup = null;
16724  }
16725  updateEdited(params) {
16726    if (!this.container) {
16727      return;
16728    }
16729    if (params.rect) {
16730      this.#updates ||= {
16731        rect: this.data.rect.slice(0)
16732      };
16733    }
16734    const {
16735      rect,
16736      popup: newPopup
16737    } = params;
16738    if (rect) {
16739      this.#setRectEdited(rect);
16740    }
16741    let popup = this.#popupElement?.popup || this.popup;
16742    if (!popup && newPopup?.text) {
16743      this._createPopup(newPopup);
16744      popup = this.#popupElement.popup;
16745    }
16746    if (!popup) {
16747      return;
16748    }
16749    popup.updateEdited(params);
16750    if (newPopup?.deleted) {
16751      popup.remove();
16752      this.#popupElement = null;
16753      this.popup = null;
16754    }
16755  }
16756  resetEdited() {
16757    if (!this.#updates) {
16758      return;
16759    }
16760    this.#setRectEdited(this.#updates.rect);
16761    this.#popupElement?.popup.resetEdited();
16762    this.#updates = null;
16763  }
16764  #setRectEdited(rect) {
16765    const {
16766      container: {
16767        style
16768      },
16769      data: {
16770        rect: currentRect,
16771        rotation
16772      },
16773      parent: {
16774        viewport: {
16775          rawDims: {
16776            pageWidth,
16777            pageHeight,
16778            pageX,
16779            pageY
16780          }
16781        }
16782      }
16783    } = this;
16784    currentRect?.splice(0, 4, ...rect);
16785    style.left = `${100 * (rect[0] - pageX) / pageWidth}%`;
16786    style.top = `${100 * (pageHeight - rect[3] + pageY) / pageHeight}%`;
16787    if (rotation === 0) {
16788      style.width = `${100 * (rect[2] - rect[0]) / pageWidth}%`;
16789      style.height = `${100 * (rect[3] - rect[1]) / pageHeight}%`;
16790    } else {
16791      this.setRotation(rotation);
16792    }
16793  }
16794  _createContainer(ignoreBorder) {
16795    const {
16796      data,
16797      parent: {
16798        page,
16799        viewport
16800      }
16801    } = this;
16802    const container = document.createElement("section");
16803    container.setAttribute("data-annotation-id", data.id);
16804    if (!(this instanceof WidgetAnnotationElement) && !(this instanceof LinkAnnotationElement)) {
16805      container.tabIndex = 0;
16806    }
16807    const {
16808      style
16809    } = container;
16810    style.zIndex = this.parent.zIndex;
16811    this.parent.zIndex += 2;
16812    if (data.alternativeText) {
16813      container.title = data.alternativeText;
16814    }
16815    if (data.noRotate) {
16816      container.classList.add("norotate");
16817    }
16818    if (!data.rect || this instanceof PopupAnnotationElement) {
16819      const {
16820        rotation
16821      } = data;
16822      if (!data.hasOwnCanvas && rotation !== 0) {
16823        this.setRotation(rotation, container);
16824      }
16825      return container;
16826    }
16827    const {
16828      width,
16829      height
16830    } = this;
16831    if (!ignoreBorder && data.borderStyle.width > 0) {
16832      style.borderWidth = `${data.borderStyle.width}px`;
16833      const horizontalRadius = data.borderStyle.horizontalCornerRadius;
16834      const verticalRadius = data.borderStyle.verticalCornerRadius;
16835      if (horizontalRadius > 0 || verticalRadius > 0) {
16836        const radius = `calc(${horizontalRadius}px * var(--total-scale-factor)) / calc(${verticalRadius}px * var(--total-scale-factor))`;
16837        style.borderRadius = radius;
16838      } else if (this instanceof RadioButtonWidgetAnnotationElement) {
16839        const radius = `calc(${width}px * var(--total-scale-factor)) / calc(${height}px * var(--total-scale-factor))`;
16840        style.borderRadius = radius;
16841      }
16842      switch (data.borderStyle.style) {
16843        case AnnotationBorderStyleType.SOLID:
16844          style.borderStyle = "solid";
16845          break;
16846        case AnnotationBorderStyleType.DASHED:
16847          style.borderStyle = "dashed";
16848          break;
16849        case AnnotationBorderStyleType.BEVELED:
16850          warn("Unimplemented border style: beveled");
16851          break;
16852        case AnnotationBorderStyleType.INSET:
16853          warn("Unimplemented border style: inset");
16854          break;
16855        case AnnotationBorderStyleType.UNDERLINE:
16856          style.borderBottomStyle = "solid";
16857          break;
16858        default:
16859          break;
16860      }
16861      const borderColor = data.borderColor || null;
16862      if (borderColor) {
16863        this.#hasBorder = true;
16864        style.borderColor = Util.makeHexColor(borderColor[0] | 0, borderColor[1] | 0, borderColor[2] | 0);
16865      } else {
16866        style.borderWidth = 0;
16867      }
16868    }
16869    const rect = 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]]);
16870    const {
16871      pageWidth,
16872      pageHeight,
16873      pageX,
16874      pageY
16875    } = viewport.rawDims;
16876    style.left = `${100 * (rect[0] - pageX) / pageWidth}%`;
16877    style.top = `${100 * (rect[1] - pageY) / pageHeight}%`;
16878    const {
16879      rotation
16880    } = data;
16881    if (data.hasOwnCanvas || rotation === 0) {
16882      style.width = `${100 * width / pageWidth}%`;
16883      style.height = `${100 * height / pageHeight}%`;
16884    } else {
16885      this.setRotation(rotation, container);
16886    }
16887    return container;
16888  }
16889  setRotation(angle, container = this.container) {
16890    if (!this.data.rect) {
16891      return;
16892    }
16893    const {
16894      pageWidth,
16895      pageHeight
16896    } = this.parent.viewport.rawDims;
16897    let {
16898      width,
16899      height
16900    } = this;
16901    if (angle % 180 !== 0) {
16902      [width, height] = [height, width];
16903    }
16904    container.style.width = `${100 * width / pageWidth}%`;
16905    container.style.height = `${100 * height / pageHeight}%`;
16906    container.setAttribute("data-main-rotation", (360 - angle) % 360);
16907  }
16908  get _commonActions() {
16909    const setColor = (jsName, styleName, event) => {
16910      const color = event.detail[jsName];
16911      const colorType = color[0];
16912      const colorArray = color.slice(1);
16913      event.target.style[styleName] = ColorConverters[`${colorType}_HTML`](colorArray);
16914      this.annotationStorage.setValue(this.data.id, {
16915        [styleName]: ColorConverters[`${colorType}_rgb`](colorArray)
16916      });
16917    };
16918    return shadow(this, "_commonActions", {
16919      display: event => {
16920        const {
16921          display
16922        } = event.detail;
16923        const hidden = display % 2 === 1;
16924        this.container.style.visibility = hidden ? "hidden" : "visible";
16925        this.annotationStorage.setValue(this.data.id, {
16926          noView: hidden,
16927          noPrint: display === 1 || display === 2
16928        });
16929      },
16930      print: event => {
16931        this.annotationStorage.setValue(this.data.id, {
16932          noPrint: !event.detail.print
16933        });
16934      },
16935      hidden: event => {
16936        const {
16937          hidden
16938        } = event.detail;
16939        this.container.style.visibility = hidden ? "hidden" : "visible";
16940        this.annotationStorage.setValue(this.data.id, {
16941          noPrint: hidden,
16942          noView: hidden
16943        });
16944      },
16945      focus: event => {
16946        setTimeout(() => event.target.focus({
16947          preventScroll: false
16948        }), 0);
16949      },
16950      userName: event => {
16951        event.target.title = event.detail.userName;
16952      },
16953      readonly: event => {
16954        event.target.disabled = event.detail.readonly;
16955      },
16956      required: event => {
16957        this._setRequired(event.target, event.detail.required);
16958      },
16959      bgColor: event => {
16960        setColor("bgColor", "backgroundColor", event);
16961      },
16962      fillColor: event => {
16963        setColor("fillColor", "backgroundColor", event);
16964      },
16965      fgColor: event => {
16966        setColor("fgColor", "color", event);
16967      },
16968      textColor: event => {
16969        setColor("textColor", "color", event);
16970      },
16971      borderColor: event => {
16972        setColor("borderColor", "borderColor", event);
16973      },
16974      strokeColor: event => {
16975        setColor("strokeColor", "borderColor", event);
16976      },
16977      rotation: event => {
16978        const angle = event.detail.rotation;
16979        this.setRotation(angle);
16980        this.annotationStorage.setValue(this.data.id, {
16981          rotation: angle
16982        });
16983      }
16984    });
16985  }
16986  _dispatchEventFromSandbox(actions, jsEvent) {
16987    const commonActions = this._commonActions;
vendor: 18,371 bytes, lines 16988-17615
16988    for (const name of Object.keys(jsEvent.detail)) {
16989      const action = actions[name] || commonActions[name];
16990      action?.(jsEvent);
16991    }
16992  }
16993  _setDefaultPropertiesFromJS(element) {
16994    if (!this.enableScripting) {
16995      return;
16996    }
16997    const storedData = this.annotationStorage.getRawValue(this.data.id);
16998    if (!storedData) {
16999      return;
17000    }
17001    const commonActions = this._commonActions;
17002    for (const [actionName, detail] of Object.entries(storedData)) {
17003      const action = commonActions[actionName];
17004      if (action) {
17005        const eventProxy = {
17006          detail: {
17007            [actionName]: detail
17008          },
17009          target: element
17010        };
17011        action(eventProxy);
17012        delete storedData[actionName];
17013      }
17014    }
17015  }
17016  _createQuadrilaterals() {
17017    if (!this.container) {
17018      return;
17019    }
17020    const {
17021      quadPoints
17022    } = this.data;
17023    if (!quadPoints) {
17024      return;
17025    }
17026    const [rectBlX, rectBlY, rectTrX, rectTrY] = this.data.rect.map(x => Math.fround(x));
17027    if (quadPoints.length === 8) {
17028      const [trX, trY, blX, blY] = quadPoints.subarray(2, 6);
17029      if (rectTrX === trX && rectTrY === trY && rectBlX === blX && rectBlY === blY) {
17030        return;
17031      }
17032    }
17033    const {
17034      style
17035    } = this.container;
17036    let svgBuffer;
17037    if (this.#hasBorder) {
17038      const {
17039        borderColor,
17040        borderWidth
17041      } = style;
17042      style.borderWidth = 0;
17043      svgBuffer = ["url('data:image/svg+xml;utf8,", `<svg xmlns="http://www.w3.org/2000/svg"`, ` preserveAspectRatio="none" viewBox="0 0 1 1">`, `<g fill="transparent" stroke="${borderColor}" stroke-width="${borderWidth}">`];
17044      this.container.classList.add("hasBorder");
17045    }
17046    const width = rectTrX - rectBlX;
17047    const height = rectTrY - rectBlY;
17048    const {
17049      svgFactory
17050    } = this;
17051    const svg = svgFactory.createElement("svg");
17052    svg.classList.add("quadrilateralsContainer");
17053    svg.setAttribute("width", 0);
17054    svg.setAttribute("height", 0);
17055    svg.role = "none";
17056    const defs = svgFactory.createElement("defs");
17057    svg.append(defs);
17058    const clipPath = svgFactory.createElement("clipPath");
17059    const id = `clippath_${this.data.id}`;
17060    clipPath.setAttribute("id", id);
17061    clipPath.setAttribute("clipPathUnits", "objectBoundingBox");
17062    defs.append(clipPath);
17063    for (let i = 2, ii = quadPoints.length; i < ii; i += 8) {
17064      const trX = quadPoints[i];
17065      const trY = quadPoints[i + 1];
17066      const blX = quadPoints[i + 2];
17067      const blY = quadPoints[i + 3];
17068      const rect = svgFactory.createElement("rect");
17069      const x = (blX - rectBlX) / width;
17070      const y = (rectTrY - trY) / height;
17071      const rectWidth = (trX - blX) / width;
17072      const rectHeight = (trY - blY) / height;
17073      rect.setAttribute("x", x);
17074      rect.setAttribute("y", y);
17075      rect.setAttribute("width", rectWidth);
17076      rect.setAttribute("height", rectHeight);
17077      clipPath.append(rect);
17078      svgBuffer?.push(`<rect vector-effect="non-scaling-stroke" x="${x}" y="${y}" width="${rectWidth}" height="${rectHeight}"/>`);
17079    }
17080    if (this.#hasBorder) {
17081      svgBuffer.push(`</g></svg>')`);
17082      style.backgroundImage = svgBuffer.join("");
17083    }
17084    this.container.append(svg);
17085    this.container.style.clipPath = `url(#${id})`;
17086  }
17087  _createPopup(popupData = null) {
17088    const {
17089      data
17090    } = this;
17091    let contentsObj, modificationDate;
17092    if (popupData) {
17093      contentsObj = {
17094        str: popupData.text
17095      };
17096      modificationDate = popupData.date;
17097    } else {
17098      contentsObj = data.contentsObj;
17099      modificationDate = data.modificationDate;
17100    }
17101    this.#popupElement = new PopupAnnotationElement({
17102      data: {
17103        color: data.color,
17104        titleObj: data.titleObj,
17105        modificationDate,
17106        contentsObj,
17107        richText: data.richText,
17108        parentRect: data.rect,
17109        borderStyle: 0,
17110        id: `popup_${data.id}`,
17111        rotation: data.rotation,
17112        noRotate: true
17113      },
17114      linkService: this.linkService,
17115      parent: this.parent,
17116      elements: [this]
17117    });
17118  }
17119  get hasPopupElement() {
17120    return !!(this.#popupElement || this.popup || this.data.popupRef);
17121  }
17122  get extraPopupElement() {
17123    return this.#popupElement;
17124  }
17125  render() {
17126    unreachable("Abstract method `AnnotationElement.render` called");
17127  }
17128  _getElementsByName(name, skipId = null) {
17129    const fields = [];
17130    if (this._fieldObjects) {
17131      const fieldObj = this._fieldObjects[name];
17132      if (fieldObj) {
17133        for (const {
17134          page,
17135          id,
17136          exportValues
17137        } of fieldObj) {
17138          if (page === -1) {
17139            continue;
17140          }
17141          if (id === skipId) {
17142            continue;
17143          }
17144          const exportValue = typeof exportValues === "string" ? exportValues : null;
17145          const domElement = document.querySelector(`[data-element-id="${id}"]`);
17146          if (domElement && !GetElementsByNameSet.has(domElement)) {
17147            warn(`_getElementsByName - element not allowed: ${id}`);
17148            continue;
17149          }
17150          fields.push({
17151            id,
17152            exportValue,
17153            domElement
17154          });
17155        }
17156      }
17157      return fields;
17158    }
17159    for (const domElement of document.getElementsByName(name)) {
17160      const {
17161        exportValue
17162      } = domElement;
17163      const id = domElement.getAttribute("data-element-id");
17164      if (id === skipId) {
17165        continue;
17166      }
17167      if (!GetElementsByNameSet.has(domElement)) {
17168        continue;
17169      }
17170      fields.push({
17171        id,
17172        exportValue,
17173        domElement
17174      });
17175    }
17176    return fields;
17177  }
17178  show() {
17179    if (this.container) {
17180      this.container.hidden = false;
17181    }
17182    this.popup?.maybeShow();
17183  }
17184  hide() {
17185    if (this.container) {
17186      this.container.hidden = true;
17187    }
17188    this.popup?.forceHide();
17189  }
17190  getElementsToTriggerPopup() {
17191    return this.container;
17192  }
17193  addHighlightArea() {
17194    const triggers = this.getElementsToTriggerPopup();
17195    if (Array.isArray(triggers)) {
17196      for (const element of triggers) {
17197        element.classList.add("highlightArea");
17198      }
17199    } else {
17200      triggers.classList.add("highlightArea");
17201    }
17202  }
17203  _editOnDoubleClick() {
17204    if (!this._isEditable) {
17205      return;
17206    }
17207    const {
17208      annotationEditorType: mode,
17209      data: {
17210        id: editId
17211      }
17212    } = this;
17213    this.container.addEventListener("dblclick", () => {
17214      this.linkService.eventBus?.dispatch("switchannotationeditormode", {
17215        source: this,
17216        mode,
17217        editId,
17218        mustEnterInEditMode: true
17219      });
17220    });
17221  }
17222  get width() {
17223    return this.data.rect[2] - this.data.rect[0];
17224  }
17225  get height() {
17226    return this.data.rect[3] - this.data.rect[1];
17227  }
17228}
17229class EditorAnnotationElement extends AnnotationElement {
17230  constructor(parameters) {
17231    super(parameters, {
17232      isRenderable: true,
17233      ignoreBorder: true
17234    });
17235    this.editor = parameters.editor;
17236  }
17237  render() {
17238    this.container.className = "editorAnnotation";
17239    return this.container;
17240  }
17241  createOrUpdatePopup() {
17242    const {
17243      editor
17244    } = this;
17245    if (!editor.hasComment) {
17246      return;
17247    }
17248    this._createPopup(editor.comment);
17249  }
17250  get hasCommentButton() {
17251    return this.enableComment && this.editor.hasComment;
17252  }
17253  get commentButtonPosition() {
17254    return this.editor.commentButtonPositionInPage;
17255  }
17256  get commentText() {
17257    return this.editor.comment.text;
17258  }
17259  set commentText(text) {
17260    this.editor.comment = text;
17261    if (!text) {
17262      this.removePopup();
17263    }
17264  }
17265  get commentData() {
17266    return this.editor.getData();
17267  }
17268  remove() {
17269    this.parent.removeAnnotation(this.data.id);
17270    this.container.remove();
17271    this.container = null;
17272    this.removePopup();
17273  }
17274}
17275class LinkAnnotationElement extends AnnotationElement {
17276  constructor(parameters, options = null) {
17277    super(parameters, {
17278      isRenderable: true,
17279      ignoreBorder: !!options?.ignoreBorder,
17280      createQuadrilaterals: true
17281    });
17282    this.isTooltipOnly = parameters.data.isTooltipOnly;
17283  }
17284  render() {
17285    const {
17286      data,
17287      linkService
17288    } = this;
17289    const link = document.createElement("a");
17290    link.setAttribute("data-element-id", data.id);
17291    let isBound = false;
17292    if (data.url) {
17293      linkService.addLinkAttributes(link, data.url, data.newWindow);
17294      isBound = true;
17295    } else if (data.action) {
17296      this._bindNamedAction(link, data.action, data.overlaidText);
17297      isBound = true;
17298    } else if (data.attachment) {
17299      this.#bindAttachment(link, data.attachment, data.overlaidText, data.attachmentDest);
17300      isBound = true;
17301    } else if (data.setOCGState) {
17302      this.#bindSetOCGState(link, data.setOCGState, data.overlaidText);
17303      isBound = true;
17304    } else if (data.dest) {
17305      this._bindLink(link, data.dest, data.overlaidText);
17306      isBound = true;
17307    } else {
17308      if (data.actions && (data.actions.Action || data.actions["Mouse Up"] || data.actions["Mouse Down"]) && this.enableScripting && this.hasJSActions) {
17309        this._bindJSAction(link, data);
17310        isBound = true;
17311      }
17312      if (data.resetForm) {
17313        this._bindResetFormAction(link, data.resetForm);
17314        isBound = true;
17315      } else if (this.isTooltipOnly && !isBound) {
17316        this._bindLink(link, "");
17317        isBound = true;
17318      }
17319    }
17320    this.container.classList.add("linkAnnotation");
17321    if (isBound) {
17322      this.contentElement = link;
17323      this.container.append(link);
17324    }
17325    return this.container;
17326  }
17327  #setInternalLink() {
17328    this.container.setAttribute("data-internal-link", "");
17329  }
17330  _bindLink(link, destination, overlaidText = "") {
17331    link.href = this.linkService.getDestinationHash(destination);
17332    link.onclick = () => {
17333      if (destination) {
17334        this.linkService.goToDestination(destination);
17335      }
17336      return false;
17337    };
17338    if (destination || destination === "") {
17339      this.#setInternalLink();
17340    }
17341    if (overlaidText) {
17342      link.title = overlaidText;
17343    }
17344  }
17345  _bindNamedAction(link, action, overlaidText = "") {
17346    link.href = this.linkService.getAnchorUrl("");
17347    link.onclick = () => {
17348      this.linkService.executeNamedAction(action);
17349      return false;
17350    };
17351    if (overlaidText) {
17352      link.title = overlaidText;
17353    }
17354    this.#setInternalLink();
17355  }
17356  #bindAttachment(link, attachment, overlaidText = "", dest = null) {
17357    link.href = this.linkService.getAnchorUrl("");
17358    if (attachment.description) {
17359      link.title = attachment.description;
17360    } else if (overlaidText) {
17361      link.title = overlaidText;
17362    }
17363    link.onclick = () => {
17364      this.downloadManager?.openOrDownloadData(attachment.content, attachment.filename, dest);
17365      return false;
17366    };
17367    this.#setInternalLink();
17368  }
17369  #bindSetOCGState(link, action, overlaidText = "") {
17370    link.href = this.linkService.getAnchorUrl("");
17371    link.onclick = () => {
17372      this.linkService.executeSetOCGState(action);
17373      return false;
17374    };
17375    if (overlaidText) {
17376      link.title = overlaidText;
17377    }
17378    this.#setInternalLink();
17379  }
17380  _bindJSAction(link, data) {
17381    link.href = this.linkService.getAnchorUrl("");
17382    const map = new Map([["Action", "onclick"], ["Mouse Up", "onmouseup"], ["Mouse Down", "onmousedown"]]);
17383    for (const name of Object.keys(data.actions)) {
17384      const jsName = map.get(name);
17385      if (!jsName) {
17386        continue;
17387      }
17388      link[jsName] = () => {
17389        this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
17390          source: this,
17391          detail: {
17392            id: data.id,
17393            name
17394          }
17395        });
17396        return false;
17397      };
17398    }
17399    if (data.overlaidText) {
17400      link.title = data.overlaidText;
17401    }
17402    if (!link.onclick) {
17403      link.onclick = () => false;
17404    }
17405    this.#setInternalLink();
17406  }
17407  _bindResetFormAction(link, resetForm) {
17408    const otherClickAction = link.onclick;
17409    if (!otherClickAction) {
17410      link.href = this.linkService.getAnchorUrl("");
17411    }
17412    this.#setInternalLink();
17413    if (!this._fieldObjects) {
17414      warn(`_bindResetFormAction - "resetForm" action not supported, ` + "ensure that the `fieldObjects` parameter is provided.");
17415      if (!otherClickAction) {
17416        link.onclick = () => false;
17417      }
17418      return;
17419    }
17420    link.onclick = () => {
17421      otherClickAction?.();
17422      const {
17423        fields: resetFormFields,
17424        refs: resetFormRefs,
17425        include
17426      } = resetForm;
17427      const allFields = [];
17428      if (resetFormFields.length !== 0 || resetFormRefs.length !== 0) {
17429        const fieldIds = new Set(resetFormRefs);
17430        for (const fieldName of resetFormFields) {
17431          const fields = this._fieldObjects[fieldName] || [];
17432          for (const {
17433            id
17434          } of fields) {
17435            fieldIds.add(id);
17436          }
17437        }
17438        for (const fields of Object.values(this._fieldObjects)) {
17439          for (const field of fields) {
17440            if (fieldIds.has(field.id) === include) {
17441              allFields.push(field);
17442            }
17443          }
17444        }
17445      } else {
17446        for (const fields of Object.values(this._fieldObjects)) {
17447          allFields.push(...fields);
17448        }
17449      }
17450      const storage = this.annotationStorage;
17451      const allIds = [];
17452      for (const field of allFields) {
17453        const {
17454          id
17455        } = field;
17456        allIds.push(id);
17457        switch (field.type) {
17458          case "text":
17459            {
17460              const value = field.defaultValue || "";
17461              storage.setValue(id, {
17462                value
17463              });
17464              break;
17465            }
17466          case "checkbox":
17467          case "radiobutton":
17468            {
17469              const value = field.defaultValue === field.exportValues;
17470              storage.setValue(id, {
17471                value
17472              });
17473              break;
17474            }
17475          case "combobox":
17476          case "listbox":
17477            {
17478              const value = field.defaultValue || "";
17479              storage.setValue(id, {
17480                value
17481              });
17482              break;
17483            }
17484          default:
17485            continue;
17486        }
17487        const domElement = document.querySelector(`[data-element-id="${id}"]`);
17488        if (!domElement) {
17489          continue;
17490        } else if (!GetElementsByNameSet.has(domElement)) {
17491          warn(`_bindResetFormAction - element not allowed: ${id}`);
17492          continue;
17493        }
17494        domElement.dispatchEvent(new Event("resetform"));
17495      }
17496      if (this.enableScripting) {
17497        this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
17498          source: this,
17499          detail: {
17500            id: "app",
17501            ids: allIds,
17502            name: "ResetForm"
17503          }
17504        });
17505      }
17506      return false;
17507    };
17508  }
17509}
17510class TextAnnotationElement extends AnnotationElement {
17511  constructor(parameters) {
17512    super(parameters, {
17513      isRenderable: true
17514    });
17515  }
17516  render() {
17517    this.container.classList.add("textAnnotation");
17518    const image = document.createElement("img");
17519    image.src = this.imageResourcesPath + "annotation-" + this.data.name.toLowerCase() + ".svg";
17520    image.setAttribute("data-l10n-id", "pdfjs-text-annotation-type");
17521    image.setAttribute("data-l10n-args", JSON.stringify({
17522      type: this.data.name
17523    }));
17524    if (!this.data.popupRef && this.hasPopupData) {
17525      this.hasOwnCommentButton = true;
17526      this._createPopup();
17527    }
17528    this.container.append(image);
17529    return this.container;
17530  }
17531}
17532class WidgetAnnotationElement extends AnnotationElement {
17533  render() {
17534    return this.container;
17535  }
17536  showElementAndHideCanvas(element) {
17537    if (this.data.hasOwnCanvas) {
17538      if (element.previousSibling?.nodeName === "CANVAS") {
17539        element.previousSibling.hidden = true;
17540      }
17541      element.hidden = false;
17542    }
17543  }
17544  _getKeyModifier(event) {
17545    return util_FeatureTest.platform.isMac ? event.metaKey : event.ctrlKey;
17546  }
17547  _setEventListener(element, elementData, baseName, eventName, valueGetter) {
17548    if (baseName.includes("mouse")) {
17549      element.addEventListener(baseName, event => {
17550        this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
17551          source: this,
17552          detail: {
17553            id: this.data.id,
17554            name: eventName,
17555            value: valueGetter(event),
17556            shift: event.shiftKey,
17557            modifier: this._getKeyModifier(event)
17558          }
17559        });
17560      });
17561    } else {
17562      element.addEventListener(baseName, event => {
17563        if (baseName === "blur") {
17564          if (!elementData.focused || !event.relatedTarget) {
17565            return;
17566          }
17567          elementData.focused = false;
17568        } else if (baseName === "focus") {
17569          if (elementData.focused) {
17570            return;
17571          }
17572          elementData.focused = true;
17573        }
17574        if (!valueGetter) {
17575          return;
17576        }
17577        this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
17578          source: this,
17579          detail: {
17580            id: this.data.id,
17581            name: eventName,
17582            value: valueGetter(event)
17583          }
17584        });
17585      });
17586    }
17587  }
17588  _setEventListeners(element, elementData, names, getter) {
17589    for (const [baseName, eventName] of names) {
17590      if (eventName === "Action" || this.data.actions?.[eventName]) {
17591        if (eventName === "Focus" || eventName === "Blur") {
17592          elementData ||= {
17593            focused: false
17594          };
17595        }
17596        this._setEventListener(element, elementData, baseName, eventName, getter);
17597        if (eventName === "Focus" && !this.data.actions?.Blur) {
17598          this._setEventListener(element, elementData, "blur", "Blur", null);
17599        } else if (eventName === "Blur" && !this.data.actions?.Focus) {
17600          this._setEventListener(element, elementData, "focus", "Focus", null);
17601        }
17602      }
17603    }
17604  }
17605  _setBackgroundColor(element) {
17606    const color = this.data.backgroundColor || null;
17607    element.style.backgroundColor = color === null ? "transparent" : Util.makeHexColor(color[0], color[1], color[2]);
17608  }
17609  _setTextStyle(element) {
17610    const TEXT_ALIGNMENT = ["left", "center", "right"];
17611    const {
17612      fontColor
17613    } = this.data.defaultAppearanceData;
17614    const fontSize = this.data.defaultAppearanceData.fontSize || annotation_layer_DEFAULT_FONT_SIZE;
17615    const style = element.style;
vendor: 33,566 bytes, lines 17616-18595
17616    let computedFontSize;
17617    const BORDER_SIZE = 2;
17618    const roundToOneDecimal = x => Math.round(10 * x) / 10;
17619    if (this.data.multiLine) {
17620      const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE);
17621      const numberOfLines = Math.round(height / (LINE_FACTOR * fontSize)) || 1;
17622      const lineHeight = height / numberOfLines;
17623      computedFontSize = Math.min(fontSize, roundToOneDecimal(lineHeight / LINE_FACTOR));
17624    } else {
17625      const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE);
17626      computedFontSize = Math.min(fontSize, roundToOneDecimal(height / LINE_FACTOR));
17627    }
17628    style.fontSize = `calc(${computedFontSize}px * var(--total-scale-factor))`;
17629    style.color = Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]);
17630    if (this.data.textAlignment !== null) {
17631      style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment];
17632    }
17633  }
17634  _setRequired(element, isRequired) {
17635    if (isRequired) {
17636      element.setAttribute("required", true);
17637    } else {
17638      element.removeAttribute("required");
17639    }
17640    element.setAttribute("aria-required", isRequired);
17641  }
17642}
17643class TextWidgetAnnotationElement extends WidgetAnnotationElement {
17644  constructor(parameters) {
17645    const isRenderable = parameters.renderForms || parameters.data.hasOwnCanvas || !parameters.data.hasAppearance && !!parameters.data.fieldValue;
17646    super(parameters, {
17647      isRenderable
17648    });
17649  }
17650  setPropertyOnSiblings(base, key, value, keyInStorage) {
17651    const storage = this.annotationStorage;
17652    for (const element of this._getElementsByName(base.name, base.id)) {
17653      if (element.domElement) {
17654        element.domElement[key] = value;
17655      }
17656      storage.setValue(element.id, {
17657        [keyInStorage]: value
17658      });
17659    }
17660  }
17661  render() {
17662    const storage = this.annotationStorage;
17663    const id = this.data.id;
17664    this.container.classList.add("textWidgetAnnotation");
17665    let element = null;
17666    if (this.renderForms) {
17667      const storedData = storage.getValue(id, {
17668        value: this.data.fieldValue
17669      });
17670      let textContent = storedData.value || "";
17671      const maxLen = storage.getValue(id, {
17672        charLimit: this.data.maxLen
17673      }).charLimit;
17674      if (maxLen && textContent.length > maxLen) {
17675        textContent = textContent.slice(0, maxLen);
17676      }
17677      let fieldFormattedValues = storedData.formattedValue || this.data.textContent?.join("\n") || null;
17678      if (fieldFormattedValues && this.data.comb) {
17679        fieldFormattedValues = fieldFormattedValues.replaceAll(/\s+/g, "");
17680      }
17681      const elementData = {
17682        userValue: textContent,
17683        formattedValue: fieldFormattedValues,
17684        lastCommittedValue: null,
17685        commitKey: 1,
17686        focused: false
17687      };
17688      if (this.data.multiLine) {
17689        element = document.createElement("textarea");
17690        element.textContent = fieldFormattedValues ?? textContent;
17691        if (this.data.doNotScroll) {
17692          element.style.overflowY = "hidden";
17693        }
17694      } else {
17695        element = document.createElement("input");
17696        element.type = this.data.password ? "password" : "text";
17697        element.setAttribute("value", fieldFormattedValues ?? textContent);
17698        if (this.data.doNotScroll) {
17699          element.style.overflowX = "hidden";
17700        }
17701      }
17702      if (this.data.hasOwnCanvas) {
17703        element.hidden = true;
17704      }
17705      GetElementsByNameSet.add(element);
17706      this.contentElement = element;
17707      element.setAttribute("data-element-id", id);
17708      element.disabled = this.data.readOnly;
17709      element.name = this.data.fieldName;
17710      element.tabIndex = 0;
17711      const {
17712        datetimeFormat,
17713        datetimeType,
17714        timeStep
17715      } = this.data;
17716      const hasDateOrTime = !!datetimeType && this.enableScripting;
17717      if (datetimeFormat) {
17718        element.title = datetimeFormat;
17719      }
17720      this._setRequired(element, this.data.required);
17721      if (maxLen) {
17722        element.maxLength = maxLen;
17723      }
17724      element.addEventListener("input", event => {
17725        storage.setValue(id, {
17726          value: event.target.value
17727        });
17728        this.setPropertyOnSiblings(element, "value", event.target.value, "value");
17729        elementData.formattedValue = null;
17730      });
17731      element.addEventListener("resetform", event => {
17732        const defaultValue = this.data.defaultFieldValue ?? "";
17733        element.value = elementData.userValue = defaultValue;
17734        elementData.formattedValue = null;
17735      });
17736      let blurListener = event => {
17737        const {
17738          formattedValue
17739        } = elementData;
17740        if (formattedValue !== null && formattedValue !== undefined) {
17741          event.target.value = formattedValue;
17742        }
17743        event.target.scrollLeft = 0;
17744      };
17745      if (this.enableScripting && this.hasJSActions) {
17746        element.addEventListener("focus", event => {
17747          if (elementData.focused) {
17748            return;
17749          }
17750          const {
17751            target
17752          } = event;
17753          if (hasDateOrTime) {
17754            target.type = datetimeType;
17755            if (timeStep) {
17756              target.step = timeStep;
17757            }
17758          }
17759          if (elementData.userValue) {
17760            const value = elementData.userValue;
17761            if (hasDateOrTime) {
17762              if (datetimeType === "time") {
17763                const date = new Date(value);
17764                const parts = [date.getHours(), date.getMinutes(), date.getSeconds()];
17765                target.value = parts.map(v => v.toString().padStart(2, "0")).join(":");
17766              } else {
17767                target.value = new Date(value - TIMEZONE_OFFSET).toISOString().split(datetimeType === "date" ? "T" : ".", 1)[0];
17768              }
17769            } else {
17770              target.value = value;
17771            }
17772          }
17773          elementData.lastCommittedValue = target.value;
17774          elementData.commitKey = 1;
17775          if (!this.data.actions?.Focus) {
17776            elementData.focused = true;
17777          }
17778        });
17779        element.addEventListener("updatefromsandbox", jsEvent => {
17780          this.showElementAndHideCanvas(jsEvent.target);
17781          const actions = {
17782            value(event) {
17783              elementData.userValue = event.detail.value ?? "";
17784              if (!hasDateOrTime) {
17785                storage.setValue(id, {
17786                  value: elementData.userValue.toString()
17787                });
17788              }
17789              event.target.value = elementData.userValue;
17790            },
17791            formattedValue(event) {
17792              const {
17793                formattedValue
17794              } = event.detail;
17795              elementData.formattedValue = formattedValue;
17796              if (formattedValue !== null && formattedValue !== undefined && event.target !== document.activeElement) {
17797                event.target.value = formattedValue;
17798              }
17799              const data = {
17800                formattedValue
17801              };
17802              if (hasDateOrTime) {
17803                data.value = formattedValue;
17804              }
17805              storage.setValue(id, data);
17806            },
17807            selRange(event) {
17808              event.target.setSelectionRange(...event.detail.selRange);
17809            },
17810            charLimit: event => {
17811              const {
17812                charLimit
17813              } = event.detail;
17814              const {
17815                target
17816              } = event;
17817              if (charLimit === 0) {
17818                target.removeAttribute("maxLength");
17819                return;
17820              }
17821              target.setAttribute("maxLength", charLimit);
17822              let value = elementData.userValue;
17823              if (!value || value.length <= charLimit) {
17824                return;
17825              }
17826              value = value.slice(0, charLimit);
17827              target.value = elementData.userValue = value;
17828              storage.setValue(id, {
17829                value
17830              });
17831              this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
17832                source: this,
17833                detail: {
17834                  id,
17835                  name: "Keystroke",
17836                  value,
17837                  willCommit: true,
17838                  commitKey: 1,
17839                  selStart: target.selectionStart,
17840                  selEnd: target.selectionEnd
17841                }
17842              });
17843            }
17844          };
17845          this._dispatchEventFromSandbox(actions, jsEvent);
17846        });
17847        element.addEventListener("keydown", event => {
17848          elementData.commitKey = 1;
17849          let commitKey = -1;
17850          if (event.key === "Escape") {
17851            commitKey = 0;
17852          } else if (event.key === "Enter" && !this.data.multiLine) {
17853            commitKey = 2;
17854          } else if (event.key === "Tab") {
17855            elementData.commitKey = 3;
17856          }
17857          if (commitKey === -1) {
17858            return;
17859          }
17860          const {
17861            value
17862          } = event.target;
17863          if (elementData.lastCommittedValue === value) {
17864            return;
17865          }
17866          elementData.lastCommittedValue = value;
17867          elementData.userValue = value;
17868          this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
17869            source: this,
17870            detail: {
17871              id,
17872              name: "Keystroke",
17873              value,
17874              willCommit: true,
17875              commitKey,
17876              selStart: event.target.selectionStart,
17877              selEnd: event.target.selectionEnd
17878            }
17879          });
17880        });
17881        const _blurListener = blurListener;
17882        blurListener = null;
17883        element.addEventListener("blur", event => {
17884          if (!elementData.focused || !event.relatedTarget) {
17885            return;
17886          }
17887          if (!this.data.actions?.Blur) {
17888            elementData.focused = false;
17889          }
17890          const {
17891            target
17892          } = event;
17893          let {
17894            value
17895          } = target;
17896          if (hasDateOrTime) {
17897            if (value && datetimeType === "time") {
17898              const parts = value.split(":").map(v => parseInt(v, 10));
17899              value = new Date(2000, 0, 1, parts[0], parts[1], parts[2] || 0).valueOf();
17900              target.step = "";
17901            } else {
17902              if (!value.includes("T")) {
17903                value = `${value}T00:00`;
17904              }
17905              value = new Date(value).valueOf();
17906            }
17907            target.type = "text";
17908          }
17909          elementData.userValue = value;
17910          if (elementData.lastCommittedValue !== value) {
17911            this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
17912              source: this,
17913              detail: {
17914                id,
17915                name: "Keystroke",
17916                value,
17917                willCommit: true,
17918                commitKey: elementData.commitKey,
17919                selStart: event.target.selectionStart,
17920                selEnd: event.target.selectionEnd
17921              }
17922            });
17923          }
17924          _blurListener(event);
17925        });
17926        if (this.data.actions?.Keystroke) {
17927          element.addEventListener("beforeinput", event => {
17928            elementData.lastCommittedValue = null;
17929            const {
17930              data,
17931              target
17932            } = event;
17933            const {
17934              value,
17935              selectionStart,
17936              selectionEnd
17937            } = target;
17938            let selStart = selectionStart,
17939              selEnd = selectionEnd;
17940            switch (event.inputType) {
17941              case "deleteWordBackward":
17942                {
17943                  const match = value.substring(0, selectionStart).match(/\w*[^\w]*$/);
17944                  if (match) {
17945                    selStart -= match[0].length;
17946                  }
17947                  break;
17948                }
17949              case "deleteWordForward":
17950                {
17951                  const match = value.substring(selectionStart).match(/^[^\w]*\w*/);
17952                  if (match) {
17953                    selEnd += match[0].length;
17954                  }
17955                  break;
17956                }
17957              case "deleteContentBackward":
17958                if (selectionStart === selectionEnd) {
17959                  selStart -= 1;
17960                }
17961                break;
17962              case "deleteContentForward":
17963                if (selectionStart === selectionEnd) {
17964                  selEnd += 1;
17965                }
17966                break;
17967            }
17968            event.preventDefault();
17969            this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
17970              source: this,
17971              detail: {
17972                id,
17973                name: "Keystroke",
17974                value,
17975                change: data || "",
17976                willCommit: false,
17977                selStart,
17978                selEnd
17979              }
17980            });
17981          });
17982        }
17983        this._setEventListeners(element, elementData, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.value);
17984      }
17985      if (blurListener) {
17986        element.addEventListener("blur", blurListener);
17987      }
17988      if (this.data.comb) {
17989        const fieldWidth = this.data.rect[2] - this.data.rect[0];
17990        const combWidth = fieldWidth / maxLen;
17991        element.classList.add("comb");
17992        element.style.letterSpacing = `calc(${combWidth}px * var(--total-scale-factor) - 1ch)`;
17993      }
17994    } else {
17995      element = document.createElement("div");
17996      element.textContent = this.data.fieldValue;
17997      element.style.verticalAlign = "middle";
17998      element.style.display = "table-cell";
17999      if (this.data.hasOwnCanvas) {
18000        element.hidden = true;
18001      }
18002    }
18003    this._setTextStyle(element);
18004    this._setBackgroundColor(element);
18005    this._setDefaultPropertiesFromJS(element);
18006    this.container.append(element);
18007    return this.container;
18008  }
18009}
18010class SignatureWidgetAnnotationElement extends WidgetAnnotationElement {
18011  constructor(parameters) {
18012    super(parameters, {
18013      isRenderable: !!parameters.data.hasOwnCanvas
18014    });
18015  }
18016}
18017class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
18018  constructor(parameters) {
18019    super(parameters, {
18020      isRenderable: parameters.renderForms
18021    });
18022  }
18023  render() {
18024    const storage = this.annotationStorage;
18025    const data = this.data;
18026    const id = data.id;
18027    let value = storage.getValue(id, {
18028      value: data.exportValue === data.fieldValue
18029    }).value;
18030    if (typeof value === "string") {
18031      value = value !== "Off";
18032      storage.setValue(id, {
18033        value
18034      });
18035    }
18036    this.container.classList.add("buttonWidgetAnnotation", "checkBox");
18037    const element = document.createElement("input");
18038    GetElementsByNameSet.add(element);
18039    element.setAttribute("data-element-id", id);
18040    element.disabled = data.readOnly;
18041    this._setRequired(element, this.data.required);
18042    element.type = "checkbox";
18043    element.name = data.fieldName;
18044    if (value) {
18045      element.setAttribute("checked", true);
18046    }
18047    element.setAttribute("exportValue", data.exportValue);
18048    element.tabIndex = 0;
18049    element.addEventListener("change", event => {
18050      const {
18051        name,
18052        checked
18053      } = event.target;
18054      for (const checkbox of this._getElementsByName(name, id)) {
18055        const curChecked = checked && checkbox.exportValue === data.exportValue;
18056        if (checkbox.domElement) {
18057          checkbox.domElement.checked = curChecked;
18058        }
18059        storage.setValue(checkbox.id, {
18060          value: curChecked
18061        });
18062      }
18063      storage.setValue(id, {
18064        value: checked
18065      });
18066    });
18067    element.addEventListener("resetform", event => {
18068      const defaultValue = data.defaultFieldValue || "Off";
18069      event.target.checked = defaultValue === data.exportValue;
18070    });
18071    if (this.enableScripting && this.hasJSActions) {
18072      element.addEventListener("updatefromsandbox", jsEvent => {
18073        const actions = {
18074          value(event) {
18075            event.target.checked = event.detail.value !== "Off";
18076            storage.setValue(id, {
18077              value: event.target.checked
18078            });
18079          }
18080        };
18081        this._dispatchEventFromSandbox(actions, jsEvent);
18082      });
18083      this._setEventListeners(element, null, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked);
18084    }
18085    this._setBackgroundColor(element);
18086    this._setDefaultPropertiesFromJS(element);
18087    this.container.append(element);
18088    return this.container;
18089  }
18090}
18091class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
18092  constructor(parameters) {
18093    super(parameters, {
18094      isRenderable: parameters.renderForms
18095    });
18096  }
18097  render() {
18098    this.container.classList.add("buttonWidgetAnnotation", "radioButton");
18099    const storage = this.annotationStorage;
18100    const data = this.data;
18101    const id = data.id;
18102    let value = storage.getValue(id, {
18103      value: data.fieldValue === data.buttonValue
18104    }).value;
18105    if (typeof value === "string") {
18106      value = value !== data.buttonValue;
18107      storage.setValue(id, {
18108        value
18109      });
18110    }
18111    if (value) {
18112      for (const radio of this._getElementsByName(data.fieldName, id)) {
18113        storage.setValue(radio.id, {
18114          value: false
18115        });
18116      }
18117    }
18118    const element = document.createElement("input");
18119    GetElementsByNameSet.add(element);
18120    element.setAttribute("data-element-id", id);
18121    element.disabled = data.readOnly;
18122    this._setRequired(element, this.data.required);
18123    element.type = "radio";
18124    element.name = data.fieldName;
18125    if (value) {
18126      element.setAttribute("checked", true);
18127    }
18128    element.tabIndex = 0;
18129    element.addEventListener("change", event => {
18130      const {
18131        name,
18132        checked
18133      } = event.target;
18134      for (const radio of this._getElementsByName(name, id)) {
18135        storage.setValue(radio.id, {
18136          value: false
18137        });
18138      }
18139      storage.setValue(id, {
18140        value: checked
18141      });
18142    });
18143    element.addEventListener("resetform", event => {
18144      const defaultValue = data.defaultFieldValue;
18145      event.target.checked = defaultValue !== null && defaultValue !== undefined && defaultValue === data.buttonValue;
18146    });
18147    if (this.enableScripting && this.hasJSActions) {
18148      const pdfButtonValue = data.buttonValue;
18149      element.addEventListener("updatefromsandbox", jsEvent => {
18150        const actions = {
18151          value: event => {
18152            const checked = pdfButtonValue === event.detail.value;
18153            for (const radio of this._getElementsByName(event.target.name)) {
18154              const curChecked = checked && radio.id === id;
18155              if (radio.domElement) {
18156                radio.domElement.checked = curChecked;
18157              }
18158              storage.setValue(radio.id, {
18159                value: curChecked
18160              });
18161            }
18162          }
18163        };
18164        this._dispatchEventFromSandbox(actions, jsEvent);
18165      });
18166      this._setEventListeners(element, null, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked);
18167    }
18168    this._setBackgroundColor(element);
18169    this._setDefaultPropertiesFromJS(element);
18170    this.container.append(element);
18171    return this.container;
18172  }
18173}
18174class PushButtonWidgetAnnotationElement extends LinkAnnotationElement {
18175  constructor(parameters) {
18176    super(parameters, {
18177      ignoreBorder: parameters.data.hasAppearance
18178    });
18179  }
18180  render() {
18181    const container = super.render();
18182    container.classList.add("buttonWidgetAnnotation", "pushButton");
18183    const linkElement = container.lastChild;
18184    if (this.enableScripting && this.hasJSActions && linkElement) {
18185      this._setDefaultPropertiesFromJS(linkElement);
18186      linkElement.addEventListener("updatefromsandbox", jsEvent => {
18187        this._dispatchEventFromSandbox({}, jsEvent);
18188      });
18189    }
18190    return container;
18191  }
18192}
18193class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
18194  constructor(parameters) {
18195    super(parameters, {
18196      isRenderable: parameters.renderForms
18197    });
18198  }
18199  render() {
18200    this.container.classList.add("choiceWidgetAnnotation");
18201    const storage = this.annotationStorage;
18202    const id = this.data.id;
18203    const storedData = storage.getValue(id, {
18204      value: this.data.fieldValue
18205    });
18206    const selectElement = document.createElement("select");
18207    GetElementsByNameSet.add(selectElement);
18208    selectElement.setAttribute("data-element-id", id);
18209    selectElement.disabled = this.data.readOnly;
18210    this._setRequired(selectElement, this.data.required);
18211    selectElement.name = this.data.fieldName;
18212    selectElement.tabIndex = 0;
18213    let addAnEmptyEntry = this.data.combo && this.data.options.length > 0;
18214    if (!this.data.combo) {
18215      selectElement.size = this.data.options.length;
18216      if (this.data.multiSelect) {
18217        selectElement.multiple = true;
18218      }
18219    }
18220    selectElement.addEventListener("resetform", event => {
18221      const defaultValue = this.data.defaultFieldValue;
18222      for (const option of selectElement.options) {
18223        option.selected = option.value === defaultValue;
18224      }
18225    });
18226    for (const option of this.data.options) {
18227      const optionElement = document.createElement("option");
18228      optionElement.textContent = option.displayValue;
18229      optionElement.value = option.exportValue;
18230      if (storedData.value.includes(option.exportValue)) {
18231        optionElement.setAttribute("selected", true);
18232        addAnEmptyEntry = false;
18233      }
18234      selectElement.append(optionElement);
18235    }
18236    let removeEmptyEntry = null;
18237    if (addAnEmptyEntry) {
18238      const noneOptionElement = document.createElement("option");
18239      noneOptionElement.value = " ";
18240      noneOptionElement.setAttribute("hidden", true);
18241      noneOptionElement.setAttribute("selected", true);
18242      selectElement.prepend(noneOptionElement);
18243      removeEmptyEntry = () => {
18244        noneOptionElement.remove();
18245        selectElement.removeEventListener("input", removeEmptyEntry);
18246        removeEmptyEntry = null;
18247      };
18248      selectElement.addEventListener("input", removeEmptyEntry);
18249    }
18250    const getValue = isExport => {
18251      const name = isExport ? "value" : "textContent";
18252      const {
18253        options,
18254        multiple
18255      } = selectElement;
18256      if (!multiple) {
18257        return options.selectedIndex === -1 ? null : options[options.selectedIndex][name];
18258      }
18259      return Array.prototype.filter.call(options, option => option.selected).map(option => option[name]);
18260    };
18261    let selectedValues = getValue(false);
18262    const getItems = event => {
18263      const options = event.target.options;
18264      return Array.prototype.map.call(options, option => ({
18265        displayValue: option.textContent,
18266        exportValue: option.value
18267      }));
18268    };
18269    if (this.enableScripting && this.hasJSActions) {
18270      selectElement.addEventListener("updatefromsandbox", jsEvent => {
18271        const actions = {
18272          value(event) {
18273            removeEmptyEntry?.();
18274            const value = event.detail.value;
18275            const values = new Set(Array.isArray(value) ? value : [value]);
18276            for (const option of selectElement.options) {
18277              option.selected = values.has(option.value);
18278            }
18279            storage.setValue(id, {
18280              value: getValue(true)
18281            });
18282            selectedValues = getValue(false);
18283          },
18284          multipleSelection(event) {
18285            selectElement.multiple = true;
18286          },
18287          remove(event) {
18288            const options = selectElement.options;
18289            const index = event.detail.remove;
18290            options[index].selected = false;
18291            selectElement.remove(index);
18292            if (options.length > 0) {
18293              const i = Array.prototype.findIndex.call(options, option => option.selected);
18294              if (i === -1) {
18295                options[0].selected = true;
18296              }
18297            }
18298            storage.setValue(id, {
18299              value: getValue(true),
18300              items: getItems(event)
18301            });
18302            selectedValues = getValue(false);
18303          },
18304          clear(event) {
18305            while (selectElement.length !== 0) {
18306              selectElement.remove(0);
18307            }
18308            storage.setValue(id, {
18309              value: null,
18310              items: []
18311            });
18312            selectedValues = getValue(false);
18313          },
18314          insert(event) {
18315            const {
18316              index,
18317              displayValue,
18318              exportValue
18319            } = event.detail.insert;
18320            const selectChild = selectElement.children[index];
18321            const optionElement = document.createElement("option");
18322            optionElement.textContent = displayValue;
18323            optionElement.value = exportValue;
18324            if (selectChild) {
18325              selectChild.before(optionElement);
18326            } else {
18327              selectElement.append(optionElement);
18328            }
18329            storage.setValue(id, {
18330              value: getValue(true),
18331              items: getItems(event)
18332            });
18333            selectedValues = getValue(false);
18334          },
18335          items(event) {
18336            const {
18337              items
18338            } = event.detail;
18339            while (selectElement.length !== 0) {
18340              selectElement.remove(0);
18341            }
18342            for (const item of items) {
18343              const {
18344                displayValue,
18345                exportValue
18346              } = item;
18347              const optionElement = document.createElement("option");
18348              optionElement.textContent = displayValue;
18349              optionElement.value = exportValue;
18350              selectElement.append(optionElement);
18351            }
18352            if (selectElement.options.length > 0) {
18353              selectElement.options[0].selected = true;
18354            }
18355            storage.setValue(id, {
18356              value: getValue(true),
18357              items: getItems(event)
18358            });
18359            selectedValues = getValue(false);
18360          },
18361          indices(event) {
18362            const indices = new Set(event.detail.indices);
18363            for (const option of event.target.options) {
18364              option.selected = indices.has(option.index);
18365            }
18366            storage.setValue(id, {
18367              value: getValue(true)
18368            });
18369            selectedValues = getValue(false);
18370          },
18371          editable(event) {
18372            event.target.disabled = !event.detail.editable;
18373          }
18374        };
18375        this._dispatchEventFromSandbox(actions, jsEvent);
18376      });
18377      selectElement.addEventListener("input", event => {
18378        const exportValue = getValue(true);
18379        const change = getValue(false);
18380        storage.setValue(id, {
18381          value: exportValue
18382        });
18383        event.preventDefault();
18384        this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
18385          source: this,
18386          detail: {
18387            id,
18388            name: "Keystroke",
18389            value: selectedValues,
18390            change,
18391            changeEx: exportValue,
18392            willCommit: false,
18393            commitKey: 1,
18394            keyDown: false
18395          }
18396        });
18397      });
18398      this._setEventListeners(selectElement, null, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"], ["input", "Action"], ["input", "Validate"]], event => event.target.value);
18399    } else {
18400      selectElement.addEventListener("input", function (event) {
18401        storage.setValue(id, {
18402          value: getValue(true)
18403        });
18404      });
18405    }
18406    if (this.data.combo) {
18407      this._setTextStyle(selectElement);
18408    } else {}
18409    this._setBackgroundColor(selectElement);
18410    this._setDefaultPropertiesFromJS(selectElement);
18411    this.container.append(selectElement);
18412    return this.container;
18413  }
18414}
18415class PopupAnnotationElement extends AnnotationElement {
18416  constructor(parameters) {
18417    const {
18418      data,
18419      elements,
18420      parent
18421    } = parameters;
18422    const hasCommentManager = !!parent._commentManager;
18423    super(parameters, {
18424      isRenderable: !hasCommentManager && AnnotationElement._hasPopupData(data)
18425    });
18426    this.elements = elements;
18427    if (hasCommentManager && AnnotationElement._hasPopupData(data)) {
18428      const popup = this.popup = this.#createPopup();
18429      for (const element of elements) {
18430        element.popup = popup;
18431      }
18432    } else {
18433      this.popup = null;
18434    }
18435  }
18436  #createPopup() {
18437    return new PopupElement({
18438      container: this.container,
18439      color: this.data.color,
18440      titleObj: this.data.titleObj,
18441      modificationDate: this.data.modificationDate || this.data.creationDate,
18442      contentsObj: this.data.contentsObj,
18443      richText: this.data.richText,
18444      rect: this.data.rect,
18445      parentRect: this.data.parentRect || null,
18446      parent: this.parent,
18447      elements: this.elements,
18448      open: this.data.open,
18449      commentManager: this.parent._commentManager
18450    });
18451  }
18452  render() {
18453    const {
18454      container
18455    } = this;
18456    container.classList.add("popupAnnotation");
18457    container.role = "comment";
18458    const popup = this.popup = this.#createPopup();
18459    const elementIds = [];
18460    for (const element of this.elements) {
18461      element.popup = popup;
18462      element.container.ariaHasPopup = "dialog";
18463      elementIds.push(element.data.id);
18464      element.addHighlightArea();
18465    }
18466    this.container.setAttribute("aria-controls", elementIds.map(id => `${AnnotationPrefix}${id}`).join(","));
18467    return this.container;
18468  }
18469}
18470class PopupElement {
18471  #commentManager = null;
18472  #boundKeyDown = this.#keyDown.bind(this);
18473  #boundHide = this.#hide.bind(this);
18474  #boundShow = this.#show.bind(this);
18475  #boundToggle = this.#toggle.bind(this);
18476  #color = null;
18477  #container = null;
18478  #contentsObj = null;
18479  #dateObj = null;
18480  #elements = null;
18481  #parent = null;
18482  #parentRect = null;
18483  #pinned = false;
18484  #popup = null;
18485  #popupAbortController = null;
18486  #position = null;
18487  #commentButton = null;
18488  #commentButtonPosition = null;
18489  #popupPosition = null;
18490  #rect = null;
18491  #richText = null;
18492  #titleObj = null;
18493  #updates = null;
18494  #wasVisible = false;
18495  #firstElement = null;
18496  #commentText = null;
18497  constructor({
18498    container,
18499    color,
18500    elements,
18501    titleObj,
18502    modificationDate,
18503    contentsObj,
18504    richText,
18505    parent,
18506    rect,
18507    parentRect,
18508    open,
18509    commentManager = null
18510  }) {
18511    this.#container = container;
18512    this.#titleObj = titleObj;
18513    this.#contentsObj = contentsObj;
18514    this.#richText = richText;
18515    this.#parent = parent;
18516    this.#color = color;
18517    this.#rect = rect;
18518    this.#parentRect = parentRect;
18519    this.#elements = elements;
18520    this.#commentManager = commentManager;
18521    this.#firstElement = elements[0];
18522    this.#dateObj = PDFDateString.toDateObject(modificationDate);
18523    this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup());
18524    if (!commentManager) {
18525      this.#addEventListeners();
18526      this.#container.hidden = true;
18527      if (open) {
18528        this.#toggle();
18529      }
18530    }
18531  }
18532  #addEventListeners() {
18533    if (this.#popupAbortController) {
18534      return;
18535    }
18536    this.#popupAbortController = new AbortController();
18537    const {
18538      signal
18539    } = this.#popupAbortController;
18540    for (const element of this.trigger) {
18541      element.addEventListener("click", this.#boundToggle, {
18542        signal
18543      });
18544      element.addEventListener("pointerenter", this.#boundShow, {
18545        signal
18546      });
18547      element.addEventListener("pointerleave", this.#boundHide, {
18548        signal
18549      });
18550      element.classList.add("popupTriggerArea");
18551    }
18552    for (const element of this.#elements) {
18553      element.container?.addEventListener("keydown", this.#boundKeyDown, {
18554        signal
18555      });
18556    }
18557  }
18558  #setCommentButtonPosition() {
18559    const element = this.#elements.find(e => e.hasCommentButton);
18560    if (!element) {
18561      return;
18562    }
18563    this.#commentButtonPosition = element._normalizePoint(element.commentButtonPosition);
18564  }
18565  renderCommentButton() {
18566    if (this.#commentButton) {
18567      if (!this.#commentButton.parentNode) {
18568        this.#firstElement.container.after(this.#commentButton);
18569      }
18570      return;
18571    }
18572    if (!this.#commentButtonPosition) {
18573      this.#setCommentButtonPosition();
18574    }
18575    if (!this.#commentButtonPosition) {
18576      return;
18577    }
18578    const {
18579      signal
18580    } = this.#popupAbortController = new AbortController();
18581    const hasOwnButton = this.#firstElement.hasOwnCommentButton;
18582    const togglePopup = () => {
18583      this.#commentManager.toggleCommentPopup(this, true, undefined, !hasOwnButton);
18584    };
18585    const showPopup = () => {
18586      this.#commentManager.toggleCommentPopup(this, false, true, !hasOwnButton);
18587    };
18588    const hidePopup = () => {
18589      this.#commentManager.toggleCommentPopup(this, false, false);
18590    };
18591    if (!hasOwnButton) {
18592      const button = this.#commentButton = document.createElement("button");
18593      button.className = "annotationCommentButton";
18594      const parentContainer = this.#firstElement.container;
18595      button.style.zIndex = parentContainer.style.zIndex
vendor: 10,950 bytes, lines 18595-18992
18595 + 1;
18596      button.tabIndex = 0;
18597      button.ariaHasPopup = "dialog";
18598      button.ariaControls = "commentPopup";
18599      button.setAttribute("data-l10n-id", "pdfjs-show-comment-button");
18600      this.#updateColor();
18601      this.#updateCommentButtonPosition();
18602      button.addEventListener("keydown", this.#boundKeyDown, {
18603        signal
18604      });
18605      button.addEventListener("click", togglePopup, {
18606        signal
18607      });
18608      button.addEventListener("pointerenter", showPopup, {
18609        signal
18610      });
18611      button.addEventListener("pointerleave", hidePopup, {
18612        signal
18613      });
18614      parentContainer.after(button);
18615    } else {
18616      this.#commentButton = this.#firstElement.container;
18617      for (const element of this.trigger) {
18618        element.ariaHasPopup = "dialog";
18619        element.ariaControls = "commentPopup";
18620        element.addEventListener("keydown", this.#boundKeyDown, {
18621          signal
18622        });
18623        element.addEventListener("click", togglePopup, {
18624          signal
18625        });
18626        element.addEventListener("pointerenter", showPopup, {
18627          signal
18628        });
18629        element.addEventListener("pointerleave", hidePopup, {
18630          signal
18631        });
18632        element.classList.add("popupTriggerArea");
18633      }
18634    }
18635  }
18636  #updateCommentButtonPosition() {
18637    if (this.#firstElement.extraPopupElement && !this.#firstElement.editor) {
18638      return;
18639    }
18640    if (!this.#commentButton) {
18641      this.renderCommentButton();
18642    }
18643    const [x, y] = this.#commentButtonPosition;
18644    const {
18645      style
18646    } = this.#commentButton;
18647    style.left = `calc(${x}%)`;
18648    style.top = `calc(${y}% - var(--comment-button-dim))`;
18649  }
18650  #updateColor() {
18651    if (this.#firstElement.extraPopupElement) {
18652      return;
18653    }
18654    if (!this.#commentButton) {
18655      this.renderCommentButton();
18656    }
18657    this.#commentButton.style.backgroundColor = this.commentButtonColor || "";
18658  }
18659  get commentButtonColor() {
18660    const {
18661      color,
18662      opacity
18663    } = this.#firstElement.commentData;
18664    if (!color) {
18665      return null;
18666    }
18667    return this.#parent._commentManager.makeCommentColor(color, opacity);
18668  }
18669  focusCommentButton() {
18670    setTimeout(() => {
18671      this.#commentButton?.focus();
18672    }, 0);
18673  }
18674  getData() {
18675    const {
18676      richText,
18677      color,
18678      opacity,
18679      creationDate,
18680      modificationDate
18681    } = this.#firstElement.commentData;
18682    return {
18683      contentsObj: {
18684        str: this.comment
18685      },
18686      richText,
18687      color,
18688      opacity,
18689      creationDate,
18690      modificationDate
18691    };
18692  }
18693  get elementBeforePopup() {
18694    return this.#commentButton;
18695  }
18696  get comment() {
18697    this.#commentText ||= this.#firstElement.commentText;
18698    return this.#commentText;
18699  }
18700  set comment(text) {
18701    if (text === this.comment) {
18702      return;
18703    }
18704    this.#firstElement.commentText = this.#commentText = text;
18705  }
18706  focus() {
18707    this.#firstElement.container?.focus();
18708  }
18709  get parentBoundingClientRect() {
18710    return this.#firstElement.layer.getBoundingClientRect();
18711  }
18712  setCommentButtonStates({
18713    selected,
18714    hasPopup
18715  }) {
18716    if (!this.#commentButton) {
18717      return;
18718    }
18719    this.#commentButton.classList.toggle("selected", selected);
18720    this.#commentButton.ariaExpanded = hasPopup;
18721  }
18722  setSelectedCommentButton(selected) {
18723    this.#commentButton.classList.toggle("selected", selected);
18724  }
18725  get commentPopupPosition() {
18726    if (this.#popupPosition) {
18727      return this.#popupPosition;
18728    }
18729    const {
18730      x,
18731      y,
18732      height
18733    } = this.#commentButton.getBoundingClientRect();
18734    const {
18735      x: parentX,
18736      y: parentY,
18737      width: parentWidth,
18738      height: parentHeight
18739    } = this.#firstElement.layer.getBoundingClientRect();
18740    return [(x - parentX) / parentWidth, (y + height - parentY) / parentHeight];
18741  }
18742  set commentPopupPosition(pos) {
18743    this.#popupPosition = pos;
18744  }
18745  hasDefaultPopupPosition() {
18746    return this.#popupPosition === null;
18747  }
18748  get commentButtonPosition() {
18749    return this.#commentButtonPosition;
18750  }
18751  get commentButtonWidth() {
18752    return this.#commentButton.getBoundingClientRect().width / this.parentBoundingClientRect.width;
18753  }
18754  editComment(options) {
18755    const [posX, posY] = this.#popupPosition || this.commentButtonPosition.map(x => x / 100);
18756    const parentDimensions = this.parentBoundingClientRect;
18757    const {
18758      x: parentX,
18759      y: parentY,
18760      width: parentWidth,
18761      height: parentHeight
18762    } = parentDimensions;
18763    this.#commentManager.showDialog(null, this, parentX + posX * parentWidth, parentY + posY * parentHeight, {
18764      ...options,
18765      parentDimensions
18766    });
18767  }
18768  render() {
18769    if (this.#popup) {
18770      return;
18771    }
18772    const popup = this.#popup = document.createElement("div");
18773    popup.className = "popup";
18774    if (this.#color) {
18775      const baseColor = popup.style.outlineColor = Util.makeHexColor(...this.#color);
18776      popup.style.backgroundColor = `color-mix(in srgb, ${baseColor} 30%, white)`;
18777    }
18778    const header = document.createElement("span");
18779    header.className = "header";
18780    if (this.#titleObj?.str) {
18781      const title = document.createElement("span");
18782      title.className = "title";
18783      header.append(title);
18784      ({
18785        dir: title.dir,
18786        str: title.textContent
18787      } = this.#titleObj);
18788    }
18789    popup.append(header);
18790    if (this.#dateObj) {
18791      const modificationDate = document.createElement("time");
18792      modificationDate.className = "popupDate";
18793      modificationDate.setAttribute("data-l10n-id", "pdfjs-annotation-date-time-string");
18794      modificationDate.setAttribute("data-l10n-args", JSON.stringify({
18795        dateObj: this.#dateObj.valueOf()
18796      }));
18797      modificationDate.dateTime = this.#dateObj.toISOString();
18798      header.append(modificationDate);
18799    }
18800    renderRichText({
18801      html: this.#html || this.#contentsObj.str,
18802      dir: this.#contentsObj?.dir,
18803      className: "popupContent"
18804    }, popup);
18805    this.#container.append(popup);
18806  }
18807  get #html() {
18808    const richText = this.#richText;
18809    const contentsObj = this.#contentsObj;
18810    if (richText?.str && (!contentsObj?.str || contentsObj.str === richText.str)) {
18811      return this.#richText.html || null;
18812    }
18813    return null;
18814  }
18815  get #fontSize() {
18816    return this.#html?.attributes?.style?.fontSize || 0;
18817  }
18818  get #fontColor() {
18819    return this.#html?.attributes?.style?.color || null;
18820  }
18821  #makePopupContent(text) {
18822    const popupLines = [];
18823    const popupContent = {
18824      str: text,
18825      html: {
18826        name: "div",
18827        attributes: {
18828          dir: "auto"
18829        },
18830        children: [{
18831          name: "p",
18832          children: popupLines
18833        }]
18834      }
18835    };
18836    const lineAttributes = {
18837      style: {
18838        color: this.#fontColor,
18839        fontSize: this.#fontSize ? `calc(${this.#fontSize}px * var(--total-scale-factor))` : ""
18840      }
18841    };
18842    for (const line of text.split("\n")) {
18843      popupLines.push({
18844        name: "span",
18845        value: line,
18846        attributes: lineAttributes
18847      });
18848    }
18849    return popupContent;
18850  }
18851  #keyDown(event) {
18852    if (event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) {
18853      return;
18854    }
18855    if (event.key === "Enter" || event.key === "Escape" && this.#pinned) {
18856      this.#toggle();
18857    }
18858  }
18859  updateEdited({
18860    rect,
18861    popup,
18862    deleted
18863  }) {
18864    if (this.#commentManager) {
18865      if (deleted) {
18866        this.remove();
18867        this.#commentText = null;
18868      } else if (popup) {
18869        if (popup.deleted) {
18870          this.remove();
18871        } else {
18872          this.#updateColor();
18873          this.#commentText = popup.text;
18874        }
18875      }
18876      if (rect) {
18877        this.#commentButtonPosition = null;
18878        this.#setCommentButtonPosition();
18879        this.#updateCommentButtonPosition();
18880      }
18881      return;
18882    }
18883    if (deleted || popup?.deleted) {
18884      this.remove();
18885      return;
18886    }
18887    this.#addEventListeners();
18888    this.#updates ||= {
18889      contentsObj: this.#contentsObj,
18890      richText: this.#richText
18891    };
18892    if (rect) {
18893      this.#position = null;
18894    }
18895    if (popup && popup.text) {
18896      this.#richText = this.#makePopupContent(popup.text);
18897      this.#dateObj = PDFDateString.toDateObject(popup.date);
18898      this.#contentsObj = null;
18899    }
18900    this.#popup?.remove();
18901    this.#popup = null;
18902  }
18903  resetEdited() {
18904    if (!this.#updates) {
18905      return;
18906    }
18907    ({
18908      contentsObj: this.#contentsObj,
18909      richText: this.#richText
18910    } = this.#updates);
18911    this.#updates = null;
18912    this.#popup?.remove();
18913    this.#popup = null;
18914    this.#position = null;
18915  }
18916  remove() {
18917    this.#popupAbortController?.abort();
18918    this.#popupAbortController = null;
18919    this.#popup?.remove();
18920    this.#popup = null;
18921    this.#wasVisible = false;
18922    this.#pinned = false;
18923    this.#commentButton?.remove();
18924    this.#commentButton = null;
18925    if (this.trigger) {
18926      for (const element of this.trigger) {
18927        element.classList.remove("popupTriggerArea");
18928      }
18929    }
18930  }
18931  #setPosition() {
18932    if (this.#position !== null) {
18933      return;
18934    }
18935    const {
18936      page: {
18937        view
18938      },
18939      viewport: {
18940        rawDims: {
18941          pageWidth,
18942          pageHeight,
18943          pageX,
18944          pageY
18945        }
18946      }
18947    } = this.#parent;
18948    let useParentRect = !!this.#parentRect;
18949    let rect = useParentRect ? this.#parentRect : this.#rect;
18950    for (const element of this.#elements) {
18951      if (!rect || Util.intersect(element.data.rect, rect) !== null) {
18952        rect = element.data.rect;
18953        useParentRect = true;
18954        break;
18955      }
18956    }
18957    const normalizedRect = Util.normalizeRect([rect[0], view[3] - rect[1] + view[1], rect[2], view[3] - rect[3] + view[1]]);
18958    const HORIZONTAL_SPACE_AFTER_ANNOTATION = 5;
18959    const parentWidth = useParentRect ? rect[2] - rect[0] + HORIZONTAL_SPACE_AFTER_ANNOTATION : 0;
18960    const popupLeft = normalizedRect[0] + parentWidth;
18961    const popupTop = normalizedRect[1];
18962    this.#position = [100 * (popupLeft - pageX) / pageWidth, 100 * (popupTop - pageY) / pageHeight];
18963    const {
18964      style
18965    } = this.#container;
18966    style.left = `${this.#position[0]}%`;
18967    style.top = `${this.#position[1]}%`;
18968  }
18969  #toggle() {
18970    if (this.#commentManager) {
18971      this.#commentManager.toggleCommentPopup(this, false);
18972      return;
18973    }
18974    this.#pinned = !this.#pinned;
18975    if (this.#pinned) {
18976      this.#show();
18977      this.#container.addEventListener("click", this.#boundToggle);
18978      this.#container.addEventListener("keydown", this.#boundKeyDown);
18979    } else {
18980      this.#hide();
18981      this.#container.removeEventListener("click", this.#boundToggle);
18982      this.#container.removeEventListener("keydown", this.#boundKeyDown);
18983    }
18984  }
18985  #show() {
18986    if (!this.#popup) {
18987      this.render();
18988    }
18989    if (!this.isVisible) {
18990      this.#setPosition();
18991      this.#container.hidden = false;
18992      this.#container.style.zIndex = parseInt(this.#container.style.zIndex
vendor: 715 bytes, lines 18992-19023
18992) + 1000;
18993    } else if (this.#pinned) {
18994      this.#container.classList.add("focused");
18995    }
18996  }
18997  #hide() {
18998    this.#container.classList.remove("focused");
18999    if (this.#pinned || !this.isVisible) {
19000      return;
19001    }
19002    this.#container.hidden = true;
19003    this.#container.style.zIndex = parseInt(this.#container.style.zIndex) - 1000;
19004  }
19005  forceHide() {
19006    this.#wasVisible = this.isVisible;
19007    if (!this.#wasVisible) {
19008      return;
19009    }
19010    this.#container.hidden = true;
19011  }
19012  maybeShow() {
19013    if (this.#commentManager) {
19014      return;
19015    }
19016    this.#addEventListeners();
19017    if (!this.#wasVisible) {
19018      return;
19019    }
19020    if (!this.#popup) {
19021      this.#show();
19022    }
19023    this.#wasVisible = false;
vendor: 13,084 bytes, lines 19024-19480
19024    this.#container.hidden = false;
19025  }
19026  get isVisible() {
19027    if (this.#commentManager) {
19028      return false;
19029    }
19030    return this.#container.hidden === false;
19031  }
19032}
19033class FreeTextAnnotationElement extends AnnotationElement {
19034  constructor(parameters) {
19035    super(parameters, {
19036      isRenderable: true,
19037      ignoreBorder: true
19038    });
19039    this.textContent = parameters.data.textContent;
19040    this.textPosition = parameters.data.textPosition;
19041    this.annotationEditorType = AnnotationEditorType.FREETEXT;
19042  }
19043  render() {
19044    this.container.classList.add("freeTextAnnotation");
19045    if (this.textContent) {
19046      const content = this.contentElement = document.createElement("div");
19047      content.classList.add("annotationTextContent");
19048      content.setAttribute("role", "comment");
19049      for (const line of this.textContent) {
19050        const lineSpan = document.createElement("span");
19051        lineSpan.textContent = line;
19052        content.append(lineSpan);
19053      }
19054      this.container.append(content);
19055    }
19056    if (!this.data.popupRef && this.hasPopupData) {
19057      this.hasOwnCommentButton = true;
19058      this._createPopup();
19059    }
19060    this._editOnDoubleClick();
19061    return this.container;
19062  }
19063}
19064class LineAnnotationElement extends AnnotationElement {
19065  #line = null;
19066  constructor(parameters) {
19067    super(parameters, {
19068      isRenderable: true,
19069      ignoreBorder: true
19070    });
19071  }
19072  render() {
19073    this.container.classList.add("lineAnnotation");
19074    const {
19075      data,
19076      width,
19077      height
19078    } = this;
19079    const svg = this.svgFactory.create(width, height, true);
19080    const line = this.#line = this.svgFactory.createElement("svg:line");
19081    line.setAttribute("x1", data.rect[2] - data.lineCoordinates[0]);
19082    line.setAttribute("y1", data.rect[3] - data.lineCoordinates[1]);
19083    line.setAttribute("x2", data.rect[2] - data.lineCoordinates[2]);
19084    line.setAttribute("y2", data.rect[3] - data.lineCoordinates[3]);
19085    line.setAttribute("stroke-width", data.borderStyle.width || 1);
19086    line.setAttribute("stroke", "transparent");
19087    line.setAttribute("fill", "transparent");
19088    svg.append(line);
19089    this.container.append(svg);
19090    if (!data.popupRef && this.hasPopupData) {
19091      this.hasOwnCommentButton = true;
19092      this._createPopup();
19093    }
19094    return this.container;
19095  }
19096  getElementsToTriggerPopup() {
19097    return this.#line;
19098  }
19099  addHighlightArea() {
19100    this.container.classList.add("highlightArea");
19101  }
19102}
19103class SquareAnnotationElement extends AnnotationElement {
19104  #square = null;
19105  constructor(parameters) {
19106    super(parameters, {
19107      isRenderable: true,
19108      ignoreBorder: true
19109    });
19110  }
19111  render() {
19112    this.container.classList.add("squareAnnotation");
19113    const {
19114      data,
19115      width,
19116      height
19117    } = this;
19118    const svg = this.svgFactory.create(width, height, true);
19119    const borderWidth = data.borderStyle.width;
19120    const square = this.#square = this.svgFactory.createElement("svg:rect");
19121    square.setAttribute("x", borderWidth / 2);
19122    square.setAttribute("y", borderWidth / 2);
19123    square.setAttribute("width", width - borderWidth);
19124    square.setAttribute("height", height - borderWidth);
19125    square.setAttribute("stroke-width", borderWidth || 1);
19126    square.setAttribute("stroke", "transparent");
19127    square.setAttribute("fill", "transparent");
19128    svg.append(square);
19129    this.container.append(svg);
19130    if (!data.popupRef && this.hasPopupData) {
19131      this.hasOwnCommentButton = true;
19132      this._createPopup();
19133    }
19134    return this.container;
19135  }
19136  getElementsToTriggerPopup() {
19137    return this.#square;
19138  }
19139  addHighlightArea() {
19140    this.container.classList.add("highlightArea");
19141  }
19142}
19143class CircleAnnotationElement extends AnnotationElement {
19144  #circle = null;
19145  constructor(parameters) {
19146    super(parameters, {
19147      isRenderable: true,
19148      ignoreBorder: true
19149    });
19150  }
19151  render() {
19152    this.container.classList.add("circleAnnotation");
19153    const {
19154      data,
19155      width,
19156      height
19157    } = this;
19158    const svg = this.svgFactory.create(width, height, true);
19159    const borderWidth = data.borderStyle.width;
19160    const circle = this.#circle = this.svgFactory.createElement("svg:ellipse");
19161    circle.setAttribute("cx", width / 2);
19162    circle.setAttribute("cy", height / 2);
19163    circle.setAttribute("rx", width / 2 - borderWidth / 2);
19164    circle.setAttribute("ry", height / 2 - borderWidth / 2);
19165    circle.setAttribute("stroke-width", borderWidth || 1);
19166    circle.setAttribute("stroke", "transparent");
19167    circle.setAttribute("fill", "transparent");
19168    svg.append(circle);
19169    this.container.append(svg);
19170    if (!data.popupRef && this.hasPopupData) {
19171      this.hasOwnCommentButton = true;
19172      this._createPopup();
19173    }
19174    return this.container;
19175  }
19176  getElementsToTriggerPopup() {
19177    return this.#circle;
19178  }
19179  addHighlightArea() {
19180    this.container.classList.add("highlightArea");
19181  }
19182}
19183class PolylineAnnotationElement extends AnnotationElement {
19184  #polyline = null;
19185  constructor(parameters) {
19186    super(parameters, {
19187      isRenderable: true,
19188      ignoreBorder: true
19189    });
19190    this.containerClassName = "polylineAnnotation";
19191    this.svgElementName = "svg:polyline";
19192  }
19193  render() {
19194    this.container.classList.add(this.containerClassName);
19195    const {
19196      data: {
19197        rect,
19198        vertices,
19199        borderStyle,
19200        popupRef
19201      },
19202      width,
19203      height
19204    } = this;
19205    if (!vertices) {
19206      return this.container;
19207    }
19208    const svg = this.svgFactory.create(width, height, true);
19209    let points = [];
19210    for (let i = 0, ii = vertices.length; i < ii; i += 2) {
19211      const x = vertices[i] - rect[0];
19212      const y = rect[3] - vertices[i + 1];
19213      points.push(`${x},${y}`);
19214    }
19215    points = points.join(" ");
19216    const polyline = this.#polyline = this.svgFactory.createElement(this.svgElementName);
19217    polyline.setAttribute("points", points);
19218    polyline.setAttribute("stroke-width", borderStyle.width || 1);
19219    polyline.setAttribute("stroke", "transparent");
19220    polyline.setAttribute("fill", "transparent");
19221    svg.append(polyline);
19222    this.container.append(svg);
19223    if (!popupRef && this.hasPopupData) {
19224      this.hasOwnCommentButton = true;
19225      this._createPopup();
19226    }
19227    return this.container;
19228  }
19229  getElementsToTriggerPopup() {
19230    return this.#polyline;
19231  }
19232  addHighlightArea() {
19233    this.container.classList.add("highlightArea");
19234  }
19235}
19236class PolygonAnnotationElement extends PolylineAnnotationElement {
19237  constructor(parameters) {
19238    super(parameters);
19239    this.containerClassName = "polygonAnnotation";
19240    this.svgElementName = "svg:polygon";
19241  }
19242}
19243class CaretAnnotationElement extends AnnotationElement {
19244  constructor(parameters) {
19245    super(parameters, {
19246      isRenderable: true,
19247      ignoreBorder: true
19248    });
19249  }
19250  render() {
19251    this.container.classList.add("caretAnnotation");
19252    if (!this.data.popupRef && this.hasPopupData) {
19253      this.hasOwnCommentButton = true;
19254      this._createPopup();
19255    }
19256    return this.container;
19257  }
19258}
19259class InkAnnotationElement extends AnnotationElement {
19260  #polylinesGroupElement = null;
19261  #polylines = [];
19262  constructor(parameters) {
19263    super(parameters, {
19264      isRenderable: true,
19265      ignoreBorder: true
19266    });
19267    this.containerClassName = "inkAnnotation";
19268    this.svgElementName = "svg:polyline";
19269    this.annotationEditorType = this.data.it === "InkHighlight" ? AnnotationEditorType.HIGHLIGHT : AnnotationEditorType.INK;
19270  }
19271  #getTransform(rotation, rect) {
19272    switch (rotation) {
19273      case 90:
19274        return {
19275          transform: `rotate(90) translate(${-rect[0]},${rect[1]}) scale(1,-1)`,
19276          width: rect[3] - rect[1],
19277          height: rect[2] - rect[0]
19278        };
19279      case 180:
19280        return {
19281          transform: `rotate(180) translate(${-rect[2]},${rect[1]}) scale(1,-1)`,
19282          width: rect[2] - rect[0],
19283          height: rect[3] - rect[1]
19284        };
19285      case 270:
19286        return {
19287          transform: `rotate(270) translate(${-rect[2]},${rect[3]}) scale(1,-1)`,
19288          width: rect[3] - rect[1],
19289          height: rect[2] - rect[0]
19290        };
19291      default:
19292        return {
19293          transform: `translate(${-rect[0]},${rect[3]}) scale(1,-1)`,
19294          width: rect[2] - rect[0],
19295          height: rect[3] - rect[1]
19296        };
19297    }
19298  }
19299  render() {
19300    this.container.classList.add(this.containerClassName);
19301    const {
19302      data: {
19303        rect,
19304        rotation,
19305        inkLists,
19306        borderStyle,
19307        popupRef
19308      }
19309    } = this;
19310    const {
19311      transform,
19312      width,
19313      height
19314    } = this.#getTransform(rotation, rect);
19315    const svg = this.svgFactory.create(width, height, true);
19316    const g = this.#polylinesGroupElement = this.svgFactory.createElement("svg:g");
19317    svg.append(g);
19318    g.setAttribute("stroke-width", borderStyle.width || 1);
19319    g.setAttribute("stroke-linecap", "round");
19320    g.setAttribute("stroke-linejoin", "round");
19321    g.setAttribute("stroke-miterlimit", 10);
19322    g.setAttribute("stroke", "transparent");
19323    g.setAttribute("fill", "transparent");
19324    g.setAttribute("transform", transform);
19325    for (let i = 0, ii = inkLists.length; i < ii; i++) {
19326      const polyline = this.svgFactory.createElement(this.svgElementName);
19327      this.#polylines.push(polyline);
19328      polyline.setAttribute("points", inkLists[i].join(","));
19329      g.append(polyline);
19330    }
19331    if (!popupRef && this.hasPopupData) {
19332      this.hasOwnCommentButton = true;
19333      this._createPopup();
19334    }
19335    this.container.append(svg);
19336    this._editOnDoubleClick();
19337    return this.container;
19338  }
19339  updateEdited(params) {
19340    super.updateEdited(params);
19341    const {
19342      thickness,
19343      points,
19344      rect
19345    } = params;
19346    const g = this.#polylinesGroupElement;
19347    if (thickness >= 0) {
19348      g.setAttribute("stroke-width", thickness || 1);
19349    }
19350    if (points) {
19351      for (let i = 0, ii = this.#polylines.length; i < ii; i++) {
19352        this.#polylines[i].setAttribute("points", points[i].join(","));
19353      }
19354    }
19355    if (rect) {
19356      const {
19357        transform,
19358        width,
19359        height
19360      } = this.#getTransform(this.data.rotation, rect);
19361      const root = g.parentElement;
19362      root.setAttribute("viewBox", `0 0 ${width} ${height}`);
19363      g.setAttribute("transform", transform);
19364    }
19365  }
19366  getElementsToTriggerPopup() {
19367    return this.#polylines;
19368  }
19369  addHighlightArea() {
19370    this.container.classList.add("highlightArea");
19371  }
19372}
19373class HighlightAnnotationElement extends AnnotationElement {
19374  constructor(parameters) {
19375    super(parameters, {
19376      isRenderable: true,
19377      ignoreBorder: true,
19378      createQuadrilaterals: true
19379    });
19380    this.annotationEditorType = AnnotationEditorType.HIGHLIGHT;
19381  }
19382  render() {
19383    const {
19384      data: {
19385        overlaidText,
19386        popupRef
19387      }
19388    } = this;
19389    if (!popupRef && this.hasPopupData) {
19390      this.hasOwnCommentButton = true;
19391      this._createPopup();
19392    }
19393    this.container.classList.add("highlightAnnotation");
19394    this._editOnDoubleClick();
19395    if (overlaidText) {
19396      const mark = document.createElement("mark");
19397      mark.classList.add("overlaidText");
19398      mark.textContent = overlaidText;
19399      this.container.append(mark);
19400    }
19401    return this.container;
19402  }
19403}
19404class UnderlineAnnotationElement extends AnnotationElement {
19405  constructor(parameters) {
19406    super(parameters, {
19407      isRenderable: true,
19408      ignoreBorder: true,
19409      createQuadrilaterals: true
19410    });
19411  }
19412  render() {
19413    const {
19414      data: {
19415        overlaidText,
19416        popupRef
19417      }
19418    } = this;
19419    if (!popupRef && this.hasPopupData) {
19420      this.hasOwnCommentButton = true;
19421      this._createPopup();
19422    }
19423    this.container.classList.add("underlineAnnotation");
19424    if (overlaidText) {
19425      const underline = document.createElement("u");
19426      underline.classList.add("overlaidText");
19427      underline.textContent = overlaidText;
19428      this.container.append(underline);
19429    }
19430    return this.container;
19431  }
19432}
19433class SquigglyAnnotationElement extends AnnotationElement {
19434  constructor(parameters) {
19435    super(parameters, {
19436      isRenderable: true,
19437      ignoreBorder: true,
19438      createQuadrilaterals: true
19439    });
19440  }
19441  render() {
19442    const {
19443      data: {
19444        overlaidText,
19445        popupRef
19446      }
19447    } = this;
19448    if (!popupRef && this.hasPopupData) {
19449      this.hasOwnCommentButton = true;
19450      this._createPopup();
19451    }
19452    this.container.classList.add("squigglyAnnotation");
19453    if (overlaidText) {
19454      const underline = document.createElement("u");
19455      underline.classList.add("overlaidText");
19456      underline.textContent = overlaidText;
19457      this.container.append(underline);
19458    }
19459    return this.container;
19460  }
19461}
19462class StrikeOutAnnotationElement extends AnnotationElement {
19463  constructor(parameters) {
19464    super(parameters, {
19465      isRenderable: true,
19466      ignoreBorder: true,
19467      createQuadrilaterals: true
19468    });
19469  }
19470  render() {
19471    const {
19472      data: {
19473        overlaidText,
19474        popupRef
19475      }
19476    } = this;
19477    if (!popupRef && this.hasPopupData) {
19478      this.hasOwnCommentButton = true;
19479      this._createPopup();
19480    }
vendor: 3,717 bytes, lines 19481-19609
19481    this.container.classList.add("strikeoutAnnotation");
19482    if (overlaidText) {
19483      const strikeout = document.createElement("s");
19484      strikeout.classList.add("overlaidText");
19485      strikeout.textContent = overlaidText;
19486      this.container.append(strikeout);
19487    }
19488    return this.container;
19489  }
19490}
19491class StampAnnotationElement extends AnnotationElement {
19492  constructor(parameters) {
19493    super(parameters, {
19494      isRenderable: true,
19495      ignoreBorder: true
19496    });
19497    this.annotationEditorType = AnnotationEditorType.STAMP;
19498  }
19499  render() {
19500    this.container.classList.add("stampAnnotation");
19501    this.container.setAttribute("role", "img");
19502    if (!this.data.popupRef && this.hasPopupData) {
19503      this.hasOwnCommentButton = true;
19504      this._createPopup();
19505    }
19506    this._editOnDoubleClick();
19507    return this.container;
19508  }
19509}
19510class FileAttachmentAnnotationElement extends AnnotationElement {
19511  #trigger = null;
19512  constructor(parameters) {
19513    super(parameters, {
19514      isRenderable: true
19515    });
19516    const {
19517      file
19518    } = this.data;
19519    this.filename = file.filename;
19520    this.content = file.content;
19521    this.linkService.eventBus?.dispatch("fileattachmentannotation", {
19522      source: this,
19523      ...file
19524    });
19525  }
19526  render() {
19527    this.container.classList.add("fileAttachmentAnnotation");
19528    const {
19529      container,
19530      data
19531    } = this;
19532    let trigger;
19533    if (data.hasAppearance || data.fillAlpha === 0) {
19534      trigger = document.createElement("div");
19535    } else {
19536      trigger = document.createElement("img");
19537      trigger.src = `${this.imageResourcesPath}annotation-${/paperclip/i.test(data.name) ? "paperclip" : "pushpin"}.svg`;
19538      if (data.fillAlpha && data.fillAlpha < 1) {
19539        trigger.style = `filter: opacity(${Math.round(data.fillAlpha * 100)}%);`;
19540      }
19541    }
19542    trigger.addEventListener("dblclick", this.#download.bind(this));
19543    this.#trigger = trigger;
19544    const {
19545      isMac
19546    } = util_FeatureTest.platform;
19547    container.addEventListener("keydown", evt => {
19548      if (evt.key === "Enter" && (isMac ? evt.metaKey : evt.ctrlKey)) {
19549        this.#download();
19550      }
19551    });
19552    if (!data.popupRef && this.hasPopupData) {
19553      this.hasOwnCommentButton = true;
19554      this._createPopup();
19555    } else {
19556      trigger.classList.add("popupTriggerArea");
19557    }
19558    container.append(trigger);
19559    return container;
19560  }
19561  getElementsToTriggerPopup() {
19562    return this.#trigger;
19563  }
19564  addHighlightArea() {
19565    this.container.classList.add("highlightArea");
19566  }
19567  #download() {
19568    this.downloadManager?.openOrDownloadData(this.content, this.filename);
19569  }
19570}
19571class AnnotationLayer {
19572  #accessibilityManager = null;
19573  #annotationCanvasMap = null;
19574  #annotationStorage = null;
19575  #editableAnnotations = new Map();
19576  #structTreeLayer = null;
19577  #linkService = null;
19578  #elements = [];
19579  #hasAriaAttributesFromStructTree = false;
19580  constructor({
19581    div,
19582    accessibilityManager,
19583    annotationCanvasMap,
19584    annotationEditorUIManager,
19585    page,
19586    viewport,
19587    structTreeLayer,
19588    commentManager,
19589    linkService,
19590    annotationStorage
19591  }) {
19592    this.div = div;
19593    this.#accessibilityManager = accessibilityManager;
19594    this.#annotationCanvasMap = annotationCanvasMap;
19595    this.#structTreeLayer = structTreeLayer || null;
19596    this.#linkService = linkService || null;
19597    this.#annotationStorage = annotationStorage || new AnnotationStorage();
19598    this.page = page;
19599    this.viewport = viewport;
19600    this.zIndex = 0;
19601    this._annotationEditorUIManager = annotationEditorUIManager;
19602    this._commentManager = commentManager || null;
19603  }
19604  hasEditableAnnotations() {
19605    return this.#editableAnnotations.size > 0;
19606  }
19607  async render(params) {
19608    const {
19609      annotations
vendor: 1,604 bytes, lines 19609-19659
19609
19610    } = params;
19611    const layer = this.div;
19612    setLayerDimensions(layer, this.viewport);
19613    const popupToElements = new Map();
19614    const popupAnnotations = [];
19615    const elementParams = {
19616      data: null,
19617      layer,
19618      linkService: this.#linkService,
19619      downloadManager: params.downloadManager,
19620      imageResourcesPath: params.imageResourcesPath || "",
19621      renderForms: params.renderForms !== false,
19622      svgFactory: new DOMSVGFactory(),
19623      annotationStorage: this.#annotationStorage,
19624      enableComment: params.enableComment === true,
19625      enableScripting: params.enableScripting === true,
19626      hasJSActions: params.hasJSActions,
19627      fieldObjects: params.fieldObjects,
19628      parent: this,
19629      elements: null
19630    };
19631    for (const data of annotations) {
19632      if (data.noHTML) {
19633        continue;
19634      }
19635      const isPopupAnnotation = data.annotationType === AnnotationType.POPUP;
19636      if (!isPopupAnnotation) {
19637        if (data.rect[2] === data.rect[0] || data.rect[3] === data.rect[1]) {
19638          continue;
19639        }
19640      } else {
19641        const elements = popupToElements.get(data.id);
19642        if (!elements) {
19643          continue;
19644        }
19645        if (!this._commentManager) {
19646          popupAnnotations.push(data);
19647          continue;
19648        }
19649        elementParams.elements = elements;
19650      }
19651      elementParams.data = data;
19652      const element = AnnotationElementFactory.create(elementParams);
19653      if (!element.isRenderable) {
19654        continue;
19655      }
19656      if (!isPopupAnnotation) {
19657        this.#elements.push(element);
19658        if (data.popupRef) {
19659          
vendor: 9,178 bytes, lines 19659-19958
19659const elements = popupToElements.get(data.popupRef);
19660          if (!elements) {
19661            popupToElements.set(data.popupRef, [element]);
19662          } else {
19663            elements.push(element);
19664          }
19665        }
19666      }
19667      const rendered = element.render();
19668      if (data.hidden) {
19669        rendered.style.visibility = "hidden";
19670      }
19671      if (element._isEditable) {
19672        this.#editableAnnotations.set(element.data.id, element);
19673        this._annotationEditorUIManager?.renderAnnotationElement(element);
19674      }
19675    }
19676    await this.#addElementsToDOM();
19677    for (const data of popupAnnotations) {
19678      const elements = elementParams.elements = popupToElements.get(data.id);
19679      elementParams.data = data;
19680      const element = AnnotationElementFactory.create(elementParams);
19681      if (!element.isRenderable) {
19682        continue;
19683      }
19684      const rendered = element.render();
19685      element.contentElement.id = `${AnnotationPrefix}${data.id}`;
19686      if (data.hidden) {
19687        rendered.style.visibility = "hidden";
19688      }
19689      elements.at(-1).container.after(rendered);
19690    }
19691    this.#setAnnotationCanvasMap();
19692  }
19693  async #addElementsToDOM() {
19694    if (this.#elements.length === 0) {
19695      return;
19696    }
19697    this.div.replaceChildren();
19698    const promises = [];
19699    if (!this.#hasAriaAttributesFromStructTree) {
19700      this.#hasAriaAttributesFromStructTree = true;
19701      for (const {
19702        contentElement,
19703        data: {
19704          id
19705        }
19706      } of this.#elements) {
19707        const annotationId = contentElement.id = `${AnnotationPrefix}${id}`;
19708        promises.push(this.#structTreeLayer?.getAriaAttributes(annotationId).then(ariaAttributes => {
19709          if (ariaAttributes) {
19710            for (const [key, value] of ariaAttributes) {
19711              contentElement.setAttribute(key, value);
19712            }
19713          }
19714        }));
19715      }
19716    }
19717    this.#elements.sort(({
19718      data: {
19719        rect: [a0, a1, a2, a3]
19720      }
19721    }, {
19722      data: {
19723        rect: [b0, b1, b2, b3]
19724      }
19725    }) => {
19726      if (a0 === a2 && a1 === a3) {
19727        return +1;
19728      }
19729      if (b0 === b2 && b1 === b3) {
19730        return -1;
19731      }
19732      const top1 = a3;
19733      const bot1 = a1;
19734      const mid1 = (a1 + a3) / 2;
19735      const top2 = b3;
19736      const bot2 = b1;
19737      const mid2 = (b1 + b3) / 2;
19738      if (mid1 >= top2 && mid2 <= bot1) {
19739        return -1;
19740      }
19741      if (mid2 >= top1 && mid1 <= bot2) {
19742        return +1;
19743      }
19744      const centerX1 = (a0 + a2) / 2;
19745      const centerX2 = (b0 + b2) / 2;
19746      return centerX1 - centerX2;
19747    });
19748    const fragment = document.createDocumentFragment();
19749    for (const element of this.#elements) {
19750      fragment.append(element.container);
19751      if (this._commentManager) {
19752        (element.extraPopupElement?.popup || element.popup)?.renderCommentButton();
19753      } else if (element.extraPopupElement) {
19754        fragment.append(element.extraPopupElement.render());
19755      }
19756    }
19757    this.div.append(fragment);
19758    await Promise.all(promises);
19759    if (this.#accessibilityManager) {
19760      for (const element of this.#elements) {
19761        this.#accessibilityManager.addPointerInTextLayer(element.contentElement, false);
19762      }
19763    }
19764  }
19765  async addLinkAnnotations(annotations) {
19766    const elementParams = {
19767      data: null,
19768      layer: this.div,
19769      linkService: this.#linkService,
19770      svgFactory: new DOMSVGFactory(),
19771      parent: this
19772    };
19773    for (const data of annotations) {
19774      data.borderStyle ||= AnnotationLayer._defaultBorderStyle;
19775      elementParams.data = data;
19776      const element = AnnotationElementFactory.create(elementParams);
19777      if (!element.isRenderable) {
19778        continue;
19779      }
19780      element.render();
19781      element.contentElement.id = `${AnnotationPrefix}${data.id}`;
19782      this.#elements.push(element);
19783    }
19784    await this.#addElementsToDOM();
19785  }
19786  update({
19787    viewport
19788  }) {
19789    const layer = this.div;
19790    this.viewport = viewport;
19791    setLayerDimensions(layer, {
19792      rotation: viewport.rotation
19793    });
19794    this.#setAnnotationCanvasMap();
19795    layer.hidden = false;
19796  }
19797  #setAnnotationCanvasMap() {
19798    if (!this.#annotationCanvasMap) {
19799      return;
19800    }
19801    const layer = this.div;
19802    for (const [id, canvas] of this.#annotationCanvasMap) {
19803      const element = layer.querySelector(`[data-annotation-id="${id}"]`);
19804      if (!element) {
19805        continue;
19806      }
19807      canvas.className = "annotationContent";
19808      const {
19809        firstChild
19810      } = element;
19811      if (!firstChild) {
19812        element.append(canvas);
19813      } else if (firstChild.nodeName === "CANVAS") {
19814        firstChild.replaceWith(canvas);
19815      } else if (!firstChild.classList.contains("annotationContent")) {
19816        firstChild.before(canvas);
19817      } else {
19818        firstChild.after(canvas);
19819      }
19820      const editableAnnotation = this.#editableAnnotations.get(id);
19821      if (!editableAnnotation) {
19822        continue;
19823      }
19824      if (editableAnnotation._hasNoCanvas) {
19825        this._annotationEditorUIManager?.setMissingCanvas(id, element.id, canvas);
19826        editableAnnotation._hasNoCanvas = false;
19827      } else {
19828        editableAnnotation.canvas = canvas;
19829      }
19830    }
19831    this.#annotationCanvasMap.clear();
19832  }
19833  getEditableAnnotations() {
19834    return Array.from(this.#editableAnnotations.values());
19835  }
19836  getEditableAnnotation(id) {
19837    return this.#editableAnnotations.get(id);
19838  }
19839  addFakeAnnotation(editor) {
19840    const {
19841      div
19842    } = this;
19843    const {
19844      id,
19845      rotation
19846    } = editor;
19847    const element = new EditorAnnotationElement({
19848      data: {
19849        id,
19850        rect: editor.getPDFRect(),
19851        rotation
19852      },
19853      editor,
19854      layer: div,
19855      parent: this,
19856      enableComment: !!this._commentManager,
19857      linkService: this.#linkService,
19858      annotationStorage: this.#annotationStorage
19859    });
19860    element.render();
19861    element.contentElement.id = `${AnnotationPrefix}${id}`;
19862    element.createOrUpdatePopup();
19863    this.#elements.push(element);
19864    return element;
19865  }
19866  removeAnnotation(id) {
19867    const index = this.#elements.findIndex(el => el.data.id === id);
19868    if (index < 0) {
19869      return;
19870    }
19871    const [element] = this.#elements.splice(index, 1);
19872    this.#accessibilityManager?.removePointerInTextLayer(element.contentElement);
19873  }
19874  updateFakeAnnotations(editors) {
19875    if (editors.length === 0) {
19876      return;
19877    }
19878    for (const editor of editors) {
19879      editor.updateFakeAnnotationElement(this);
19880    }
19881    this.#addElementsToDOM();
19882  }
19883  togglePointerEvents(enabled = false) {
19884    this.div.classList.toggle("disabled", !enabled);
19885  }
19886  static get _defaultBorderStyle() {
19887    return shadow(this, "_defaultBorderStyle", Object.freeze({
19888      width: 1,
19889      rawWidth: 1,
19890      style: AnnotationBorderStyleType.SOLID,
19891      dashArray: [3],
19892      horizontalCornerRadius: 0,
19893      verticalCornerRadius: 0
19894    }));
19895  }
19896}
19897
19898;// ./src/display/editor/freetext.js
19899
19900
19901
19902
19903
19904const EOL_PATTERN = /\r\n?|\n/g;
19905class FreeTextEditor extends AnnotationEditor {
19906  #content = "";
19907  #editorDivId = `${this.id}-editor`;
19908  #editModeAC = null;
19909  #fontSize;
19910  _colorPicker = null;
19911  static _freeTextDefaultContent = "";
19912  static _internalPadding = 0;
19913  static _defaultColor = null;
19914  static _defaultFontSize = 10;
19915  static get _keyboardManager() {
19916    const proto = FreeTextEditor.prototype;
19917    const arrowChecker = self => self.isEmpty();
19918    const small = AnnotationEditorUIManager.TRANSLATE_SMALL;
19919    const big = AnnotationEditorUIManager.TRANSLATE_BIG;
19920    return shadow(this, "_keyboardManager", new KeyboardManager([[["ctrl+s", "mac+meta+s", "ctrl+p", "mac+meta+p"], proto.commitOrRemove, {
19921      bubbles: true
19922    }], [["ctrl+Enter", "mac+meta+Enter", "Escape", "mac+Escape"], proto.commitOrRemove], [["ArrowLeft", "mac+ArrowLeft"], proto._translateEmpty, {
19923      args: [-small, 0],
19924      checker: arrowChecker
19925    }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], proto._translateEmpty, {
19926      args: [-big, 0],
19927      checker: arrowChecker
19928    }], [["ArrowRight", "mac+ArrowRight"], proto._translateEmpty, {
19929      args: [small, 0],
19930      checker: arrowChecker
19931    }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], proto._translateEmpty, {
19932      args: [big, 0],
19933      checker: arrowChecker
19934    }], [["ArrowUp", "mac+ArrowUp"], proto._translateEmpty, {
19935      args: [0, -small],
19936      checker: arrowChecker
19937    }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], proto._translateEmpty, {
19938      args: [0, -big],
19939      checker: arrowChecker
19940    }], [["ArrowDown", "mac+ArrowDown"], proto._translateEmpty, {
19941      args: [0, small],
19942      checker: arrowChecker
19943    }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], proto._translateEmpty, {
19944      args: [0, big],
19945      checker: arrowChecker
19946    }]]));
19947  }
19948  static _type = "freetext";
19949  static _editorType = AnnotationEditorType.FREETEXT;
19950  constructor(params) {
19951    super({
19952      ...params,
19953      name: "freeTextEditor"
19954    });
19955    this.color = params.color || FreeTextEditor._defaultColor || AnnotationEditor._defaultLineColor;
19956    this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize;
19957    if (!this.annotationElementId) {
19958      this._uiManager.a11yAlert("pdfjs-editor-freetext-added-alert"
vendor: 14,846 bytes, lines 19958-20445
19958);
19959    }
19960    this.canAddComment = false;
19961  }
19962  static initialize(l10n, uiManager) {
19963    AnnotationEditor.initialize(l10n, uiManager);
19964    const style = getComputedStyle(document.documentElement);
19965    this._internalPadding = parseFloat(style.getPropertyValue("--freetext-padding"));
19966  }
19967  static updateDefaultParams(type, value) {
19968    switch (type) {
19969      case AnnotationEditorParamsType.FREETEXT_SIZE:
19970        FreeTextEditor._defaultFontSize = value;
19971        break;
19972      case AnnotationEditorParamsType.FREETEXT_COLOR:
19973        FreeTextEditor._defaultColor = value;
19974        break;
19975    }
19976  }
19977  updateParams(type, value) {
19978    switch (type) {
19979      case AnnotationEditorParamsType.FREETEXT_SIZE:
19980        this.#updateFontSize(value);
19981        break;
19982      case AnnotationEditorParamsType.FREETEXT_COLOR:
19983        this.#updateColor(value);
19984        break;
19985    }
19986  }
19987  static get defaultPropertiesToUpdate() {
19988    return [[AnnotationEditorParamsType.FREETEXT_SIZE, FreeTextEditor._defaultFontSize], [AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor || AnnotationEditor._defaultLineColor]];
19989  }
19990  get propertiesToUpdate() {
19991    return [[AnnotationEditorParamsType.FREETEXT_SIZE, this.#fontSize], [AnnotationEditorParamsType.FREETEXT_COLOR, this.color]];
19992  }
19993  get toolbarButtons() {
19994    this._colorPicker ||= new BasicColorPicker(this);
19995    return [["colorPicker", this._colorPicker]];
19996  }
19997  get colorType() {
19998    return AnnotationEditorParamsType.FREETEXT_COLOR;
19999  }
20000  #updateFontSize(fontSize) {
20001    const setFontsize = size => {
20002      this.editorDiv.style.fontSize = `calc(${size}px * var(--total-scale-factor))`;
20003      this.translate(0, -(size - this.#fontSize) * this.parentScale);
20004      this.#fontSize = size;
20005      this.#setEditorDimensions();
20006    };
20007    const savedFontsize = this.#fontSize;
20008    this.addCommands({
20009      cmd: setFontsize.bind(this, fontSize),
20010      undo: setFontsize.bind(this, savedFontsize),
20011      post: this._uiManager.updateUI.bind(this._uiManager, this),
20012      mustExec: true,
20013      type: AnnotationEditorParamsType.FREETEXT_SIZE,
20014      overwriteIfSameType: true,
20015      keepUndo: true
20016    });
20017  }
20018  onUpdatedColor() {
20019    this.editorDiv.style.color = this.color;
20020    this._colorPicker?.update(this.color);
20021    super.onUpdatedColor();
20022  }
20023  #updateColor(color) {
20024    const setColor = col => {
20025      this.color = col;
20026      this.onUpdatedColor();
20027    };
20028    const savedColor = this.color;
20029    this.addCommands({
20030      cmd: setColor.bind(this, color),
20031      undo: setColor.bind(this, savedColor),
20032      post: this._uiManager.updateUI.bind(this._uiManager, this),
20033      mustExec: true,
20034      type: AnnotationEditorParamsType.FREETEXT_COLOR,
20035      overwriteIfSameType: true,
20036      keepUndo: true
20037    });
20038  }
20039  _translateEmpty(x, y) {
20040    this._uiManager.translateSelectedEditors(x, y, true);
20041  }
20042  getInitialTranslation() {
20043    const scale = this.parentScale;
20044    return [-FreeTextEditor._internalPadding * scale, -(FreeTextEditor._internalPadding + this.#fontSize) * scale];
20045  }
20046  rebuild() {
20047    if (!this.parent) {
20048      return;
20049    }
20050    super.rebuild();
20051    if (this.div === null) {
20052      return;
20053    }
20054    if (!this.isAttachedToDOM) {
20055      this.parent.add(this);
20056    }
20057  }
20058  enableEditMode() {
20059    if (!super.enableEditMode()) {
20060      return false;
20061    }
20062    this.overlayDiv.classList.remove("enabled");
20063    this.editorDiv.contentEditable = true;
20064    this._isDraggable = false;
20065    this.div.removeAttribute("aria-activedescendant");
20066    this.#editModeAC = new AbortController();
20067    const signal = this._uiManager.combinedSignal(this.#editModeAC);
20068    this.editorDiv.addEventListener("keydown", this.editorDivKeydown.bind(this), {
20069      signal
20070    });
20071    this.editorDiv.addEventListener("focus", this.editorDivFocus.bind(this), {
20072      signal
20073    });
20074    this.editorDiv.addEventListener("blur", this.editorDivBlur.bind(this), {
20075      signal
20076    });
20077    this.editorDiv.addEventListener("input", this.editorDivInput.bind(this), {
20078      signal
20079    });
20080    this.editorDiv.addEventListener("paste", this.editorDivPaste.bind(this), {
20081      signal
20082    });
20083    return true;
20084  }
20085  disableEditMode() {
20086    if (!super.disableEditMode()) {
20087      return false;
20088    }
20089    this.overlayDiv.classList.add("enabled");
20090    this.editorDiv.contentEditable = false;
20091    this.div.setAttribute("aria-activedescendant", this.#editorDivId);
20092    this._isDraggable = true;
20093    this.#editModeAC?.abort();
20094    this.#editModeAC = null;
20095    this.div.focus({
20096      preventScroll: true
20097    });
20098    this.isEditing = false;
20099    this.parent.div.classList.add("freetextEditing");
20100    return true;
20101  }
20102  focusin(event) {
20103    if (!this._focusEventsAllowed) {
20104      return;
20105    }
20106    super.focusin(event);
20107    if (event.target !== this.editorDiv) {
20108      this.editorDiv.focus();
20109    }
20110  }
20111  onceAdded(focus) {
20112    if (this.width) {
20113      return;
20114    }
20115    this.enableEditMode();
20116    if (focus) {
20117      this.editorDiv.focus();
20118    }
20119    if (this._initialOptions?.isCentered) {
20120      this.center();
20121    }
20122    this._initialOptions = null;
20123  }
20124  isEmpty() {
20125    return !this.editorDiv || this.editorDiv.innerText.trim() === "";
20126  }
20127  remove() {
20128    this.isEditing = false;
20129    if (this.parent) {
20130      this.parent.setEditingState(true);
20131      this.parent.div.classList.add("freetextEditing");
20132    }
20133    super.remove();
20134  }
20135  #extractText() {
20136    const buffer = [];
20137    this.editorDiv.normalize();
20138    let prevChild = null;
20139    for (const child of this.editorDiv.childNodes) {
20140      if (prevChild?.nodeType === Node.TEXT_NODE && child.nodeName === "BR") {
20141        continue;
20142      }
20143      buffer.push(FreeTextEditor.#getNodeContent(child));
20144      prevChild = child;
20145    }
20146    return buffer.join("\n");
20147  }
20148  #setEditorDimensions() {
20149    const [parentWidth, parentHeight] = this.parentDimensions;
20150    let rect;
20151    if (this.isAttachedToDOM) {
20152      rect = this.div.getBoundingClientRect();
20153    } else {
20154      const {
20155        currentLayer,
20156        div
20157      } = this;
20158      const savedDisplay = div.style.display;
20159      const savedVisibility = div.classList.contains("hidden");
20160      div.classList.remove("hidden");
20161      div.style.display = "hidden";
20162      currentLayer.div.append(this.div);
20163      rect = div.getBoundingClientRect();
20164      div.remove();
20165      div.style.display = savedDisplay;
20166      div.classList.toggle("hidden", savedVisibility);
20167    }
20168    if (this.rotation % 180 === this.parentRotation % 180) {
20169      this.width = rect.width / parentWidth;
20170      this.height = rect.height / parentHeight;
20171    } else {
20172      this.width = rect.height / parentWidth;
20173      this.height = rect.width / parentHeight;
20174    }
20175    this.fixAndSetPosition();
20176  }
20177  commit() {
20178    if (!this.isInEditMode()) {
20179      return;
20180    }
20181    super.commit();
20182    this.disableEditMode();
20183    const savedText = this.#content;
20184    const newText = this.#content = this.#extractText().trimEnd();
20185    if (savedText === newText) {
20186      return;
20187    }
20188    const setText = text => {
20189      this.#content = text;
20190      if (!text) {
20191        this.remove();
20192        return;
20193      }
20194      this.#setContent();
20195      this._uiManager.rebuild(this);
20196      this.#setEditorDimensions();
20197    };
20198    this.addCommands({
20199      cmd: () => {
20200        setText(newText);
20201      },
20202      undo: () => {
20203        setText(savedText);
20204      },
20205      mustExec: false
20206    });
20207    this.#setEditorDimensions();
20208  }
20209  shouldGetKeyboardEvents() {
20210    return this.isInEditMode();
20211  }
20212  enterInEditMode() {
20213    this.enableEditMode();
20214    this.editorDiv.focus();
20215  }
20216  keydown(event) {
20217    if (event.target === this.div && event.key === "Enter") {
20218      this.enterInEditMode();
20219      event.preventDefault();
20220    }
20221  }
20222  editorDivKeydown(event) {
20223    FreeTextEditor._keyboardManager.exec(this, event);
20224  }
20225  editorDivFocus(event) {
20226    this.isEditing = true;
20227  }
20228  editorDivBlur(event) {
20229    this.isEditing = false;
20230  }
20231  editorDivInput(event) {
20232    this.parent.div.classList.toggle("freetextEditing", this.isEmpty());
20233  }
20234  disableEditing() {
20235    this.editorDiv.setAttribute("role", "comment");
20236    this.editorDiv.removeAttribute("aria-multiline");
20237  }
20238  enableEditing() {
20239    this.editorDiv.setAttribute("role", "textbox");
20240    this.editorDiv.setAttribute("aria-multiline", true);
20241  }
20242  get canChangeContent() {
20243    return true;
20244  }
20245  render() {
20246    if (this.div) {
20247      return this.div;
20248    }
20249    let baseX, baseY;
20250    if (this._isCopy || this.annotationElementId) {
20251      baseX = this.x;
20252      baseY = this.y;
20253    }
20254    super.render();
20255    this.editorDiv = document.createElement("div");
20256    this.editorDiv.className = "internal";
20257    this.editorDiv.setAttribute("id", this.#editorDivId);
20258    this.editorDiv.setAttribute("data-l10n-id", "pdfjs-free-text2");
20259    this.editorDiv.setAttribute("data-l10n-attrs", "default-content");
20260    this.enableEditing();
20261    this.editorDiv.contentEditable = true;
20262    const {
20263      style
20264    } = this.editorDiv;
20265    style.fontSize = `calc(${this.#fontSize}px * var(--total-scale-factor))`;
20266    style.color = this.color;
20267    this.div.append(this.editorDiv);
20268    this.overlayDiv = document.createElement("div");
20269    this.overlayDiv.classList.add("overlay", "enabled");
20270    this.div.append(this.overlayDiv);
20271    if (this._isCopy || this.annotationElementId) {
20272      const [parentWidth, parentHeight] = this.parentDimensions;
20273      if (this.annotationElementId) {
20274        const {
20275          position
20276        } = this._initialData;
20277        let [tx, ty] = this.getInitialTranslation();
20278        [tx, ty] = this.pageTranslationToScreen(tx, ty);
20279        const [pageWidth, pageHeight] = this.pageDimensions;
20280        const [pageX, pageY] = this.pageTranslation;
20281        let posX, posY;
20282        switch (this.rotation) {
20283          case 0:
20284            posX = baseX + (position[0] - pageX) / pageWidth;
20285            posY = baseY + this.height - (position[1] - pageY) / pageHeight;
20286            break;
20287          case 90:
20288            posX = baseX + (position[0] - pageX) / pageWidth;
20289            posY = baseY - (position[1] - pageY) / pageHeight;
20290            [tx, ty] = [ty, -tx];
20291            break;
20292          case 180:
20293            posX = baseX - this.width + (position[0] - pageX) / pageWidth;
20294            posY = baseY - (position[1] - pageY) / pageHeight;
20295            [tx, ty] = [-tx, -ty];
20296            break;
20297          case 270:
20298            posX = baseX + (position[0] - pageX - this.height * pageHeight) / pageWidth;
20299            posY = baseY + (position[1] - pageY - this.width * pageWidth) / pageHeight;
20300            [tx, ty] = [-ty, tx];
20301            break;
20302        }
20303        this.setAt(posX * parentWidth, posY * parentHeight, tx, ty);
20304      } else {
20305        this._moveAfterPaste(baseX, baseY);
20306      }
20307      this.#setContent();
20308      this._isDraggable = true;
20309      this.editorDiv.contentEditable = false;
20310    } else {
20311      this._isDraggable = false;
20312      this.editorDiv.contentEditable = true;
20313    }
20314    return this.div;
20315  }
20316  static #getNodeContent(node) {
20317    return (node.nodeType === Node.TEXT_NODE ? node.nodeValue : node.innerText).replaceAll(EOL_PATTERN, "");
20318  }
20319  editorDivPaste(event) {
20320    const clipboardData = event.clipboardData || window.clipboardData;
20321    const {
20322      types
20323    } = clipboardData;
20324    if (types.length === 1 && types[0] === "text/plain") {
20325      return;
20326    }
20327    event.preventDefault();
20328    const paste = FreeTextEditor.#deserializeContent(clipboardData.getData("text") || "").replaceAll(EOL_PATTERN, "\n");
20329    if (!paste) {
20330      return;
20331    }
20332    const selection = window.getSelection();
20333    if (!selection.rangeCount) {
20334      return;
20335    }
20336    this.editorDiv.normalize();
20337    selection.deleteFromDocument();
20338    const range = selection.getRangeAt(0);
20339    if (!paste.includes("\n")) {
20340      range.insertNode(document.createTextNode(paste));
20341      this.editorDiv.normalize();
20342      selection.collapseToStart();
20343      return;
20344    }
20345    const {
20346      startContainer,
20347      startOffset
20348    } = range;
20349    const bufferBefore = [];
20350    const bufferAfter = [];
20351    if (startContainer.nodeType === Node.TEXT_NODE) {
20352      const parent = startContainer.parentElement;
20353      bufferAfter.push(startContainer.nodeValue.slice(startOffset).replaceAll(EOL_PATTERN, ""));
20354      if (parent !== this.editorDiv) {
20355        let buffer = bufferBefore;
20356        for (const child of this.editorDiv.childNodes) {
20357          if (child === parent) {
20358            buffer = bufferAfter;
20359            continue;
20360          }
20361          buffer.push(FreeTextEditor.#getNodeContent(child));
20362        }
20363      }
20364      bufferBefore.push(startContainer.nodeValue.slice(0, startOffset).replaceAll(EOL_PATTERN, ""));
20365    } else if (startContainer === this.editorDiv) {
20366      let buffer = bufferBefore;
20367      let i = 0;
20368      for (const child of this.editorDiv.childNodes) {
20369        if (i++ === startOffset) {
20370          buffer = bufferAfter;
20371        }
20372        buffer.push(FreeTextEditor.#getNodeContent(child));
20373      }
20374    }
20375    this.#content = `${bufferBefore.join("\n")}${paste}${bufferAfter.join("\n")}`;
20376    this.#setContent();
20377    const newRange = new Range();
20378    let beforeLength = Math.sumPrecise(bufferBefore.map(line => line.length));
20379    for (const {
20380      firstChild
20381    } of this.editorDiv.childNodes) {
20382      if (firstChild.nodeType === Node.TEXT_NODE) {
20383        const length = firstChild.nodeValue.length;
20384        if (beforeLength <= length) {
20385          newRange.setStart(firstChild, beforeLength);
20386          newRange.setEnd(firstChild, beforeLength);
20387          break;
20388        }
20389        beforeLength -= length;
20390      }
20391    }
20392    selection.removeAllRanges();
20393    selection.addRange(newRange);
20394  }
20395  #setContent() {
20396    this.editorDiv.replaceChildren();
20397    if (!this.#content) {
20398      return;
20399    }
20400    for (const line of this.#content.split("\n")) {
20401      const div = document.createElement("div");
20402      div.append(line ? document.createTextNode(line) : document.createElement("br"));
20403      this.editorDiv.append(div);
20404    }
20405  }
20406  #serializeContent() {
20407    return this.#content.replaceAll("\xa0", " ");
20408  }
20409  static #deserializeContent(content) {
20410    return content.replaceAll(" ", "\xa0");
20411  }
20412  get contentDiv() {
20413    return this.editorDiv;
20414  }
20415  getPDFRect() {
20416    const padding = FreeTextEditor._internalPadding * this.parentScale;
20417    return this.getRect(padding, padding);
20418  }
20419  static async deserialize(data, parent, uiManager) {
20420    let initialData = null;
20421    if (data instanceof FreeTextAnnotationElement) {
20422      const {
20423        data: {
20424          defaultAppearanceData: {
20425            fontSize,
20426            fontColor
20427          },
20428          rect,
20429          rotation,
20430          id,
20431          popupRef,
20432          richText,
20433          contentsObj,
20434          creationDate,
20435          modificationDate
20436        },
20437        textContent,
20438        textPosition,
20439        parent: {
20440          page: {
20441            pageNumber
20442          }
20443        }
20444      } = data;
20445      if (!textContent
vendor: 6,223 bytes, lines 20445-20655
20445 || textContent.length === 0) {
20446        return null;
20447      }
20448      initialData = data = {
20449        annotationType: AnnotationEditorType.FREETEXT,
20450        color: Array.from(fontColor),
20451        fontSize,
20452        value: textContent.join("\n"),
20453        position: textPosition,
20454        pageIndex: pageNumber - 1,
20455        rect: rect.slice(0),
20456        rotation,
20457        annotationElementId: id,
20458        id,
20459        deleted: false,
20460        popupRef,
20461        comment: contentsObj?.str || null,
20462        richText,
20463        creationDate,
20464        modificationDate
20465      };
20466    }
20467    const editor = await super.deserialize(data, parent, uiManager);
20468    editor.#fontSize = data.fontSize;
20469    editor.color = Util.makeHexColor(...data.color);
20470    editor.#content = FreeTextEditor.#deserializeContent(data.value);
20471    editor._initialData = initialData;
20472    if (data.comment) {
20473      editor.setCommentData(data);
20474    }
20475    return editor;
20476  }
20477  serialize(isForCopying = false) {
20478    if (this.isEmpty()) {
20479      return null;
20480    }
20481    if (this.deleted) {
20482      return this.serializeDeleted();
20483    }
20484    const color = AnnotationEditor._colorManager.convert(this.isAttachedToDOM ? getComputedStyle(this.editorDiv).color : this.color);
20485    const serialized = Object.assign(super.serialize(isForCopying), {
20486      color,
20487      fontSize: this.#fontSize,
20488      value: this.#serializeContent()
20489    });
20490    this.addComment(serialized);
20491    if (isForCopying) {
20492      serialized.isCopy = true;
20493      return serialized;
20494    }
20495    if (this.annotationElementId && !this.#hasElementChanged(serialized)) {
20496      return null;
20497    }
20498    serialized.id = this.annotationElementId;
20499    return serialized;
20500  }
20501  #hasElementChanged(serialized) {
20502    const {
20503      value,
20504      fontSize,
20505      color,
20506      pageIndex
20507    } = this._initialData;
20508    return this.hasEditedComment || this._hasBeenMoved || serialized.value !== value || serialized.fontSize !== fontSize || serialized.color.some((c, i) => c !== color[i]) || serialized.pageIndex !== pageIndex;
20509  }
20510  renderAnnotationElement(annotation) {
20511    const content = super.renderAnnotationElement(annotation);
20512    if (!content) {
20513      return null;
20514    }
20515    const {
20516      style
20517    } = content;
20518    style.fontSize = `calc(${this.#fontSize}px * var(--total-scale-factor))`;
20519    style.color = this.color;
20520    content.replaceChildren();
20521    for (const line of this.#content.split("\n")) {
20522      const div = document.createElement("div");
20523      div.append(line ? document.createTextNode(line) : document.createElement("br"));
20524      content.append(div);
20525    }
20526    annotation.updateEdited({
20527      rect: this.getPDFRect(),
20528      popup: this._uiManager.hasCommentManager() || this.hasEditedComment ? this.comment : {
20529        text: this.#content
20530      }
20531    });
20532    return content;
20533  }
20534  resetAnnotationElement(annotation) {
20535    super.resetAnnotationElement(annotation);
20536    annotation.resetEdited();
20537  }
20538}
20539
20540;// ./src/display/editor/drawers/outline.js
20541
20542class Outline {
20543  static PRECISION = 1e-4;
20544  toSVGPath() {
20545    unreachable("Abstract method `toSVGPath` must be implemented.");
20546  }
20547  get box() {
20548    unreachable("Abstract getter `box` must be implemented.");
20549  }
20550  serialize(_bbox, _rotation) {
20551    unreachable("Abstract method `serialize` must be implemented.");
20552  }
20553  static _rescale(src, tx, ty, sx, sy, dest) {
20554    dest ||= new Float32Array(src.length);
20555    for (let i = 0, ii = src.length; i < ii; i += 2) {
20556      dest[i] = tx + src[i] * sx;
20557      dest[i + 1] = ty + src[i + 1] * sy;
20558    }
20559    return dest;
20560  }
20561  static _rescaleAndSwap(src, tx, ty, sx, sy, dest) {
20562    dest ||= new Float32Array(src.length);
20563    for (let i = 0, ii = src.length; i < ii; i += 2) {
20564      dest[i] = tx + src[i + 1] * sx;
20565      dest[i + 1] = ty + src[i] * sy;
20566    }
20567    return dest;
20568  }
20569  static _translate(src, tx, ty, dest) {
20570    dest ||= new Float32Array(src.length);
20571    for (let i = 0, ii = src.length; i < ii; i += 2) {
20572      dest[i] = tx + src[i];
20573      dest[i + 1] = ty + src[i + 1];
20574    }
20575    return dest;
20576  }
20577  static svgRound(x) {
20578    return Math.round(x * 10000);
20579  }
20580  static _normalizePoint(x, y, parentWidth, parentHeight, rotation) {
20581    switch (rotation) {
20582      case 90:
20583        return [1 - y / parentWidth, x / parentHeight];
20584      case 180:
20585        return [1 - x / parentWidth, 1 - y / parentHeight];
20586      case 270:
20587        return [y / parentWidth, 1 - x / parentHeight];
20588      default:
20589        return [x / parentWidth, y / parentHeight];
20590    }
20591  }
20592  static _normalizePagePoint(x, y, rotation) {
20593    switch (rotation) {
20594      case 90:
20595        return [1 - y, x];
20596      case 180:
20597        return [1 - x, 1 - y];
20598      case 270:
20599        return [y, 1 - x];
20600      default:
20601        return [x, y];
20602    }
20603  }
20604  static createBezierPoints(x1, y1, x2, y2, x3, y3) {
20605    return [(x1 + 5 * x2) / 6, (y1 + 5 * y2) / 6, (5 * x2 + x3) / 6, (5 * y2 + y3) / 6, (x2 + x3) / 2, (y2 + y3) / 2];
20606  }
20607}
20608
20609;// ./src/display/editor/drawers/freedraw.js
20610
20611
20612class FreeDrawOutliner {
20613  #box;
20614  #bottom = [];
20615  #innerMargin;
20616  #isLTR;
20617  #top = [];
20618  #last = new Float32Array(18);
20619  #lastX;
20620  #lastY;
20621  #min;
20622  #min_dist;
20623  #scaleFactor;
20624  #thickness;
20625  #points = [];
20626  static #MIN_DIST = 8;
20627  static #MIN_DIFF = 2;
20628  static #MIN = FreeDrawOutliner.#MIN_DIST + FreeDrawOutliner.#MIN_DIFF;
20629  constructor({
20630    x,
20631    y
20632  }, box, scaleFactor, thickness, isLTR, innerMargin = 0) {
20633    this.#box = box;
20634    this.#thickness = thickness * scaleFactor;
20635    this.#isLTR = isLTR;
20636    this.#last.set([NaN, NaN, NaN, NaN, x, y], 6);
20637    this.#innerMargin = innerMargin;
20638    this.#min_dist = FreeDrawOutliner.#MIN_DIST * scaleFactor;
20639    this.#min = FreeDrawOutliner.#MIN * scaleFactor;
20640    this.#scaleFactor = scaleFactor;
20641    this.#points.push(x, y);
20642  }
20643  isEmpty() {
20644    return isNaN(this.#last[8]);
20645  }
20646  #getLastCoords() {
20647    const lastTop = this.#last.subarray(4, 6);
20648    const lastBottom = this.#last.subarray(16, 18);
20649    const [x, y, width, height] = this.#box;
20650    return [(this.#lastX + (lastTop[0] - lastBottom[0]) / 2 - x) / width, (this.#lastY + (lastTop[1] - lastBottom[1]) / 2 - y) / height, (this.#lastX + (lastBottom[0] - lastTop[0]) / 2 - x) / width, (this.#lastY + (lastBottom[1] - lastTop[1]) / 2 - y) / height];
20651  }
20652  add({
20653    x,
20654    y
20655  }
vendor: 11,269 bytes, lines 20655-20919
20655) {
20656    this.#lastX = x;
20657    this.#lastY = y;
20658    const [layerX, layerY, layerWidth, layerHeight] = this.#box;
20659    let [x1, y1, x2, y2] = this.#last.subarray(8, 12);
20660    const diffX = x - x2;
20661    const diffY = y - y2;
20662    const d = Math.hypot(diffX, diffY);
20663    if (d < this.#min) {
20664      return false;
20665    }
20666    const diffD = d - this.#min_dist;
20667    const K = diffD / d;
20668    const shiftX = K * diffX;
20669    const shiftY = K * diffY;
20670    let x0 = x1;
20671    let y0 = y1;
20672    x1 = x2;
20673    y1 = y2;
20674    x2 += shiftX;
20675    y2 += shiftY;
20676    this.#points?.push(x, y);
20677    const nX = -shiftY / diffD;
20678    const nY = shiftX / diffD;
20679    const thX = nX * this.#thickness;
20680    const thY = nY * this.#thickness;
20681    this.#last.set(this.#last.subarray(2, 8), 0);
20682    this.#last.set([x2 + thX, y2 + thY], 4);
20683    this.#last.set(this.#last.subarray(14, 18), 12);
20684    this.#last.set([x2 - thX, y2 - thY], 16);
20685    if (isNaN(this.#last[6])) {
20686      if (this.#top.length === 0) {
20687        this.#last.set([x1 + thX, y1 + thY], 2);
20688        this.#top.push(NaN, NaN, NaN, NaN, (x1 + thX - layerX) / layerWidth, (y1 + thY - layerY) / layerHeight);
20689        this.#last.set([x1 - thX, y1 - thY], 14);
20690        this.#bottom.push(NaN, NaN, NaN, NaN, (x1 - thX - layerX) / layerWidth, (y1 - thY - layerY) / layerHeight);
20691      }
20692      this.#last.set([x0, y0, x1, y1, x2, y2], 6);
20693      return !this.isEmpty();
20694    }
20695    this.#last.set([x0, y0, x1, y1, x2, y2], 6);
20696    const angle = Math.abs(Math.atan2(y0 - y1, x0 - x1) - Math.atan2(shiftY, shiftX));
20697    if (angle < Math.PI / 2) {
20698      [x1, y1, x2, y2] = this.#last.subarray(2, 6);
20699      this.#top.push(NaN, NaN, NaN, NaN, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight);
20700      [x1, y1, x0, y0] = this.#last.subarray(14, 18);
20701      this.#bottom.push(NaN, NaN, NaN, NaN, ((x0 + x1) / 2 - layerX) / layerWidth, ((y0 + y1) / 2 - layerY) / layerHeight);
20702      return true;
20703    }
20704    [x0, y0, x1, y1, x2, y2] = this.#last.subarray(0, 6);
20705    this.#top.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight);
20706    [x2, y2, x1, y1, x0, y0] = this.#last.subarray(12, 18);
20707    this.#bottom.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight);
20708    return true;
20709  }
20710  toSVGPath() {
20711    if (this.isEmpty()) {
20712      return "";
20713    }
20714    const top = this.#top;
20715    const bottom = this.#bottom;
20716    if (isNaN(this.#last[6]) && !this.isEmpty()) {
20717      return this.#toSVGPathTwoPoints();
20718    }
20719    const buffer = [];
20720    buffer.push(`M${top[4]} ${top[5]}`);
20721    for (let i = 6; i < top.length; i += 6) {
20722      if (isNaN(top[i])) {
20723        buffer.push(`L${top[i + 4]} ${top[i + 5]}`);
20724      } else {
20725        buffer.push(`C${top[i]} ${top[i + 1]} ${top[i + 2]} ${top[i + 3]} ${top[i + 4]} ${top[i + 5]}`);
20726      }
20727    }
20728    this.#toSVGPathEnd(buffer);
20729    for (let i = bottom.length - 6; i >= 6; i -= 6) {
20730      if (isNaN(bottom[i])) {
20731        buffer.push(`L${bottom[i + 4]} ${bottom[i + 5]}`);
20732      } else {
20733        buffer.push(`C${bottom[i]} ${bottom[i + 1]} ${bottom[i + 2]} ${bottom[i + 3]} ${bottom[i + 4]} ${bottom[i + 5]}`);
20734      }
20735    }
20736    this.#toSVGPathStart(buffer);
20737    return buffer.join(" ");
20738  }
20739  #toSVGPathTwoPoints() {
20740    const [x, y, width, height] = this.#box;
20741    const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords();
20742    return `M${(this.#last[2] - x) / width} ${(this.#last[3] - y) / height} L${(this.#last[4] - x) / width} ${(this.#last[5] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(this.#last[16] - x) / width} ${(this.#last[17] - y) / height} L${(this.#last[14] - x) / width} ${(this.#last[15] - y) / height} Z`;
20743  }
20744  #toSVGPathStart(buffer) {
20745    const bottom = this.#bottom;
20746    buffer.push(`L${bottom[4]} ${bottom[5]} Z`);
20747  }
20748  #toSVGPathEnd(buffer) {
20749    const [x, y, width, height] = this.#box;
20750    const lastTop = this.#last.subarray(4, 6);
20751    const lastBottom = this.#last.subarray(16, 18);
20752    const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords();
20753    buffer.push(`L${(lastTop[0] - x) / width} ${(lastTop[1] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(lastBottom[0] - x) / width} ${(lastBottom[1] - y) / height}`);
20754  }
20755  newFreeDrawOutline(outline, points, box, scaleFactor, innerMargin, isLTR) {
20756    return new FreeDrawOutline(outline, points, box, scaleFactor, innerMargin, isLTR);
20757  }
20758  getOutlines() {
20759    const top = this.#top;
20760    const bottom = this.#bottom;
20761    const last = this.#last;
20762    const [layerX, layerY, layerWidth, layerHeight] = this.#box;
20763    const points = new Float32Array((this.#points?.length ?? 0) + 2);
20764    for (let i = 0, ii = points.length - 2; i < ii; i += 2) {
20765      points[i] = (this.#points[i] - layerX) / layerWidth;
20766      points[i + 1] = (this.#points[i + 1] - layerY) / layerHeight;
20767    }
20768    points[points.length - 2] = (this.#lastX - layerX) / layerWidth;
20769    points[points.length - 1] = (this.#lastY - layerY) / layerHeight;
20770    if (isNaN(last[6]) && !this.isEmpty()) {
20771      return this.#getOutlineTwoPoints(points);
20772    }
20773    const outline = new Float32Array(this.#top.length + 24 + this.#bottom.length);
20774    let N = top.length;
20775    for (let i = 0; i < N; i += 2) {
20776      if (isNaN(top[i])) {
20777        outline[i] = outline[i + 1] = NaN;
20778        continue;
20779      }
20780      outline[i] = top[i];
20781      outline[i + 1] = top[i + 1];
20782    }
20783    N = this.#getOutlineEnd(outline, N);
20784    for (let i = bottom.length - 6; i >= 6; i -= 6) {
20785      for (let j = 0; j < 6; j += 2) {
20786        if (isNaN(bottom[i + j])) {
20787          outline[N] = outline[N + 1] = NaN;
20788          N += 2;
20789          continue;
20790        }
20791        outline[N] = bottom[i + j];
20792        outline[N + 1] = bottom[i + j + 1];
20793        N += 2;
20794      }
20795    }
20796    this.#getOutlineStart(outline, N);
20797    return this.newFreeDrawOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR);
20798  }
20799  #getOutlineTwoPoints(points) {
20800    const last = this.#last;
20801    const [layerX, layerY, layerWidth, layerHeight] = this.#box;
20802    const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords();
20803    const outline = new Float32Array(36);
20804    outline.set([NaN, NaN, NaN, NaN, (last[2] - layerX) / layerWidth, (last[3] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[4] - layerX) / layerWidth, (last[5] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (last[16] - layerX) / layerWidth, (last[17] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[14] - layerX) / layerWidth, (last[15] - layerY) / layerHeight], 0);
20805    return this.newFreeDrawOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR);
20806  }
20807  #getOutlineStart(outline, pos) {
20808    const bottom = this.#bottom;
20809    outline.set([NaN, NaN, NaN, NaN, bottom[4], bottom[5]], pos);
20810    return pos += 6;
20811  }
20812  #getOutlineEnd(outline, pos) {
20813    const lastTop = this.#last.subarray(4, 6);
20814    const lastBottom = this.#last.subarray(16, 18);
20815    const [layerX, layerY, layerWidth, layerHeight] = this.#box;
20816    const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords();
20817    outline.set([NaN, NaN, NaN, NaN, (lastTop[0] - layerX) / layerWidth, (lastTop[1] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (lastBottom[0] - layerX) / layerWidth, (lastBottom[1] - layerY) / layerHeight], pos);
20818    return pos += 24;
20819  }
20820}
20821class FreeDrawOutline extends Outline {
20822  #box;
20823  #bbox = new Float32Array(4);
20824  #innerMargin;
20825  #isLTR;
20826  #points;
20827  #scaleFactor;
20828  #outline;
20829  constructor(outline, points, box, scaleFactor, innerMargin, isLTR) {
20830    super();
20831    this.#outline = outline;
20832    this.#points = points;
20833    this.#box = box;
20834    this.#scaleFactor = scaleFactor;
20835    this.#innerMargin = innerMargin;
20836    this.#isLTR = isLTR;
20837    this.firstPoint = [NaN, NaN];
20838    this.lastPoint = [NaN, NaN];
20839    this.#computeMinMax(isLTR);
20840    const [x, y, width, height] = this.#bbox;
20841    for (let i = 0, ii = outline.length; i < ii; i += 2) {
20842      outline[i] = (outline[i] - x) / width;
20843      outline[i + 1] = (outline[i + 1] - y) / height;
20844    }
20845    for (let i = 0, ii = points.length; i < ii; i += 2) {
20846      points[i] = (points[i] - x) / width;
20847      points[i + 1] = (points[i + 1] - y) / height;
20848    }
20849  }
20850  toSVGPath() {
20851    const buffer = [`M${this.#outline[4]} ${this.#outline[5]}`];
20852    for (let i = 6, ii = this.#outline.length; i < ii; i += 6) {
20853      if (isNaN(this.#outline[i])) {
20854        buffer.push(`L${this.#outline[i + 4]} ${this.#outline[i + 5]}`);
20855        continue;
20856      }
20857      buffer.push(`C${this.#outline[i]} ${this.#outline[i + 1]} ${this.#outline[i + 2]} ${this.#outline[i + 3]} ${this.#outline[i + 4]} ${this.#outline[i + 5]}`);
20858    }
20859    buffer.push("Z");
20860    return buffer.join(" ");
20861  }
20862  serialize([blX, blY, trX, trY], rotation) {
20863    const width = trX - blX;
20864    const height = trY - blY;
20865    let outline;
20866    let points;
20867    switch (rotation) {
20868      case 0:
20869        outline = Outline._rescale(this.#outline, blX, trY, width, -height);
20870        points = Outline._rescale(this.#points, blX, trY, width, -height);
20871        break;
20872      case 90:
20873        outline = Outline._rescaleAndSwap(this.#outline, blX, blY, width, height);
20874        points = Outline._rescaleAndSwap(this.#points, blX, blY, width, height);
20875        break;
20876      case 180:
20877        outline = Outline._rescale(this.#outline, trX, blY, -width, height);
20878        points = Outline._rescale(this.#points, trX, blY, -width, height);
20879        break;
20880      case 270:
20881        outline = Outline._rescaleAndSwap(this.#outline, trX, trY, -width, -height);
20882        points = Outline._rescaleAndSwap(this.#points, trX, trY, -width, -height);
20883        break;
20884    }
20885    return {
20886      outline: Array.from(outline),
20887      points: [Array.from(points)]
20888    };
20889  }
20890  #computeMinMax(isLTR) {
20891    const outline = this.#outline;
20892    let lastX = outline[4];
20893    let lastY = outline[5];
20894    const minMax = [lastX, lastY, lastX, lastY];
20895    let firstPointX = lastX;
20896    let firstPointY = lastY;
20897    let lastPointX = lastX;
20898    let lastPointY = lastY;
20899    const ltrCallback = isLTR ? Math.max : Math.min;
20900    const bezierBbox = new Float32Array(4);
20901    for (let i = 6, ii = outline.length; i < ii; i += 6) {
20902      const x = outline[i + 4],
20903        y = outline[i + 5];
20904      if (isNaN(outline[i])) {
20905        Util.pointBoundingBox(x, y, minMax);
20906        if (firstPointY > y) {
20907          firstPointX = x;
20908          firstPointY = y;
20909        } else if (firstPointY === y) {
20910          firstPointX = ltrCallback(firstPointX, x);
20911        }
20912        if (lastPointY < y) {
20913          lastPointX = x;
20914          lastPointY = y;
20915        } else if (lastPointY === y) {
20916          lastPointX = ltrCallback(lastPointX, x);
20917        }
20918      } else {
20919        bezierBbox
vendor: 46,763 bytes, lines 20919-22555
20919[0] = bezierBbox[1] = Infinity;
20920        bezierBbox[2] = bezierBbox[3] = -Infinity;
20921        Util.bezierBoundingBox(lastX, lastY, ...outline.slice(i, i + 6), bezierBbox);
20922        Util.rectBoundingBox(bezierBbox[0], bezierBbox[1], bezierBbox[2], bezierBbox[3], minMax);
20923        if (firstPointY > bezierBbox[1]) {
20924          firstPointX = bezierBbox[0];
20925          firstPointY = bezierBbox[1];
20926        } else if (firstPointY === bezierBbox[1]) {
20927          firstPointX = ltrCallback(firstPointX, bezierBbox[0]);
20928        }
20929        if (lastPointY < bezierBbox[3]) {
20930          lastPointX = bezierBbox[2];
20931          lastPointY = bezierBbox[3];
20932        } else if (lastPointY === bezierBbox[3]) {
20933          lastPointX = ltrCallback(lastPointX, bezierBbox[2]);
20934        }
20935      }
20936      lastX = x;
20937      lastY = y;
20938    }
20939    const bbox = this.#bbox;
20940    bbox[0] = minMax[0] - this.#innerMargin;
20941    bbox[1] = minMax[1] - this.#innerMargin;
20942    bbox[2] = minMax[2] - minMax[0] + 2 * this.#innerMargin;
20943    bbox[3] = minMax[3] - minMax[1] + 2 * this.#innerMargin;
20944    this.firstPoint = [firstPointX, firstPointY];
20945    this.lastPoint = [lastPointX, lastPointY];
20946  }
20947  get box() {
20948    return this.#bbox;
20949  }
20950  newOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin = 0) {
20951    return new FreeDrawOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin);
20952  }
20953  getNewOutline(thickness, innerMargin) {
20954    const [x, y, width, height] = this.#bbox;
20955    const [layerX, layerY, layerWidth, layerHeight] = this.#box;
20956    const sx = width * layerWidth;
20957    const sy = height * layerHeight;
20958    const tx = x * layerWidth + layerX;
20959    const ty = y * layerHeight + layerY;
20960    const outliner = this.newOutliner({
20961      x: this.#points[0] * sx + tx,
20962      y: this.#points[1] * sy + ty
20963    }, this.#box, this.#scaleFactor, thickness, this.#isLTR, innerMargin ?? this.#innerMargin);
20964    for (let i = 2; i < this.#points.length; i += 2) {
20965      outliner.add({
20966        x: this.#points[i] * sx + tx,
20967        y: this.#points[i + 1] * sy + ty
20968      });
20969    }
20970    return outliner.getOutlines();
20971  }
20972}
20973
20974;// ./src/display/editor/drawers/highlight.js
20975
20976
20977
20978class HighlightOutliner {
20979  #box;
20980  #firstPoint;
20981  #lastPoint;
20982  #verticalEdges = [];
20983  #intervals = [];
20984  constructor(boxes, borderWidth = 0, innerMargin = 0, isLTR = true) {
20985    const minMax = [Infinity, Infinity, -Infinity, -Infinity];
20986    const NUMBER_OF_DIGITS = 4;
20987    const EPSILON = 10 ** -NUMBER_OF_DIGITS;
20988    for (const {
20989      x,
20990      y,
20991      width,
20992      height
20993    } of boxes) {
20994      const x1 = Math.floor((x - borderWidth) / EPSILON) * EPSILON;
20995      const x2 = Math.ceil((x + width + borderWidth) / EPSILON) * EPSILON;
20996      const y1 = Math.floor((y - borderWidth) / EPSILON) * EPSILON;
20997      const y2 = Math.ceil((y + height + borderWidth) / EPSILON) * EPSILON;
20998      const left = [x1, y1, y2, true];
20999      const right = [x2, y1, y2, false];
21000      this.#verticalEdges.push(left, right);
21001      Util.rectBoundingBox(x1, y1, x2, y2, minMax);
21002    }
21003    const bboxWidth = minMax[2] - minMax[0] + 2 * innerMargin;
21004    const bboxHeight = minMax[3] - minMax[1] + 2 * innerMargin;
21005    const shiftedMinX = minMax[0] - innerMargin;
21006    const shiftedMinY = minMax[1] - innerMargin;
21007    let firstPointX = isLTR ? -Infinity : Infinity;
21008    let firstPointY = Infinity;
21009    const lastEdge = this.#verticalEdges.at(isLTR ? -1 : -2);
21010    const lastPoint = [lastEdge[0], lastEdge[2]];
21011    for (const edge of this.#verticalEdges) {
21012      const [x, y1, y2, left] = edge;
21013      if (!left && isLTR) {
21014        if (y1 < firstPointY) {
21015          firstPointY = y1;
21016          firstPointX = x;
21017        } else if (y1 === firstPointY) {
21018          firstPointX = Math.max(firstPointX, x);
21019        }
21020      } else if (left && !isLTR) {
21021        if (y1 < firstPointY) {
21022          firstPointY = y1;
21023          firstPointX = x;
21024        } else if (y1 === firstPointY) {
21025          firstPointX = Math.min(firstPointX, x);
21026        }
21027      }
21028      edge[0] = (x - shiftedMinX) / bboxWidth;
21029      edge[1] = (y1 - shiftedMinY) / bboxHeight;
21030      edge[2] = (y2 - shiftedMinY) / bboxHeight;
21031    }
21032    this.#box = new Float32Array([shiftedMinX, shiftedMinY, bboxWidth, bboxHeight]);
21033    this.#firstPoint = [firstPointX, firstPointY];
21034    this.#lastPoint = lastPoint;
21035  }
21036  getOutlines() {
21037    this.#verticalEdges.sort((a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2]);
21038    const outlineVerticalEdges = [];
21039    for (const edge of this.#verticalEdges) {
21040      if (edge[3]) {
21041        outlineVerticalEdges.push(...this.#breakEdge(edge));
21042        this.#insert(edge);
21043      } else {
21044        this.#remove(edge);
21045        outlineVerticalEdges.push(...this.#breakEdge(edge));
21046      }
21047    }
21048    return this.#getOutlines(outlineVerticalEdges);
21049  }
21050  #getOutlines(outlineVerticalEdges) {
21051    const edges = [];
21052    const allEdges = new Set();
21053    for (const edge of outlineVerticalEdges) {
21054      const [x, y1, y2] = edge;
21055      edges.push([x, y1, edge], [x, y2, edge]);
21056    }
21057    edges.sort((a, b) => a[1] - b[1] || a[0] - b[0]);
21058    for (let i = 0, ii = edges.length; i < ii; i += 2) {
21059      const edge1 = edges[i][2];
21060      const edge2 = edges[i + 1][2];
21061      edge1.push(edge2);
21062      edge2.push(edge1);
21063      allEdges.add(edge1);
21064      allEdges.add(edge2);
21065    }
21066    const outlines = [];
21067    let outline;
21068    while (allEdges.size > 0) {
21069      const edge = allEdges.values().next().value;
21070      let [x, y1, y2, edge1, edge2] = edge;
21071      allEdges.delete(edge);
21072      let lastPointX = x;
21073      let lastPointY = y1;
21074      outline = [x, y2];
21075      outlines.push(outline);
21076      while (true) {
21077        let e;
21078        if (allEdges.has(edge1)) {
21079          e = edge1;
21080        } else if (allEdges.has(edge2)) {
21081          e = edge2;
21082        } else {
21083          break;
21084        }
21085        allEdges.delete(e);
21086        [x, y1, y2, edge1, edge2] = e;
21087        if (lastPointX !== x) {
21088          outline.push(lastPointX, lastPointY, x, lastPointY === y1 ? y1 : y2);
21089          lastPointX = x;
21090        }
21091        lastPointY = lastPointY === y1 ? y2 : y1;
21092      }
21093      outline.push(lastPointX, lastPointY);
21094    }
21095    return new HighlightOutline(outlines, this.#box, this.#firstPoint, this.#lastPoint);
21096  }
21097  #binarySearch(y) {
21098    const array = this.#intervals;
21099    let start = 0;
21100    let end = array.length - 1;
21101    while (start <= end) {
21102      const middle = start + end >> 1;
21103      const y1 = array[middle][0];
21104      if (y1 === y) {
21105        return middle;
21106      }
21107      if (y1 < y) {
21108        start = middle + 1;
21109      } else {
21110        end = middle - 1;
21111      }
21112    }
21113    return end + 1;
21114  }
21115  #insert([, y1, y2]) {
21116    const index = this.#binarySearch(y1);
21117    this.#intervals.splice(index, 0, [y1, y2]);
21118  }
21119  #remove([, y1, y2]) {
21120    const index = this.#binarySearch(y1);
21121    for (let i = index; i < this.#intervals.length; i++) {
21122      const [start, end] = this.#intervals[i];
21123      if (start !== y1) {
21124        break;
21125      }
21126      if (start === y1 && end === y2) {
21127        this.#intervals.splice(i, 1);
21128        return;
21129      }
21130    }
21131    for (let i = index - 1; i >= 0; i--) {
21132      const [start, end] = this.#intervals[i];
21133      if (start !== y1) {
21134        break;
21135      }
21136      if (start === y1 && end === y2) {
21137        this.#intervals.splice(i, 1);
21138        return;
21139      }
21140    }
21141  }
21142  #breakEdge(edge) {
21143    const [x, y1, y2] = edge;
21144    const results = [[x, y1, y2]];
21145    const index = this.#binarySearch(y2);
21146    for (let i = 0; i < index; i++) {
21147      const [start, end] = this.#intervals[i];
21148      for (let j = 0, jj = results.length; j < jj; j++) {
21149        const [, y3, y4] = results[j];
21150        if (end <= y3 || y4 <= start) {
21151          continue;
21152        }
21153        if (y3 >= start) {
21154          if (y4 > end) {
21155            results[j][1] = end;
21156          } else {
21157            if (jj === 1) {
21158              return [];
21159            }
21160            results.splice(j, 1);
21161            j--;
21162            jj--;
21163          }
21164          continue;
21165        }
21166        results[j][2] = start;
21167        if (y4 > end) {
21168          results.push([x, end, y4]);
21169        }
21170      }
21171    }
21172    return results;
21173  }
21174}
21175class HighlightOutline extends Outline {
21176  #box;
21177  #outlines;
21178  constructor(outlines, box, firstPoint, lastPoint) {
21179    super();
21180    this.#outlines = outlines;
21181    this.#box = box;
21182    this.firstPoint = firstPoint;
21183    this.lastPoint = lastPoint;
21184  }
21185  toSVGPath() {
21186    const buffer = [];
21187    for (const polygon of this.#outlines) {
21188      let [prevX, prevY] = polygon;
21189      buffer.push(`M${prevX} ${prevY}`);
21190      for (let i = 2; i < polygon.length; i += 2) {
21191        const x = polygon[i];
21192        const y = polygon[i + 1];
21193        if (x === prevX) {
21194          buffer.push(`V${y}`);
21195          prevY = y;
21196        } else if (y === prevY) {
21197          buffer.push(`H${x}`);
21198          prevX = x;
21199        }
21200      }
21201      buffer.push("Z");
21202    }
21203    return buffer.join(" ");
21204  }
21205  serialize([blX, blY, trX, trY], _rotation) {
21206    const outlines = [];
21207    const width = trX - blX;
21208    const height = trY - blY;
21209    for (const outline of this.#outlines) {
21210      const points = new Array(outline.length);
21211      for (let i = 0; i < outline.length; i += 2) {
21212        points[i] = blX + outline[i] * width;
21213        points[i + 1] = trY - outline[i + 1] * height;
21214      }
21215      outlines.push(points);
21216    }
21217    return outlines;
21218  }
21219  get box() {
21220    return this.#box;
21221  }
21222  get classNamesForOutlining() {
21223    return ["highlightOutline"];
21224  }
21225}
21226class FreeHighlightOutliner extends FreeDrawOutliner {
21227  newFreeDrawOutline(outline, points, box, scaleFactor, innerMargin, isLTR) {
21228    return new FreeHighlightOutline(outline, points, box, scaleFactor, innerMargin, isLTR);
21229  }
21230}
21231class FreeHighlightOutline extends FreeDrawOutline {
21232  newOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin = 0) {
21233    return new FreeHighlightOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin);
21234  }
21235}
21236
21237;// ./src/display/editor/highlight.js
21238
21239
21240
21241
21242
21243
21244
21245class HighlightEditor extends AnnotationEditor {
21246  #anchorNode = null;
21247  #anchorOffset = 0;
21248  #boxes;
21249  #clipPathId = null;
21250  #colorPicker = null;
21251  #focusOutlines = null;
21252  #focusNode = null;
21253  #focusOffset = 0;
21254  #highlightDiv = null;
21255  #highlightOutlines = null;
21256  #id = null;
21257  #isFreeHighlight = false;
21258  #firstPoint = null;
21259  #lastPoint = null;
21260  #outlineId = null;
21261  #text = "";
21262  #thickness;
21263  #methodOfCreation = "";
21264  static _defaultColor = null;
21265  static _defaultOpacity = 1;
21266  static _defaultThickness = 12;
21267  static _type = "highlight";
21268  static _editorType = AnnotationEditorType.HIGHLIGHT;
21269  static _freeHighlightId = -1;
21270  static _freeHighlight = null;
21271  static _freeHighlightClipId = "";
21272  static get _keyboardManager() {
21273    const proto = HighlightEditor.prototype;
21274    return shadow(this, "_keyboardManager", new KeyboardManager([[["ArrowLeft", "mac+ArrowLeft"], proto._moveCaret, {
21275      args: [0]
21276    }], [["ArrowRight", "mac+ArrowRight"], proto._moveCaret, {
21277      args: [1]
21278    }], [["ArrowUp", "mac+ArrowUp"], proto._moveCaret, {
21279      args: [2]
21280    }], [["ArrowDown", "mac+ArrowDown"], proto._moveCaret, {
21281      args: [3]
21282    }]]));
21283  }
21284  constructor(params) {
21285    super({
21286      ...params,
21287      name: "highlightEditor"
21288    });
21289    this.color = params.color || HighlightEditor._defaultColor;
21290    this.#thickness = params.thickness || HighlightEditor._defaultThickness;
21291    this.opacity = params.opacity || HighlightEditor._defaultOpacity;
21292    this.#boxes = params.boxes || null;
21293    this.#methodOfCreation = params.methodOfCreation || "";
21294    this.#text = params.text || "";
21295    this._isDraggable = false;
21296    this.defaultL10nId = "pdfjs-editor-highlight-editor";
21297    if (params.highlightId > -1) {
21298      this.#isFreeHighlight = true;
21299      this.#createFreeOutlines(params);
21300      this.#addToDrawLayer();
21301    } else if (this.#boxes) {
21302      this.#anchorNode = params.anchorNode;
21303      this.#anchorOffset = params.anchorOffset;
21304      this.#focusNode = params.focusNode;
21305      this.#focusOffset = params.focusOffset;
21306      this.#createOutlines();
21307      this.#addToDrawLayer();
21308      this.rotate(this.rotation);
21309    }
21310    if (!this.annotationElementId) {
21311      this._uiManager.a11yAlert("pdfjs-editor-highlight-added-alert");
21312    }
21313  }
21314  get telemetryInitialData() {
21315    return {
21316      action: "added",
21317      type: this.#isFreeHighlight ? "free_highlight" : "highlight",
21318      color: this._uiManager.getNonHCMColorName(this.color),
21319      thickness: this.#thickness,
21320      methodOfCreation: this.#methodOfCreation
21321    };
21322  }
21323  get telemetryFinalData() {
21324    return {
21325      type: "highlight",
21326      color: this._uiManager.getNonHCMColorName(this.color)
21327    };
21328  }
21329  static computeTelemetryFinalData(data) {
21330    return {
21331      numberOfColors: data.get("color").size
21332    };
21333  }
21334  #createOutlines() {
21335    const outliner = new HighlightOutliner(this.#boxes, 0.001);
21336    this.#highlightOutlines = outliner.getOutlines();
21337    [this.x, this.y, this.width, this.height] = this.#highlightOutlines.box;
21338    const outlinerForOutline = new HighlightOutliner(this.#boxes, 0.0025, 0.001, this._uiManager.direction === "ltr");
21339    this.#focusOutlines = outlinerForOutline.getOutlines();
21340    const {
21341      firstPoint
21342    } = this.#highlightOutlines;
21343    this.#firstPoint = [(firstPoint[0] - this.x) / this.width, (firstPoint[1] - this.y) / this.height];
21344    const {
21345      lastPoint
21346    } = this.#focusOutlines;
21347    this.#lastPoint = [(lastPoint[0] - this.x) / this.width, (lastPoint[1] - this.y) / this.height];
21348  }
21349  #createFreeOutlines({
21350    highlightOutlines,
21351    highlightId,
21352    clipPathId
21353  }) {
21354    this.#highlightOutlines = highlightOutlines;
21355    const extraThickness = 1.5;
21356    this.#focusOutlines = highlightOutlines.getNewOutline(this.#thickness / 2 + extraThickness, 0.0025);
21357    if (highlightId >= 0) {
21358      this.#id = highlightId;
21359      this.#clipPathId = clipPathId;
21360      this.parent.drawLayer.finalizeDraw(highlightId, {
21361        bbox: highlightOutlines.box,
21362        path: {
21363          d: highlightOutlines.toSVGPath()
21364        }
21365      });
21366      this.#outlineId = this.parent.drawLayer.drawOutline({
21367        rootClass: {
21368          highlightOutline: true,
21369          free: true
21370        },
21371        bbox: this.#focusOutlines.box,
21372        path: {
21373          d: this.#focusOutlines.toSVGPath()
21374        }
21375      }, true);
21376    } else if (this.parent) {
21377      const angle = this.parent.viewport.rotation;
21378      this.parent.drawLayer.updateProperties(this.#id, {
21379        bbox: HighlightEditor.#rotateBbox(this.#highlightOutlines.box, (angle - this.rotation + 360) % 360),
21380        path: {
21381          d: highlightOutlines.toSVGPath()
21382        }
21383      });
21384      this.parent.drawLayer.updateProperties(this.#outlineId, {
21385        bbox: HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle),
21386        path: {
21387          d: this.#focusOutlines.toSVGPath()
21388        }
21389      });
21390    }
21391    const [x, y, width, height] = highlightOutlines.box;
21392    switch (this.rotation) {
21393      case 0:
21394        this.x = x;
21395        this.y = y;
21396        this.width = width;
21397        this.height = height;
21398        break;
21399      case 90:
21400        {
21401          const [pageWidth, pageHeight] = this.parentDimensions;
21402          this.x = y;
21403          this.y = 1 - x;
21404          this.width = width * pageHeight / pageWidth;
21405          this.height = height * pageWidth / pageHeight;
21406          break;
21407        }
21408      case 180:
21409        this.x = 1 - x;
21410        this.y = 1 - y;
21411        this.width = width;
21412        this.height = height;
21413        break;
21414      case 270:
21415        {
21416          const [pageWidth, pageHeight] = this.parentDimensions;
21417          this.x = 1 - y;
21418          this.y = x;
21419          this.width = width * pageHeight / pageWidth;
21420          this.height = height * pageWidth / pageHeight;
21421          break;
21422        }
21423    }
21424    const {
21425      firstPoint
21426    } = highlightOutlines;
21427    this.#firstPoint = [(firstPoint[0] - x) / width, (firstPoint[1] - y) / height];
21428    const {
21429      lastPoint
21430    } = this.#focusOutlines;
21431    this.#lastPoint = [(lastPoint[0] - x) / width, (lastPoint[1] - y) / height];
21432  }
21433  static initialize(l10n, uiManager) {
21434    AnnotationEditor.initialize(l10n, uiManager);
21435    HighlightEditor._defaultColor ||= uiManager.highlightColors?.values().next().value || "#fff066";
21436  }
21437  static updateDefaultParams(type, value) {
21438    switch (type) {
21439      case AnnotationEditorParamsType.HIGHLIGHT_COLOR:
21440        HighlightEditor._defaultColor = value;
21441        break;
21442      case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS:
21443        HighlightEditor._defaultThickness = value;
21444        break;
21445    }
21446  }
21447  translateInPage(x, y) {}
21448  get toolbarPosition() {
21449    return this.#lastPoint;
21450  }
21451  get commentButtonPosition() {
21452    return this.#firstPoint;
21453  }
21454  updateParams(type, value) {
21455    switch (type) {
21456      case AnnotationEditorParamsType.HIGHLIGHT_COLOR:
21457        this.#updateColor(value);
21458        break;
21459      case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS:
21460        this.#updateThickness(value);
21461        break;
21462    }
21463  }
21464  static get defaultPropertiesToUpdate() {
21465    return [[AnnotationEditorParamsType.HIGHLIGHT_COLOR, HighlightEditor._defaultColor], [AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, HighlightEditor._defaultThickness]];
21466  }
21467  get propertiesToUpdate() {
21468    return [[AnnotationEditorParamsType.HIGHLIGHT_COLOR, this.color || HighlightEditor._defaultColor], [AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, this.#thickness || HighlightEditor._defaultThickness], [AnnotationEditorParamsType.HIGHLIGHT_FREE, this.#isFreeHighlight]];
21469  }
21470  onUpdatedColor() {
21471    this.parent?.drawLayer.updateProperties(this.#id, {
21472      root: {
21473        fill: this.color,
21474        "fill-opacity": this.opacity
21475      }
21476    });
21477    this.#colorPicker?.updateColor(this.color);
21478    super.onUpdatedColor();
21479  }
21480  #updateColor(color) {
21481    const setColorAndOpacity = (col, opa) => {
21482      this.color = col;
21483      this.opacity = opa;
21484      this.onUpdatedColor();
21485    };
21486    const savedColor = this.color;
21487    const savedOpacity = this.opacity;
21488    this.addCommands({
21489      cmd: setColorAndOpacity.bind(this, color, HighlightEditor._defaultOpacity),
21490      undo: setColorAndOpacity.bind(this, savedColor, savedOpacity),
21491      post: this._uiManager.updateUI.bind(this._uiManager, this),
21492      mustExec: true,
21493      type: AnnotationEditorParamsType.HIGHLIGHT_COLOR,
21494      overwriteIfSameType: true,
21495      keepUndo: true
21496    });
21497    this._reportTelemetry({
21498      action: "color_changed",
21499      color: this._uiManager.getNonHCMColorName(color)
21500    }, true);
21501  }
21502  #updateThickness(thickness) {
21503    const savedThickness = this.#thickness;
21504    const setThickness = th => {
21505      this.#thickness = th;
21506      this.#changeThickness(th);
21507    };
21508    this.addCommands({
21509      cmd: setThickness.bind(this, thickness),
21510      undo: setThickness.bind(this, savedThickness),
21511      post: this._uiManager.updateUI.bind(this._uiManager, this),
21512      mustExec: true,
21513      type: AnnotationEditorParamsType.INK_THICKNESS,
21514      overwriteIfSameType: true,
21515      keepUndo: true
21516    });
21517    this._reportTelemetry({
21518      action: "thickness_changed",
21519      thickness
21520    }, true);
21521  }
21522  get toolbarButtons() {
21523    if (this._uiManager.highlightColors) {
21524      const colorPicker = this.#colorPicker = new ColorPicker({
21525        editor: this
21526      });
21527      return [["colorPicker", colorPicker]];
21528    }
21529    return super.toolbarButtons;
21530  }
21531  disableEditing() {
21532    super.disableEditing();
21533    this.div.classList.toggle("disabled", true);
21534  }
21535  enableEditing() {
21536    super.enableEditing();
21537    this.div.classList.toggle("disabled", false);
21538  }
21539  fixAndSetPosition() {
21540    return super.fixAndSetPosition(this.#getRotation());
21541  }
21542  getBaseTranslation() {
21543    return [0, 0];
21544  }
21545  getRect(tx, ty) {
21546    return super.getRect(tx, ty, this.#getRotation());
21547  }
21548  onceAdded(focus) {
21549    if (!this.annotationElementId) {
21550      this.parent.addUndoableEditor(this);
21551    }
21552    if (focus) {
21553      this.div.focus();
21554    }
21555  }
21556  remove() {
21557    this.#cleanDrawLayer();
21558    this._reportTelemetry({
21559      action: "deleted"
21560    });
21561    super.remove();
21562  }
21563  rebuild() {
21564    if (!this.parent) {
21565      return;
21566    }
21567    super.rebuild();
21568    if (this.div === null) {
21569      return;
21570    }
21571    this.#addToDrawLayer();
21572    if (!this.isAttachedToDOM) {
21573      this.parent.add(this);
21574    }
21575  }
21576  setParent(parent) {
21577    let mustBeSelected = false;
21578    if (this.parent && !parent) {
21579      this.#cleanDrawLayer();
21580    } else if (parent) {
21581      this.#addToDrawLayer(parent);
21582      mustBeSelected = !this.parent && this.div?.classList.contains("selectedEditor");
21583    }
21584    super.setParent(parent);
21585    this.show(this._isVisible);
21586    if (mustBeSelected) {
21587      this.select();
21588    }
21589  }
21590  #changeThickness(thickness) {
21591    if (!this.#isFreeHighlight) {
21592      return;
21593    }
21594    this.#createFreeOutlines({
21595      highlightOutlines: this.#highlightOutlines.getNewOutline(thickness / 2)
21596    });
21597    this.fixAndSetPosition();
21598    this.setDims();
21599  }
21600  #cleanDrawLayer() {
21601    if (this.#id === null || !this.parent) {
21602      return;
21603    }
21604    this.parent.drawLayer.remove(this.#id);
21605    this.#id = null;
21606    this.parent.drawLayer.remove(this.#outlineId);
21607    this.#outlineId = null;
21608  }
21609  #addToDrawLayer(parent = this.parent) {
21610    if (this.#id !== null) {
21611      return;
21612    }
21613    ({
21614      id: this.#id,
21615      clipPathId: this.#clipPathId
21616    } = parent.drawLayer.draw({
21617      bbox: this.#highlightOutlines.box,
21618      root: {
21619        viewBox: "0 0 1 1",
21620        fill: this.color,
21621        "fill-opacity": this.opacity
21622      },
21623      rootClass: {
21624        highlight: true,
21625        free: this.#isFreeHighlight
21626      },
21627      path: {
21628        d: this.#highlightOutlines.toSVGPath()
21629      }
21630    }, false, true));
21631    this.#outlineId = parent.drawLayer.drawOutline({
21632      rootClass: {
21633        highlightOutline: true,
21634        free: this.#isFreeHighlight
21635      },
21636      bbox: this.#focusOutlines.box,
21637      path: {
21638        d: this.#focusOutlines.toSVGPath()
21639      }
21640    }, this.#isFreeHighlight);
21641    if (this.#highlightDiv) {
21642      this.#highlightDiv.style.clipPath = this.#clipPathId;
21643    }
21644  }
21645  static #rotateBbox([x, y, width, height], angle) {
21646    switch (angle) {
21647      case 90:
21648        return [1 - y - height, x, height, width];
21649      case 180:
21650        return [1 - x - width, 1 - y - height, width, height];
21651      case 270:
21652        return [y, 1 - x - width, height, width];
21653    }
21654    return [x, y, width, height];
21655  }
21656  rotate(angle) {
21657    const {
21658      drawLayer
21659    } = this.parent;
21660    let box;
21661    if (this.#isFreeHighlight) {
21662      angle = (angle - this.rotation + 360) % 360;
21663      box = HighlightEditor.#rotateBbox(this.#highlightOutlines.box, angle);
21664    } else {
21665      box = HighlightEditor.#rotateBbox([this.x, this.y, this.width, this.height], angle);
21666    }
21667    drawLayer.updateProperties(this.#id, {
21668      bbox: box,
21669      root: {
21670        "data-main-rotation": angle
21671      }
21672    });
21673    drawLayer.updateProperties(this.#outlineId, {
21674      bbox: HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle),
21675      root: {
21676        "data-main-rotation": angle
21677      }
21678    });
21679  }
21680  render() {
21681    if (this.div) {
21682      return this.div;
21683    }
21684    const div = super.render();
21685    if (this.#text) {
21686      div.setAttribute("aria-label", this.#text);
21687      div.setAttribute("role", "mark");
21688    }
21689    if (this.#isFreeHighlight) {
21690      div.classList.add("free");
21691    } else {
21692      this.div.addEventListener("keydown", this.#keydown.bind(this), {
21693        signal: this._uiManager._signal
21694      });
21695    }
21696    const highlightDiv = this.#highlightDiv = document.createElement("div");
21697    div.append(highlightDiv);
21698    highlightDiv.setAttribute("aria-hidden", "true");
21699    highlightDiv.className = "internal";
21700    highlightDiv.style.clipPath = this.#clipPathId;
21701    this.setDims();
21702    bindEvents(this, this.#highlightDiv, ["pointerover", "pointerleave"]);
21703    this.enableEditing();
21704    return div;
21705  }
21706  pointerover() {
21707    if (!this.isSelected) {
21708      this.parent?.drawLayer.updateProperties(this.#outlineId, {
21709        rootClass: {
21710          hovered: true
21711        }
21712      });
21713    }
21714  }
21715  pointerleave() {
21716    if (!this.isSelected) {
21717      this.parent?.drawLayer.updateProperties(this.#outlineId, {
21718        rootClass: {
21719          hovered: false
21720        }
21721      });
21722    }
21723  }
21724  #keydown(event) {
21725    HighlightEditor._keyboardManager.exec(this, event);
21726  }
21727  _moveCaret(direction) {
21728    this.parent.unselect(this);
21729    switch (direction) {
21730      case 0:
21731      case 2:
21732        this.#setCaret(true);
21733        break;
21734      case 1:
21735      case 3:
21736        this.#setCaret(false);
21737        break;
21738    }
21739  }
21740  #setCaret(start) {
21741    if (!this.#anchorNode) {
21742      return;
21743    }
21744    const selection = window.getSelection();
21745    if (start) {
21746      selection.setPosition(this.#anchorNode, this.#anchorOffset);
21747    } else {
21748      selection.setPosition(this.#focusNode, this.#focusOffset);
21749    }
21750  }
21751  select() {
21752    super.select();
21753    if (!this.#outlineId) {
21754      return;
21755    }
21756    this.parent?.drawLayer.updateProperties(this.#outlineId, {
21757      rootClass: {
21758        hovered: false,
21759        selected: true
21760      }
21761    });
21762  }
21763  unselect() {
21764    super.unselect();
21765    if (!this.#outlineId) {
21766      return;
21767    }
21768    this.parent?.drawLayer.updateProperties(this.#outlineId, {
21769      rootClass: {
21770        selected: false
21771      }
21772    });
21773    if (!this.#isFreeHighlight) {
21774      this.#setCaret(false);
21775    }
21776  }
21777  get _mustFixPosition() {
21778    return !this.#isFreeHighlight;
21779  }
21780  show(visible = this._isVisible) {
21781    super.show(visible);
21782    if (this.parent) {
21783      this.parent.drawLayer.updateProperties(this.#id, {
21784        rootClass: {
21785          hidden: !visible
21786        }
21787      });
21788      this.parent.drawLayer.updateProperties(this.#outlineId, {
21789        rootClass: {
21790          hidden: !visible
21791        }
21792      });
21793    }
21794  }
21795  #getRotation() {
21796    return this.#isFreeHighlight ? this.rotation : 0;
21797  }
21798  #serializeBoxes() {
21799    if (this.#isFreeHighlight) {
21800      return null;
21801    }
21802    const [pageWidth, pageHeight] = this.pageDimensions;
21803    const [pageX, pageY] = this.pageTranslation;
21804    const boxes = this.#boxes;
21805    const quadPoints = new Float32Array(boxes.length * 8);
21806    let i = 0;
21807    for (const {
21808      x,
21809      y,
21810      width,
21811      height
21812    } of boxes) {
21813      const sx = x * pageWidth + pageX;
21814      const sy = (1 - y) * pageHeight + pageY;
21815      quadPoints[i] = quadPoints[i + 4] = sx;
21816      quadPoints[i + 1] = quadPoints[i + 3] = sy;
21817      quadPoints[i + 2] = quadPoints[i + 6] = sx + width * pageWidth;
21818      quadPoints[i + 5] = quadPoints[i + 7] = sy - height * pageHeight;
21819      i += 8;
21820    }
21821    return quadPoints;
21822  }
21823  #serializeOutlines(rect) {
21824    return this.#highlightOutlines.serialize(rect, this.#getRotation());
21825  }
21826  static startHighlighting(parent, isLTR, {
21827    target: textLayer,
21828    x,
21829    y
21830  }) {
21831    const {
21832      x: layerX,
21833      y: layerY,
21834      width: parentWidth,
21835      height: parentHeight
21836    } = textLayer.getBoundingClientRect();
21837    const ac = new AbortController();
21838    const signal = parent.combinedSignal(ac);
21839    const pointerUpCallback = e => {
21840      ac.abort();
21841      this.#endHighlight(parent, e);
21842    };
21843    window.addEventListener("blur", pointerUpCallback, {
21844      signal
21845    });
21846    window.addEventListener("pointerup", pointerUpCallback, {
21847      signal
21848    });
21849    window.addEventListener("pointerdown", stopEvent, {
21850      capture: true,
21851      passive: false,
21852      signal
21853    });
21854    window.addEventListener("contextmenu", noContextMenu, {
21855      signal
21856    });
21857    textLayer.addEventListener("pointermove", this.#highlightMove.bind(this, parent), {
21858      signal
21859    });
21860    this._freeHighlight = new FreeHighlightOutliner({
21861      x,
21862      y
21863    }, [layerX, layerY, parentWidth, parentHeight], parent.scale, this._defaultThickness / 2, isLTR, 0.001);
21864    ({
21865      id: this._freeHighlightId,
21866      clipPathId: this._freeHighlightClipId
21867    } = parent.drawLayer.draw({
21868      bbox: [0, 0, 1, 1],
21869      root: {
21870        viewBox: "0 0 1 1",
21871        fill: this._defaultColor,
21872        "fill-opacity": this._defaultOpacity
21873      },
21874      rootClass: {
21875        highlight: true,
21876        free: true
21877      },
21878      path: {
21879        d: this._freeHighlight.toSVGPath()
21880      }
21881    }, true, true));
21882  }
21883  static #highlightMove(parent, event) {
21884    if (this._freeHighlight.add(event)) {
21885      parent.drawLayer.updateProperties(this._freeHighlightId, {
21886        path: {
21887          d: this._freeHighlight.toSVGPath()
21888        }
21889      });
21890    }
21891  }
21892  static #endHighlight(parent, event) {
21893    if (!this._freeHighlight.isEmpty()) {
21894      parent.createAndAddNewEditor(event, false, {
21895        highlightId: this._freeHighlightId,
21896        highlightOutlines: this._freeHighlight.getOutlines(),
21897        clipPathId: this._freeHighlightClipId,
21898        methodOfCreation: "main_toolbar"
21899      });
21900    } else {
21901      parent.drawLayer.remove(this._freeHighlightId);
21902    }
21903    this._freeHighlightId = -1;
21904    this._freeHighlight = null;
21905    this._freeHighlightClipId = "";
21906  }
21907  static async deserialize(data, parent, uiManager) {
21908    let initialData = null;
21909    if (data instanceof HighlightAnnotationElement) {
21910      const {
21911        data: {
21912          quadPoints,
21913          rect,
21914          rotation,
21915          id,
21916          color,
21917          opacity,
21918          popupRef,
21919          richText,
21920          contentsObj,
21921          creationDate,
21922          modificationDate
21923        },
21924        parent: {
21925          page: {
21926            pageNumber
21927          }
21928        }
21929      } = data;
21930      initialData = data = {
21931        annotationType: AnnotationEditorType.HIGHLIGHT,
21932        color: Array.from(color),
21933        opacity,
21934        quadPoints,
21935        boxes: null,
21936        pageIndex: pageNumber - 1,
21937        rect: rect.slice(0),
21938        rotation,
21939        annotationElementId: id,
21940        id,
21941        deleted: false,
21942        popupRef,
21943        richText,
21944        comment: contentsObj?.str || null,
21945        creationDate,
21946        modificationDate
21947      };
21948    } else if (data instanceof InkAnnotationElement) {
21949      const {
21950        data: {
21951          inkLists,
21952          rect,
21953          rotation,
21954          id,
21955          color,
21956          borderStyle: {
21957            rawWidth: thickness
21958          },
21959          popupRef,
21960          richText,
21961          contentsObj,
21962          creationDate,
21963          modificationDate
21964        },
21965        parent: {
21966          page: {
21967            pageNumber
21968          }
21969        }
21970      } = data;
21971      initialData = data = {
21972        annotationType: AnnotationEditorType.HIGHLIGHT,
21973        color: Array.from(color),
21974        thickness,
21975        inkLists,
21976        boxes: null,
21977        pageIndex: pageNumber - 1,
21978        rect: rect.slice(0),
21979        rotation,
21980        annotationElementId: id,
21981        id,
21982        deleted: false,
21983        popupRef,
21984        richText,
21985        comment: contentsObj?.str || null,
21986        creationDate,
21987        modificationDate
21988      };
21989    }
21990    const {
21991      color,
21992      quadPoints,
21993      inkLists,
21994      opacity
21995    } = data;
21996    const editor = await super.deserialize(data, parent, uiManager);
21997    editor.color = Util.makeHexColor(...color);
21998    editor.opacity = opacity || 1;
21999    if (inkLists) {
22000      editor.#thickness = data.thickness;
22001    }
22002    editor._initialData = initialData;
22003    if (data.comment) {
22004      editor.setCommentData(data);
22005    }
22006    const [pageWidth, pageHeight] = editor.pageDimensions;
22007    const [pageX, pageY] = editor.pageTranslation;
22008    if (quadPoints) {
22009      const boxes = editor.#boxes = [];
22010      for (let i = 0; i < quadPoints.length; i += 8) {
22011        boxes.push({
22012          x: (quadPoints[i] - pageX) / pageWidth,
22013          y: 1 - (quadPoints[i + 1] - pageY) / pageHeight,
22014          width: (quadPoints[i + 2] - quadPoints[i]) / pageWidth,
22015          height: (quadPoints[i + 1] - quadPoints[i + 5]) / pageHeight
22016        });
22017      }
22018      editor.#createOutlines();
22019      editor.#addToDrawLayer();
22020      editor.rotate(editor.rotation);
22021    } else if (inkLists) {
22022      editor.#isFreeHighlight = true;
22023      const points = inkLists[0];
22024      const point = {
22025        x: points[0] - pageX,
22026        y: pageHeight - (points[1] - pageY)
22027      };
22028      const outliner = new FreeHighlightOutliner(point, [0, 0, pageWidth, pageHeight], 1, editor.#thickness / 2, true, 0.001);
22029      for (let i = 0, ii = points.length; i < ii; i += 2) {
22030        point.x = points[i] - pageX;
22031        point.y = pageHeight - (points[i + 1] - pageY);
22032        outliner.add(point);
22033      }
22034      const {
22035        id,
22036        clipPathId
22037      } = parent.drawLayer.draw({
22038        bbox: [0, 0, 1, 1],
22039        root: {
22040          viewBox: "0 0 1 1",
22041          fill: editor.color,
22042          "fill-opacity": editor._defaultOpacity
22043        },
22044        rootClass: {
22045          highlight: true,
22046          free: true
22047        },
22048        path: {
22049          d: outliner.toSVGPath()
22050        }
22051      }, true, true);
22052      editor.#createFreeOutlines({
22053        highlightOutlines: outliner.getOutlines(),
22054        highlightId: id,
22055        clipPathId
22056      });
22057      editor.#addToDrawLayer();
22058      editor.rotate(editor.parentRotation);
22059    }
22060    return editor;
22061  }
22062  serialize(isForCopying = false) {
22063    if (this.isEmpty() || isForCopying) {
22064      return null;
22065    }
22066    if (this.deleted) {
22067      return this.serializeDeleted();
22068    }
22069    const color = AnnotationEditor._colorManager.convert(this._uiManager.getNonHCMColor(this.color));
22070    const serialized = super.serialize(isForCopying);
22071    Object.assign(serialized, {
22072      color,
22073      opacity: this.opacity,
22074      thickness: this.#thickness,
22075      quadPoints: this.#serializeBoxes(),
22076      outlines: this.#serializeOutlines(serialized.rect)
22077    });
22078    this.addComment(serialized);
22079    if (this.annotationElementId && !this.#hasElementChanged(serialized)) {
22080      return null;
22081    }
22082    serialized.id = this.annotationElementId;
22083    return serialized;
22084  }
22085  #hasElementChanged(serialized) {
22086    const {
22087      color
22088    } = this._initialData;
22089    return this.hasEditedComment || serialized.color.some((c, i) => c !== color[i]);
22090  }
22091  renderAnnotationElement(annotation) {
22092    if (this.deleted) {
22093      annotation.hide();
22094      return null;
22095    }
22096    annotation.updateEdited({
22097      rect: this.getPDFRect(),
22098      popup: this.comment
22099    });
22100    return null;
22101  }
22102  static canCreateNewEmptyEditor() {
22103    return false;
22104  }
22105}
22106
22107;// ./src/display/editor/draw.js
22108
22109
22110
22111
22112class DrawingOptions {
22113  #svgProperties = Object.create(null);
22114  updateProperty(name, value) {
22115    this[name] = value;
22116    this.updateSVGProperty(name, value);
22117  }
22118  updateProperties(properties) {
22119    if (!properties) {
22120      return;
22121    }
22122    for (const [name, value] of Object.entries(properties)) {
22123      if (!name.startsWith("_")) {
22124        this.updateProperty(name, value);
22125      }
22126    }
22127  }
22128  updateSVGProperty(name, value) {
22129    this.#svgProperties[name] = value;
22130  }
22131  toSVGProperties() {
22132    const root = this.#svgProperties;
22133    this.#svgProperties = Object.create(null);
22134    return {
22135      root
22136    };
22137  }
22138  reset() {
22139    this.#svgProperties = Object.create(null);
22140  }
22141  updateAll(options = this) {
22142    this.updateProperties(options);
22143  }
22144  clone() {
22145    unreachable("Not implemented");
22146  }
22147}
22148class DrawingEditor extends AnnotationEditor {
22149  #drawOutlines = null;
22150  #mustBeCommitted;
22151  _colorPicker = null;
22152  _drawId = null;
22153  static _currentDrawId = -1;
22154  static _currentParent = null;
22155  static #currentDraw = null;
22156  static #currentDrawingAC = null;
22157  static #currentDrawingOptions = null;
22158  static _INNER_MARGIN = 3;
22159  constructor(params) {
22160    super(params);
22161    this.#mustBeCommitted = params.mustBeCommitted || false;
22162    this._addOutlines(params);
22163  }
22164  onUpdatedColor() {
22165    this._colorPicker?.update(this.color);
22166    super.onUpdatedColor();
22167  }
22168  _addOutlines(params) {
22169    if (params.drawOutlines) {
22170      this.#createDrawOutlines(params);
22171      this.#addToDrawLayer();
22172    }
22173  }
22174  #createDrawOutlines({
22175    drawOutlines,
22176    drawId,
22177    drawingOptions
22178  }) {
22179    this.#drawOutlines = drawOutlines;
22180    this._drawingOptions ||= drawingOptions;
22181    if (!this.annotationElementId) {
22182      this._uiManager.a11yAlert(`pdfjs-editor-${this.editorType}-added-alert`);
22183    }
22184    if (drawId >= 0) {
22185      this._drawId = drawId;
22186      this.parent.drawLayer.finalizeDraw(drawId, drawOutlines.defaultProperties);
22187    } else {
22188      this._drawId = this.#createDrawing(drawOutlines, this.parent);
22189    }
22190    this.#updateBbox(drawOutlines.box);
22191  }
22192  #createDrawing(drawOutlines, parent) {
22193    const {
22194      id
22195    } = parent.drawLayer.draw(DrawingEditor._mergeSVGProperties(this._drawingOptions.toSVGProperties(), drawOutlines.defaultSVGProperties), false, false);
22196    return id;
22197  }
22198  static _mergeSVGProperties(p1, p2) {
22199    const p1Keys = new Set(Object.keys(p1));
22200    for (const [key, value] of Object.entries(p2)) {
22201      if (p1Keys.has(key)) {
22202        Object.assign(p1[key], value);
22203      } else {
22204        p1[key] = value;
22205      }
22206    }
22207    return p1;
22208  }
22209  static getDefaultDrawingOptions(_options) {
22210    unreachable("Not implemented");
22211  }
22212  static get typesMap() {
22213    unreachable("Not implemented");
22214  }
22215  static get isDrawer() {
22216    return true;
22217  }
22218  static get supportMultipleDrawings() {
22219    return false;
22220  }
22221  static updateDefaultParams(type, value) {
22222    const propertyName = this.typesMap.get(type);
22223    if (propertyName) {
22224      this._defaultDrawingOptions.updateProperty(propertyName, value);
22225    }
22226    if (this._currentParent) {
22227      DrawingEditor.#currentDraw.updateProperty(propertyName, value);
22228      this._currentParent.drawLayer.updateProperties(this._currentDrawId, this._defaultDrawingOptions.toSVGProperties());
22229    }
22230  }
22231  updateParams(type, value) {
22232    const propertyName = this.constructor.typesMap.get(type);
22233    if (propertyName) {
22234      this._updateProperty(type, propertyName, value);
22235    }
22236  }
22237  static get defaultPropertiesToUpdate() {
22238    const properties = [];
22239    const options = this._defaultDrawingOptions;
22240    for (const [type, name] of this.typesMap) {
22241      properties.push([type, options[name]]);
22242    }
22243    return properties;
22244  }
22245  get propertiesToUpdate() {
22246    const properties = [];
22247    const {
22248      _drawingOptions
22249    } = this;
22250    for (const [type, name] of this.constructor.typesMap) {
22251      properties.push([type, _drawingOptions[name]]);
22252    }
22253    return properties;
22254  }
22255  _updateProperty(type, name, value) {
22256    const options = this._drawingOptions;
22257    const savedValue = options[name];
22258    const setter = val => {
22259      options.updateProperty(name, val);
22260      const bbox = this.#drawOutlines.updateProperty(name, val);
22261      if (bbox) {
22262        this.#updateBbox(bbox);
22263      }
22264      this.parent?.drawLayer.updateProperties(this._drawId, options.toSVGProperties());
22265      if (type === this.colorType) {
22266        this.onUpdatedColor();
22267      }
22268    };
22269    this.addCommands({
22270      cmd: setter.bind(this, value),
22271      undo: setter.bind(this, savedValue),
22272      post: this._uiManager.updateUI.bind(this._uiManager, this),
22273      mustExec: true,
22274      type,
22275      overwriteIfSameType: true,
22276      keepUndo: true
22277    });
22278  }
22279  _onResizing() {
22280    this.parent?.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties(this.#drawOutlines.getPathResizingSVGProperties(this.#convertToDrawSpace()), {
22281      bbox: this.#rotateBox()
22282    }));
22283  }
22284  _onResized() {
22285    this.parent?.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties(this.#drawOutlines.getPathResizedSVGProperties(this.#convertToDrawSpace()), {
22286      bbox: this.#rotateBox()
22287    }));
22288  }
22289  _onTranslating(_x, _y) {
22290    this.parent?.drawLayer.updateProperties(this._drawId, {
22291      bbox: this.#rotateBox()
22292    });
22293  }
22294  _onTranslated() {
22295    this.parent?.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties(this.#drawOutlines.getPathTranslatedSVGProperties(this.#convertToDrawSpace(), this.parentDimensions), {
22296      bbox: this.#rotateBox()
22297    }));
22298  }
22299  _onStartDragging() {
22300    this.parent?.drawLayer.updateProperties(this._drawId, {
22301      rootClass: {
22302        moving: true
22303      }
22304    });
22305  }
22306  _onStopDragging() {
22307    this.parent?.drawLayer.updateProperties(this._drawId, {
22308      rootClass: {
22309        moving: false
22310      }
22311    });
22312  }
22313  commit() {
22314    super.commit();
22315    this.disableEditMode();
22316    this.disableEditing();
22317  }
22318  disableEditing() {
22319    super.disableEditing();
22320    this.div.classList.toggle("disabled", true);
22321  }
22322  enableEditing() {
22323    super.enableEditing();
22324    this.div.classList.toggle("disabled", false);
22325  }
22326  getBaseTranslation() {
22327    return [0, 0];
22328  }
22329  get isResizable() {
22330    return true;
22331  }
22332  onceAdded(focus) {
22333    if (!this.annotationElementId) {
22334      this.parent.addUndoableEditor(this);
22335    }
22336    this._isDraggable = true;
22337    if (this.#mustBeCommitted) {
22338      this.#mustBeCommitted = false;
22339      this.commit();
22340      this.parent.setSelected(this);
22341      if (focus && this.isOnScreen) {
22342        this.div.focus();
22343      }
22344    }
22345  }
22346  remove() {
22347    this.#cleanDrawLayer();
22348    super.remove();
22349  }
22350  rebuild() {
22351    if (!this.parent) {
22352      return;
22353    }
22354    super.rebuild();
22355    if (this.div === null) {
22356      return;
22357    }
22358    this.#addToDrawLayer();
22359    this.#updateBbox(this.#drawOutlines.box);
22360    if (!this.isAttachedToDOM) {
22361      this.parent.add(this);
22362    }
22363  }
22364  setParent(parent) {
22365    let mustBeSelected = false;
22366    if (this.parent && !parent) {
22367      this._uiManager.removeShouldRescale(this);
22368      this.#cleanDrawLayer();
22369    } else if (parent) {
22370      this._uiManager.addShouldRescale(this);
22371      this.#addToDrawLayer(parent);
22372      mustBeSelected = !this.parent && this.div?.classList.contains("selectedEditor");
22373    }
22374    super.setParent(parent);
22375    if (mustBeSelected) {
22376      this.select();
22377    }
22378  }
22379  #cleanDrawLayer() {
22380    if (this._drawId === null || !this.parent) {
22381      return;
22382    }
22383    this.parent.drawLayer.remove(this._drawId);
22384    this._drawId = null;
22385    this._drawingOptions.reset();
22386  }
22387  #addToDrawLayer(parent = this.parent) {
22388    if (this._drawId !== null && this.parent === parent) {
22389      return;
22390    }
22391    if (this._drawId !== null) {
22392      this.parent.drawLayer.updateParent(this._drawId, parent.drawLayer);
22393      return;
22394    }
22395    this._drawingOptions.updateAll();
22396    this._drawId = this.#createDrawing(this.#drawOutlines, parent);
22397  }
22398  #convertToParentSpace([x, y, width, height]) {
22399    const {
22400      parentDimensions: [pW, pH],
22401      rotation
22402    } = this;
22403    switch (rotation) {
22404      case 90:
22405        return [y, 1 - x, width * (pH / pW), height * (pW / pH)];
22406      case 180:
22407        return [1 - x, 1 - y, width, height];
22408      case 270:
22409        return [1 - y, x, width * (pH / pW), height * (pW / pH)];
22410      default:
22411        return [x, y, width, height];
22412    }
22413  }
22414  #convertToDrawSpace() {
22415    const {
22416      x,
22417      y,
22418      width,
22419      height,
22420      parentDimensions: [pW, pH],
22421      rotation
22422    } = this;
22423    switch (rotation) {
22424      case 90:
22425        return [1 - y, x, width * (pW / pH), height * (pH / pW)];
22426      case 180:
22427        return [1 - x, 1 - y, width, height];
22428      case 270:
22429        return [y, 1 - x, width * (pW / pH), height * (pH / pW)];
22430      default:
22431        return [x, y, width, height];
22432    }
22433  }
22434  #updateBbox(bbox) {
22435    [this.x, this.y, this.width, this.height] = this.#convertToParentSpace(bbox);
22436    if (this.div) {
22437      this.fixAndSetPosition();
22438      this.setDims();
22439    }
22440    this._onResized();
22441  }
22442  #rotateBox() {
22443    const {
22444      x,
22445      y,
22446      width,
22447      height,
22448      rotation,
22449      parentRotation,
22450      parentDimensions: [pW, pH]
22451    } = this;
22452    switch ((rotation * 4 + parentRotation) / 90) {
22453      case 1:
22454        return [1 - y - height, x, height, width];
22455      case 2:
22456        return [1 - x - width, 1 - y - height, width, height];
22457      case 3:
22458        return [y, 1 - x - width, height, width];
22459      case 4:
22460        return [x, y - width * (pW / pH), height * (pH / pW), width * (pW / pH)];
22461      case 5:
22462        return [1 - y, x, width * (pW / pH), height * (pH / pW)];
22463      case 6:
22464        return [1 - x - height * (pH / pW), 1 - y, height * (pH / pW), width * (pW / pH)];
22465      case 7:
22466        return [y - width * (pW / pH), 1 - x - height * (pH / pW), width * (pW / pH), height * (pH / pW)];
22467      case 8:
22468        return [x - width, y - height, width, height];
22469      case 9:
22470        return [1 - y, x - width, height, width];
22471      case 10:
22472        return [1 - x, 1 - y, width, height];
22473      case 11:
22474        return [y - height, 1 - x, height, width];
22475      case 12:
22476        return [x - height * (pH / pW), y, height * (pH / pW), width * (pW / pH)];
22477      case 13:
22478        return [1 - y - width * (pW / pH), x - height * (pH / pW), width * (pW / pH), height * (pH / pW)];
22479      case 14:
22480        return [1 - x, 1 - y - width * (pW / pH), height * (pH / pW), width * (pW / pH)];
22481      case 15:
22482        return [y, 1 - x, width * (pW / pH), height * (pH / pW)];
22483      default:
22484        return [x, y, width, height];
22485    }
22486  }
22487  rotate() {
22488    if (!this.parent) {
22489      return;
22490    }
22491    this.parent.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties({
22492      bbox: this.#rotateBox()
22493    }, this.#drawOutlines.updateRotation((this.parentRotation - this.rotation + 360) % 360)));
22494  }
22495  onScaleChanging() {
22496    if (!this.parent) {
22497      return;
22498    }
22499    this.#updateBbox(this.#drawOutlines.updateParentDimensions(this.parentDimensions, this.parent.scale));
22500  }
22501  static onScaleChangingWhenDrawing() {}
22502  render() {
22503    if (this.div) {
22504      return this.div;
22505    }
22506    let baseX, baseY;
22507    if (this._isCopy) {
22508      baseX = this.x;
22509      baseY = this.y;
22510    }
22511    const div = super.render();
22512    div.classList.add("draw");
22513    const drawDiv = document.createElement("div");
22514    div.append(drawDiv);
22515    drawDiv.setAttribute("aria-hidden", "true");
22516    drawDiv.className = "internal";
22517    this.setDims();
22518    this._uiManager.addShouldRescale(this);
22519    this.disableEditing();
22520    if (this._isCopy) {
22521      this._moveAfterPaste(baseX, baseY);
22522    }
22523    return div;
22524  }
22525  static createDrawerInstance(_x, _y, _parentWidth, _parentHeight, _rotation) {
22526    unreachable("Not implemented");
22527  }
22528  static startDrawing(parent, uiManager, _isLTR, event) {
22529    const {
22530      target,
22531      offsetX: x,
22532      offsetY: y,
22533      pointerId,
22534      pointerType
22535    } = event;
22536    if (CurrentPointers.isInitializedAndDifferentPointerType(pointerType)) {
22537      return;
22538    }
22539    const {
22540      viewport: {
22541        rotation
22542      }
22543    } = parent;
22544    const {
22545      width: parentWidth,
22546      height: parentHeight
22547    } = target.getBoundingClientRect();
22548    const ac = DrawingEditor.#currentDrawingAC = new AbortController();
22549    const signal = parent.combinedSignal(ac);
22550    CurrentPointers.setPointer(pointerType, pointerId);
22551    window.addEventListener("pointerup", e => {
22552      if (CurrentPointers.isSamePointerIdOrRemove(e.pointerId)) {
22553        this._endDraw(e);
22554      }
22555    }, {
vendor: 5,835 bytes, lines 22556-22737
22556      signal
22557    });
22558    window.addEventListener("pointercancel", e => {
22559      if (CurrentPointers.isSamePointerIdOrRemove(e.pointerId)) {
22560        this._currentParent.endDrawingSession();
22561      }
22562    }, {
22563      signal
22564    });
22565    window.addEventListener("pointerdown", e => {
22566      if (!CurrentPointers.isSamePointerType(e.pointerType)) {
22567        return;
22568      }
22569      CurrentPointers.initializeAndAddPointerId(e.pointerId);
22570      if (DrawingEditor.#currentDraw.isCancellable()) {
22571        DrawingEditor.#currentDraw.removeLastElement();
22572        if (DrawingEditor.#currentDraw.isEmpty()) {
22573          this._currentParent.endDrawingSession(true);
22574        } else {
22575          this._endDraw(null);
22576        }
22577      }
22578    }, {
22579      capture: true,
22580      passive: false,
22581      signal
22582    });
22583    window.addEventListener("contextmenu", noContextMenu, {
22584      signal
22585    });
22586    target.addEventListener("pointermove", this._drawMove.bind(this), {
22587      signal
22588    });
22589    target.addEventListener("touchmove", e => {
22590      if (CurrentPointers.isSameTimeStamp(e.timeStamp)) {
22591        stopEvent(e);
22592      }
22593    }, {
22594      signal
22595    });
22596    parent.toggleDrawing();
22597    uiManager._editorUndoBar?.hide();
22598    if (DrawingEditor.#currentDraw) {
22599      parent.drawLayer.updateProperties(this._currentDrawId, DrawingEditor.#currentDraw.startNew(x, y, parentWidth, parentHeight, rotation));
22600      return;
22601    }
22602    uiManager.updateUIForDefaultProperties(this);
22603    DrawingEditor.#currentDraw = this.createDrawerInstance(x, y, parentWidth, parentHeight, rotation);
22604    DrawingEditor.#currentDrawingOptions = this.getDefaultDrawingOptions();
22605    this._currentParent = parent;
22606    ({
22607      id: this._currentDrawId
22608    } = parent.drawLayer.draw(this._mergeSVGProperties(DrawingEditor.#currentDrawingOptions.toSVGProperties(), DrawingEditor.#currentDraw.defaultSVGProperties), true, false));
22609  }
22610  static _drawMove(event) {
22611    CurrentPointers.isSameTimeStamp(event.timeStamp);
22612    if (!DrawingEditor.#currentDraw) {
22613      return;
22614    }
22615    const {
22616      offsetX,
22617      offsetY,
22618      pointerId
22619    } = event;
22620    if (!CurrentPointers.isSamePointerId(pointerId)) {
22621      return;
22622    }
22623    if (CurrentPointers.isUsingMultiplePointers()) {
22624      this._endDraw(event);
22625      return;
22626    }
22627    this._currentParent.drawLayer.updateProperties(this._currentDrawId, DrawingEditor.#currentDraw.add(offsetX, offsetY));
22628    CurrentPointers.setTimeStamp(event.timeStamp);
22629    stopEvent(event);
22630  }
22631  static _cleanup(all) {
22632    if (all) {
22633      this._currentDrawId = -1;
22634      this._currentParent = null;
22635      DrawingEditor.#currentDraw = null;
22636      DrawingEditor.#currentDrawingOptions = null;
22637      CurrentPointers.clearTimeStamp();
22638    }
22639    if (DrawingEditor.#currentDrawingAC) {
22640      DrawingEditor.#currentDrawingAC.abort();
22641      DrawingEditor.#currentDrawingAC = null;
22642      CurrentPointers.clearPointerIds();
22643    }
22644  }
22645  static _endDraw(event) {
22646    const parent = this._currentParent;
22647    if (!parent) {
22648      return;
22649    }
22650    parent.toggleDrawing(true);
22651    this._cleanup(false);
22652    if (event?.target === parent.div) {
22653      parent.drawLayer.updateProperties(this._currentDrawId, DrawingEditor.#currentDraw.end(event.offsetX, event.offsetY));
22654    }
22655    if (this.supportMultipleDrawings) {
22656      const draw = DrawingEditor.#currentDraw;
22657      const drawId = this._currentDrawId;
22658      const lastElement = draw.getLastElement();
22659      parent.addCommands({
22660        cmd: () => {
22661          parent.drawLayer.updateProperties(drawId, draw.setLastElement(lastElement));
22662        },
22663        undo: () => {
22664          parent.drawLayer.updateProperties(drawId, draw.removeLastElement());
22665        },
22666        mustExec: false,
22667        type: AnnotationEditorParamsType.DRAW_STEP
22668      });
22669      return;
22670    }
22671    this.endDrawing(false);
22672  }
22673  static endDrawing(isAborted) {
22674    const parent = this._currentParent;
22675    if (!parent) {
22676      return null;
22677    }
22678    parent.toggleDrawing(true);
22679    parent.cleanUndoStack(AnnotationEditorParamsType.DRAW_STEP);
22680    if (!DrawingEditor.#currentDraw.isEmpty()) {
22681      const {
22682        pageDimensions: [pageWidth, pageHeight],
22683        scale
22684      } = parent;
22685      const editor = parent.createAndAddNewEditor({
22686        offsetX: 0,
22687        offsetY: 0
22688      }, false, {
22689        drawId: this._currentDrawId,
22690        drawOutlines: DrawingEditor.#currentDraw.getOutlines(pageWidth * scale, pageHeight * scale, scale, this._INNER_MARGIN),
22691        drawingOptions: DrawingEditor.#currentDrawingOptions,
22692        mustBeCommitted: !isAborted
22693      });
22694      this._cleanup(true);
22695      return editor;
22696    }
22697    parent.drawLayer.remove(this._currentDrawId);
22698    this._cleanup(true);
22699    return null;
22700  }
22701  createDrawingOptions(_data) {}
22702  static deserializeDraw(_pageX, _pageY, _pageWidth, _pageHeight, _innerWidth, _data) {
22703    unreachable("Not implemented");
22704  }
22705  static async deserialize(data, parent, uiManager) {
22706    const {
22707      rawDims: {
22708        pageWidth,
22709        pageHeight,
22710        pageX,
22711        pageY
22712      }
22713    } = parent.viewport;
22714    const drawOutlines = this.deserializeDraw(pageX, pageY, pageWidth, pageHeight, this._INNER_MARGIN, data);
22715    const editor = await super.deserialize(data, parent, uiManager);
22716    editor.createDrawingOptions(data);
22717    editor.#createDrawOutlines({
22718      drawOutlines
22719    });
22720    editor.#addToDrawLayer();
22721    editor.onScaleChanging();
22722    editor.rotate();
22723    return editor;
22724  }
22725  serializeDraw(isForCopying) {
22726    const [pageX, pageY] = this.pageTranslation;
22727    const [pageWidth, pageHeight] = this.pageDimensions;
22728    return this.#drawOutlines.serialize([pageX, pageY, pageWidth, pageHeight], isForCopying);
22729  }
22730  renderAnnotationElement(annotation) {
22731    annotation.updateEdited({
22732      rect: this.getPDFRect()
22733    });
22734    return null;
22735  }
22736  static canCreateNewEmptyEditor() {
22737    return false;
22738  }
22739}
22740
22741;// ./src/display/editor/drawers/inkdraw.js
22742
vendor: 10,994 bytes, lines 22743-23133
22743
22744class InkDrawOutliner {
22745  #last = new Float64Array(6);
22746  #line;
22747  #lines;
22748  #rotation;
22749  #thickness;
22750  #points;
22751  #lastSVGPath = "";
22752  #lastIndex = 0;
22753  #outlines = new InkDrawOutline();
22754  #parentWidth;
22755  #parentHeight;
22756  constructor(x, y, parentWidth, parentHeight, rotation, thickness) {
22757    this.#parentWidth = parentWidth;
22758    this.#parentHeight = parentHeight;
22759    this.#rotation = rotation;
22760    this.#thickness = thickness;
22761    [x, y] = this.#normalizePoint(x, y);
22762    const line = this.#line = [NaN, NaN, NaN, NaN, x, y];
22763    this.#points = [x, y];
22764    this.#lines = [{
22765      line,
22766      points: this.#points
22767    }];
22768    this.#last.set(line, 0);
22769  }
22770  updateProperty(name, value) {
22771    if (name === "stroke-width") {
22772      this.#thickness = value;
22773    }
22774  }
22775  #normalizePoint(x, y) {
22776    return Outline._normalizePoint(x, y, this.#parentWidth, this.#parentHeight, this.#rotation);
22777  }
22778  isEmpty() {
22779    return !this.#lines || this.#lines.length === 0;
22780  }
22781  isCancellable() {
22782    return this.#points.length <= 10;
22783  }
22784  add(x, y) {
22785    [x, y] = this.#normalizePoint(x, y);
22786    const [x1, y1, x2, y2] = this.#last.subarray(2, 6);
22787    const diffX = x - x2;
22788    const diffY = y - y2;
22789    const d = Math.hypot(this.#parentWidth * diffX, this.#parentHeight * diffY);
22790    if (d <= 2) {
22791      return null;
22792    }
22793    this.#points.push(x, y);
22794    if (isNaN(x1)) {
22795      this.#last.set([x2, y2, x, y], 2);
22796      this.#line.push(NaN, NaN, NaN, NaN, x, y);
22797      return {
22798        path: {
22799          d: this.toSVGPath()
22800        }
22801      };
22802    }
22803    if (isNaN(this.#last[0])) {
22804      this.#line.splice(6, 6);
22805    }
22806    this.#last.set([x1, y1, x2, y2, x, y], 0);
22807    this.#line.push(...Outline.createBezierPoints(x1, y1, x2, y2, x, y));
22808    return {
22809      path: {
22810        d: this.toSVGPath()
22811      }
22812    };
22813  }
22814  end(x, y) {
22815    const change = this.add(x, y);
22816    if (change) {
22817      return change;
22818    }
22819    if (this.#points.length === 2) {
22820      return {
22821        path: {
22822          d: this.toSVGPath()
22823        }
22824      };
22825    }
22826    return null;
22827  }
22828  startNew(x, y, parentWidth, parentHeight, rotation) {
22829    this.#parentWidth = parentWidth;
22830    this.#parentHeight = parentHeight;
22831    this.#rotation = rotation;
22832    [x, y] = this.#normalizePoint(x, y);
22833    const line = this.#line = [NaN, NaN, NaN, NaN, x, y];
22834    this.#points = [x, y];
22835    const last = this.#lines.at(-1);
22836    if (last) {
22837      last.line = new Float32Array(last.line);
22838      last.points = new Float32Array(last.points);
22839    }
22840    this.#lines.push({
22841      line,
22842      points: this.#points
22843    });
22844    this.#last.set(line, 0);
22845    this.#lastIndex = 0;
22846    this.toSVGPath();
22847    return null;
22848  }
22849  getLastElement() {
22850    return this.#lines.at(-1);
22851  }
22852  setLastElement(element) {
22853    if (!this.#lines) {
22854      return this.#outlines.setLastElement(element);
22855    }
22856    this.#lines.push(element);
22857    this.#line = element.line;
22858    this.#points = element.points;
22859    this.#lastIndex = 0;
22860    return {
22861      path: {
22862        d: this.toSVGPath()
22863      }
22864    };
22865  }
22866  removeLastElement() {
22867    if (!this.#lines) {
22868      return this.#outlines.removeLastElement();
22869    }
22870    this.#lines.pop();
22871    this.#lastSVGPath = "";
22872    for (let i = 0, ii = this.#lines.length; i < ii; i++) {
22873      const {
22874        line,
22875        points
22876      } = this.#lines[i];
22877      this.#line = line;
22878      this.#points = points;
22879      this.#lastIndex = 0;
22880      this.toSVGPath();
22881    }
22882    return {
22883      path: {
22884        d: this.#lastSVGPath
22885      }
22886    };
22887  }
22888  toSVGPath() {
22889    const firstX = Outline.svgRound(this.#line[4]);
22890    const firstY = Outline.svgRound(this.#line[5]);
22891    if (this.#points.length === 2) {
22892      this.#lastSVGPath = `${this.#lastSVGPath} M ${firstX} ${firstY} Z`;
22893      return this.#lastSVGPath;
22894    }
22895    if (this.#points.length <= 6) {
22896      const i = this.#lastSVGPath.lastIndexOf("M");
22897      this.#lastSVGPath = `${this.#lastSVGPath.slice(0, i)} M ${firstX} ${firstY}`;
22898      this.#lastIndex = 6;
22899    }
22900    if (this.#points.length === 4) {
22901      const secondX = Outline.svgRound(this.#line[10]);
22902      const secondY = Outline.svgRound(this.#line[11]);
22903      this.#lastSVGPath = `${this.#lastSVGPath} L ${secondX} ${secondY}`;
22904      this.#lastIndex = 12;
22905      return this.#lastSVGPath;
22906    }
22907    const buffer = [];
22908    if (this.#lastIndex === 0) {
22909      buffer.push(`M ${firstX} ${firstY}`);
22910      this.#lastIndex = 6;
22911    }
22912    for (let i = this.#lastIndex, ii = this.#line.length; i < ii; i += 6) {
22913      const [c1x, c1y, c2x, c2y, x, y] = this.#line.slice(i, i + 6).map(Outline.svgRound);
22914      buffer.push(`C${c1x} ${c1y} ${c2x} ${c2y} ${x} ${y}`);
22915    }
22916    this.#lastSVGPath += buffer.join(" ");
22917    this.#lastIndex = this.#line.length;
22918    return this.#lastSVGPath;
22919  }
22920  getOutlines(parentWidth, parentHeight, scale, innerMargin) {
22921    const last = this.#lines.at(-1);
22922    last.line = new Float32Array(last.line);
22923    last.points = new Float32Array(last.points);
22924    this.#outlines.build(this.#lines, parentWidth, parentHeight, scale, this.#rotation, this.#thickness, innerMargin);
22925    this.#last = null;
22926    this.#line = null;
22927    this.#lines = null;
22928    this.#lastSVGPath = null;
22929    return this.#outlines;
22930  }
22931  get defaultSVGProperties() {
22932    return {
22933      root: {
22934        viewBox: "0 0 10000 10000"
22935      },
22936      rootClass: {
22937        draw: true
22938      },
22939      bbox: [0, 0, 1, 1]
22940    };
22941  }
22942}
22943class InkDrawOutline extends Outline {
22944  #bbox;
22945  #currentRotation = 0;
22946  #innerMargin;
22947  #lines;
22948  #parentWidth;
22949  #parentHeight;
22950  #parentScale;
22951  #rotation;
22952  #thickness;
22953  build(lines, parentWidth, parentHeight, parentScale, rotation, thickness, innerMargin) {
22954    this.#parentWidth = parentWidth;
22955    this.#parentHeight = parentHeight;
22956    this.#parentScale = parentScale;
22957    this.#rotation = rotation;
22958    this.#thickness = thickness;
22959    this.#innerMargin = innerMargin ?? 0;
22960    this.#lines = lines;
22961    this.#computeBbox();
22962  }
22963  get thickness() {
22964    return this.#thickness;
22965  }
22966  setLastElement(element) {
22967    this.#lines.push(element);
22968    return {
22969      path: {
22970        d: this.toSVGPath()
22971      }
22972    };
22973  }
22974  removeLastElement() {
22975    this.#lines.pop();
22976    return {
22977      path: {
22978        d: this.toSVGPath()
22979      }
22980    };
22981  }
22982  toSVGPath() {
22983    const buffer = [];
22984    for (const {
22985      line
22986    } of this.#lines) {
22987      buffer.push(`M${Outline.svgRound(line[4])} ${Outline.svgRound(line[5])}`);
22988      if (line.length === 6) {
22989        buffer.push("Z");
22990        continue;
22991      }
22992      if (line.length === 12 && isNaN(line[6])) {
22993        buffer.push(`L${Outline.svgRound(line[10])} ${Outline.svgRound(line[11])}`);
22994        continue;
22995      }
22996      for (let i = 6, ii = line.length; i < ii; i += 6) {
22997        const [c1x, c1y, c2x, c2y, x, y] = line.subarray(i, i + 6).map(Outline.svgRound);
22998        buffer.push(`C${c1x} ${c1y} ${c2x} ${c2y} ${x} ${y}`);
22999      }
23000    }
23001    return buffer.join("");
23002  }
23003  serialize([pageX, pageY, pageWidth, pageHeight], isForCopying) {
23004    const serializedLines = [];
23005    const serializedPoints = [];
23006    const [x, y, width, height] = this.#getBBoxWithNoMargin();
23007    let tx, ty, sx, sy, x1, y1, x2, y2, rescaleFn;
23008    switch (this.#rotation) {
23009      case 0:
23010        rescaleFn = Outline._rescale;
23011        tx = pageX;
23012        ty = pageY + pageHeight;
23013        sx = pageWidth;
23014        sy = -pageHeight;
23015        x1 = pageX + x * pageWidth;
23016        y1 = pageY + (1 - y - height) * pageHeight;
23017        x2 = pageX + (x + width) * pageWidth;
23018        y2 = pageY + (1 - y) * pageHeight;
23019        break;
23020      case 90:
23021        rescaleFn = Outline._rescaleAndSwap;
23022        tx = pageX;
23023        ty = pageY;
23024        sx = pageWidth;
23025        sy = pageHeight;
23026        x1 = pageX + y * pageWidth;
23027        y1 = pageY + x * pageHeight;
23028        x2 = pageX + (y + height) * pageWidth;
23029        y2 = pageY + (x + width) * pageHeight;
23030        break;
23031      case 180:
23032        rescaleFn = Outline._rescale;
23033        tx = pageX + pageWidth;
23034        ty = pageY;
23035        sx = -pageWidth;
23036        sy = pageHeight;
23037        x1 = pageX + (1 - x - width) * pageWidth;
23038        y1 = pageY + y * pageHeight;
23039        x2 = pageX + (1 - x) * pageWidth;
23040        y2 = pageY + (y + height) * pageHeight;
23041        break;
23042      case 270:
23043        rescaleFn = Outline._rescaleAndSwap;
23044        tx = pageX + pageWidth;
23045        ty = pageY + pageHeight;
23046        sx = -pageWidth;
23047        sy = -pageHeight;
23048        x1 = pageX + (1 - y - height) * pageWidth;
23049        y1 = pageY + (1 - x - width) * pageHeight;
23050        x2 = pageX + (1 - y) * pageWidth;
23051        y2 = pageY + (1 - x) * pageHeight;
23052        break;
23053    }
23054    for (const {
23055      line,
23056      points
23057    } of this.#lines) {
23058      serializedLines.push(rescaleFn(line, tx, ty, sx, sy, isForCopying ? new Array(line.length) : null));
23059      serializedPoints.push(rescaleFn(points, tx, ty, sx, sy, isForCopying ? new Array(points.length) : null));
23060    }
23061    return {
23062      lines: serializedLines,
23063      points: serializedPoints,
23064      rect: [x1, y1, x2, y2]
23065    };
23066  }
23067  static deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, {
23068    paths: {
23069      lines,
23070      points
23071    },
23072    rotation,
23073    thickness
23074  }) {
23075    const newLines = [];
23076    let tx, ty, sx, sy, rescaleFn;
23077    switch (rotation) {
23078      case 0:
23079        rescaleFn = Outline._rescale;
23080        tx = -pageX / pageWidth;
23081        ty = pageY / pageHeight + 1;
23082        sx = 1 / pageWidth;
23083        sy = -1 / pageHeight;
23084        break;
23085      case 90:
23086        rescaleFn = Outline._rescaleAndSwap;
23087        tx = -pageY / pageHeight;
23088        ty = -pageX / pageWidth;
23089        sx = 1 / pageHeight;
23090        sy = 1 / pageWidth;
23091        break;
23092      case 180:
23093        rescaleFn = Outline._rescale;
23094        tx = pageX / pageWidth + 1;
23095        ty = -pageY / pageHeight;
23096        sx = -1 / pageWidth;
23097        sy = 1 / pageHeight;
23098        break;
23099      case 270:
23100        rescaleFn = Outline._rescaleAndSwap;
23101        tx = pageY / pageHeight + 1;
23102        ty = pageX / pageWidth + 1;
23103        sx = -1 / pageHeight;
23104        sy = -1 / pageWidth;
23105        break;
23106    }
23107    if (!lines) {
23108      lines = [];
23109      for (const point of points) {
23110        const len = point.length;
23111        if (len === 2) {
23112          lines.push(new Float32Array([NaN, NaN, NaN, NaN, point[0], point[1]]));
23113          continue;
23114        }
23115        if (len === 4) {
23116          lines.push(new Float32Array([NaN, NaN, NaN, NaN, point[0], point[1], NaN, NaN, NaN, NaN, point[2], point[3]]));
23117          continue;
23118        }
23119        const line = new Float32Array(3 * (len - 2));
23120        lines.push(line);
23121        let [x1, y1, x2, y2] = point.subarray(0, 4);
23122        line.set([NaN, NaN, NaN, NaN, x1, y1], 0);
23123        for (let i = 4; i < len; i += 2) {
23124          const x = point[i];
23125          const y = point[i + 1];
23126          line.set(Outline.createBezierPoints(x1, y1, x2, y2, x, y), (i - 2) * 3);
23127          [x1, y1, x2, y2] = [x2, y2, x, y];
23128        }
23129      }
23130    }
23131    for (let i = 0, ii = lines.length; i < ii; i++) {
23132      newLines.push({
23133        line: rescaleFn(lines[i].map(
vendor: 1,940 bytes, lines 23133-23185
23133x => x ?? NaN), tx, ty, sx, sy),
23134        points: rescaleFn(points[i].map(x => x ?? NaN), tx, ty, sx, sy)
23135      });
23136    }
23137    const outlines = new this.prototype.constructor();
23138    outlines.build(newLines, pageWidth, pageHeight, 1, rotation, thickness, innerMargin);
23139    return outlines;
23140  }
23141  #getMarginComponents(thickness = this.#thickness) {
23142    const margin = this.#innerMargin + thickness / 2 * this.#parentScale;
23143    return this.#rotation % 180 === 0 ? [margin / this.#parentWidth, margin / this.#parentHeight] : [margin / this.#parentHeight, margin / this.#parentWidth];
23144  }
23145  #getBBoxWithNoMargin() {
23146    const [x, y, width, height] = this.#bbox;
23147    const [marginX, marginY] = this.#getMarginComponents(0);
23148    return [x + marginX, y + marginY, width - 2 * marginX, height - 2 * marginY];
23149  }
23150  #computeBbox() {
23151    const bbox = this.#bbox = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]);
23152    for (const {
23153      line
23154    } of this.#lines) {
23155      if (line.length <= 12) {
23156        for (let i = 4, ii = line.length; i < ii; i += 6) {
23157          Util.pointBoundingBox(line[i], line[i + 1], bbox);
23158        }
23159        continue;
23160      }
23161      let lastX = line[4],
23162        lastY = line[5];
23163      for (let i = 6, ii = line.length; i < ii; i += 6) {
23164        const [c1x, c1y, c2x, c2y, x, y] = line.subarray(i, i + 6);
23165        Util.bezierBoundingBox(lastX, lastY, c1x, c1y, c2x, c2y, x, y, bbox);
23166        lastX = x;
23167        lastY = y;
23168      }
23169    }
23170    const [marginX, marginY] = this.#getMarginComponents();
23171    bbox[0] = MathClamp(bbox[0] - marginX, 0, 1);
23172    bbox[1] = MathClamp(bbox[1] - marginY, 0, 1);
23173    bbox[2] = MathClamp(bbox[2] + marginX, 0, 1);
23174    bbox[3] = MathClamp(bbox[3] + marginY, 0, 1);
23175    bbox[2] -= bbox[0];
23176    bbox[3] -= bbox[1];
23177  }
23178  get box() {
23179    return this.#bbox;
23180  }
23181  updateProperty(name, value) {
23182    if (name === "stroke-width") {
23183      return this.#updateThickness(value);
23184    }
23185    return
vendor: 4,014 bytes, lines 23185-23309
23185 null;
23186  }
23187  #updateThickness(thickness) {
23188    const [oldMarginX, oldMarginY] = this.#getMarginComponents();
23189    this.#thickness = thickness;
23190    const [newMarginX, newMarginY] = this.#getMarginComponents();
23191    const [diffMarginX, diffMarginY] = [newMarginX - oldMarginX, newMarginY - oldMarginY];
23192    const bbox = this.#bbox;
23193    bbox[0] -= diffMarginX;
23194    bbox[1] -= diffMarginY;
23195    bbox[2] += 2 * diffMarginX;
23196    bbox[3] += 2 * diffMarginY;
23197    return bbox;
23198  }
23199  updateParentDimensions([width, height], scale) {
23200    const [oldMarginX, oldMarginY] = this.#getMarginComponents();
23201    this.#parentWidth = width;
23202    this.#parentHeight = height;
23203    this.#parentScale = scale;
23204    const [newMarginX, newMarginY] = this.#getMarginComponents();
23205    const diffMarginX = newMarginX - oldMarginX;
23206    const diffMarginY = newMarginY - oldMarginY;
23207    const bbox = this.#bbox;
23208    bbox[0] -= diffMarginX;
23209    bbox[1] -= diffMarginY;
23210    bbox[2] += 2 * diffMarginX;
23211    bbox[3] += 2 * diffMarginY;
23212    return bbox;
23213  }
23214  updateRotation(rotation) {
23215    this.#currentRotation = rotation;
23216    return {
23217      path: {
23218        transform: this.rotationTransform
23219      }
23220    };
23221  }
23222  get viewBox() {
23223    return this.#bbox.map(Outline.svgRound).join(" ");
23224  }
23225  get defaultProperties() {
23226    const [x, y] = this.#bbox;
23227    return {
23228      root: {
23229        viewBox: this.viewBox
23230      },
23231      path: {
23232        "transform-origin": `${Outline.svgRound(x)} ${Outline.svgRound(y)}`
23233      }
23234    };
23235  }
23236  get rotationTransform() {
23237    const [,, width, height] = this.#bbox;
23238    let a = 0,
23239      b = 0,
23240      c = 0,
23241      d = 0,
23242      e = 0,
23243      f = 0;
23244    switch (this.#currentRotation) {
23245      case 90:
23246        b = height / width;
23247        c = -width / height;
23248        e = width;
23249        break;
23250      case 180:
23251        a = -1;
23252        d = -1;
23253        e = width;
23254        f = height;
23255        break;
23256      case 270:
23257        b = -height / width;
23258        c = width / height;
23259        f = height;
23260        break;
23261      default:
23262        return "";
23263    }
23264    return `matrix(${a} ${b} ${c} ${d} ${Outline.svgRound(e)} ${Outline.svgRound(f)})`;
23265  }
23266  getPathResizingSVGProperties([newX, newY, newWidth, newHeight]) {
23267    const [marginX, marginY] = this.#getMarginComponents();
23268    const [x, y, width, height] = this.#bbox;
23269    if (Math.abs(width - marginX) <= Outline.PRECISION || Math.abs(height - marginY) <= Outline.PRECISION) {
23270      const tx = newX + newWidth / 2 - (x + width / 2);
23271      const ty = newY + newHeight / 2 - (y + height / 2);
23272      return {
23273        path: {
23274          "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}`,
23275          transform: `${this.rotationTransform} translate(${tx} ${ty})`
23276        }
23277      };
23278    }
23279    const s1x = (newWidth - 2 * marginX) / (width - 2 * marginX);
23280    const s1y = (newHeight - 2 * marginY) / (height - 2 * marginY);
23281    const s2x = width / newWidth;
23282    const s2y = height / newHeight;
23283    return {
23284      path: {
23285        "transform-origin": `${Outline.svgRound(x)} ${Outline.svgRound(y)}`,
23286        transform: `${this.rotationTransform} scale(${s2x} ${s2y}) ` + `translate(${Outline.svgRound(marginX)} ${Outline.svgRound(marginY)}) scale(${s1x} ${s1y}) ` + `translate(${Outline.svgRound(-marginX)} ${Outline.svgRound(-marginY)})`
23287      }
23288    };
23289  }
23290  getPathResizedSVGProperties([newX, newY, newWidth, newHeight]) {
23291    const [marginX, marginY] = this.#getMarginComponents();
23292    const bbox = this.#bbox;
23293    const [x, y, width, height] = bbox;
23294    bbox[0] = newX;
23295    bbox[1] = newY;
23296    bbox[2] = newWidth;
23297    bbox[3] = newHeight;
23298    if (Math.abs(width - marginX) <= Outline.PRECISION || Math.abs(height - marginY) <= Outline.PRECISION) {
23299      const tx = newX + newWidth / 2 - (x + width / 2);
23300      const ty = newY + newHeight / 2 - (y + height / 2);
23301      for (const {
23302        line,
23303        points
23304      } of this.#lines) {
23305        Outline._translate(line, tx, ty, line);
23306        Outline._translate(points, tx, ty, points);
23307      }
23308      return {
23309        root: {
vendor: 2,598 bytes, lines 23310-23400
23310          viewBox: this.viewBox
23311        },
23312        path: {
23313          "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}`,
23314          transform: this.rotationTransform || null,
23315          d: this.toSVGPath()
23316        }
23317      };
23318    }
23319    const s1x = (newWidth - 2 * marginX) / (width - 2 * marginX);
23320    const s1y = (newHeight - 2 * marginY) / (height - 2 * marginY);
23321    const tx = -s1x * (x + marginX) + newX + marginX;
23322    const ty = -s1y * (y + marginY) + newY + marginY;
23323    if (s1x !== 1 || s1y !== 1 || tx !== 0 || ty !== 0) {
23324      for (const {
23325        line,
23326        points
23327      } of this.#lines) {
23328        Outline._rescale(line, tx, ty, s1x, s1y, line);
23329        Outline._rescale(points, tx, ty, s1x, s1y, points);
23330      }
23331    }
23332    return {
23333      root: {
23334        viewBox: this.viewBox
23335      },
23336      path: {
23337        "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}`,
23338        transform: this.rotationTransform || null,
23339        d: this.toSVGPath()
23340      }
23341    };
23342  }
23343  getPathTranslatedSVGProperties([newX, newY], parentDimensions) {
23344    const [newParentWidth, newParentHeight] = parentDimensions;
23345    const bbox = this.#bbox;
23346    const tx = newX - bbox[0];
23347    const ty = newY - bbox[1];
23348    if (this.#parentWidth === newParentWidth && this.#parentHeight === newParentHeight) {
23349      for (const {
23350        line,
23351        points
23352      } of this.#lines) {
23353        Outline._translate(line, tx, ty, line);
23354        Outline._translate(points, tx, ty, points);
23355      }
23356    } else {
23357      const sx = this.#parentWidth / newParentWidth;
23358      const sy = this.#parentHeight / newParentHeight;
23359      this.#parentWidth = newParentWidth;
23360      this.#parentHeight = newParentHeight;
23361      for (const {
23362        line,
23363        points
23364      } of this.#lines) {
23365        Outline._rescale(line, tx, ty, sx, sy, line);
23366        Outline._rescale(points, tx, ty, sx, sy, points);
23367      }
23368      bbox[2] *= sx;
23369      bbox[3] *= sy;
23370    }
23371    bbox[0] = newX;
23372    bbox[1] = newY;
23373    return {
23374      root: {
23375        viewBox: this.viewBox
23376      },
23377      path: {
23378        d: this.toSVGPath(),
23379        "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}`
23380      }
23381    };
23382  }
23383  get defaultSVGProperties() {
23384    const bbox = this.#bbox;
23385    return {
23386      root: {
23387        viewBox: this.viewBox
23388      },
23389      rootClass: {
23390        draw: true
23391      },
23392      path: {
23393        d: this.toSVGPath(),
23394        "transform-origin": `${Outline.svgRound(bbox[0])} ${Outline.svgRound(bbox[1])}`,
23395        transform: this.rotationTransform || null
23396      },
23397      bbox
23398    };
23399  }
23400}
vendor: 6,555 bytes, lines 23401-23651
23401
23402;// ./src/display/editor/ink.js
23403
23404
23405
23406
23407
23408
23409class InkDrawingOptions extends DrawingOptions {
23410  constructor(viewerParameters) {
23411    super();
23412    this._viewParameters = viewerParameters;
23413    super.updateProperties({
23414      fill: "none",
23415      stroke: AnnotationEditor._defaultLineColor,
23416      "stroke-opacity": 1,
23417      "stroke-width": 1,
23418      "stroke-linecap": "round",
23419      "stroke-linejoin": "round",
23420      "stroke-miterlimit": 10
23421    });
23422  }
23423  updateSVGProperty(name, value) {
23424    if (name === "stroke-width") {
23425      value ??= this["stroke-width"];
23426      value *= this._viewParameters.realScale;
23427    }
23428    super.updateSVGProperty(name, value);
23429  }
23430  clone() {
23431    const clone = new InkDrawingOptions(this._viewParameters);
23432    clone.updateAll(this);
23433    return clone;
23434  }
23435}
23436class InkEditor extends DrawingEditor {
23437  static _type = "ink";
23438  static _editorType = AnnotationEditorType.INK;
23439  static _defaultDrawingOptions = null;
23440  constructor(params) {
23441    super({
23442      ...params,
23443      name: "inkEditor"
23444    });
23445    this._willKeepAspectRatio = true;
23446    this.defaultL10nId = "pdfjs-editor-ink-editor";
23447  }
23448  static initialize(l10n, uiManager) {
23449    AnnotationEditor.initialize(l10n, uiManager);
23450    this._defaultDrawingOptions = new InkDrawingOptions(uiManager.viewParameters);
23451  }
23452  static getDefaultDrawingOptions(options) {
23453    const clone = this._defaultDrawingOptions.clone();
23454    clone.updateProperties(options);
23455    return clone;
23456  }
23457  static get supportMultipleDrawings() {
23458    return true;
23459  }
23460  static get typesMap() {
23461    return shadow(this, "typesMap", new Map([[AnnotationEditorParamsType.INK_THICKNESS, "stroke-width"], [AnnotationEditorParamsType.INK_COLOR, "stroke"], [AnnotationEditorParamsType.INK_OPACITY, "stroke-opacity"]]));
23462  }
23463  static createDrawerInstance(x, y, parentWidth, parentHeight, rotation) {
23464    return new InkDrawOutliner(x, y, parentWidth, parentHeight, rotation, this._defaultDrawingOptions["stroke-width"]);
23465  }
23466  static deserializeDraw(pageX, pageY, pageWidth, pageHeight, innerMargin, data) {
23467    return InkDrawOutline.deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, data);
23468  }
23469  static async deserialize(data, parent, uiManager) {
23470    let initialData = null;
23471    if (data instanceof InkAnnotationElement) {
23472      const {
23473        data: {
23474          inkLists,
23475          rect,
23476          rotation,
23477          id,
23478          color,
23479          opacity,
23480          borderStyle: {
23481            rawWidth: thickness
23482          },
23483          popupRef,
23484          richText,
23485          contentsObj,
23486          creationDate,
23487          modificationDate
23488        },
23489        parent: {
23490          page: {
23491            pageNumber
23492          }
23493        }
23494      } = data;
23495      initialData = data = {
23496        annotationType: AnnotationEditorType.INK,
23497        color: Array.from(color),
23498        thickness,
23499        opacity,
23500        paths: {
23501          points: inkLists
23502        },
23503        boxes: null,
23504        pageIndex: pageNumber - 1,
23505        rect: rect.slice(0),
23506        rotation,
23507        annotationElementId: id,
23508        id,
23509        deleted: false,
23510        popupRef,
23511        richText,
23512        comment: contentsObj?.str || null,
23513        creationDate,
23514        modificationDate
23515      };
23516    }
23517    const editor = await super.deserialize(data, parent, uiManager);
23518    editor._initialData = initialData;
23519    if (data.comment) {
23520      editor.setCommentData(data);
23521    }
23522    return editor;
23523  }
23524  get toolbarButtons() {
23525    this._colorPicker ||= new BasicColorPicker(this);
23526    return [["colorPicker", this._colorPicker]];
23527  }
23528  get colorType() {
23529    return AnnotationEditorParamsType.INK_COLOR;
23530  }
23531  get color() {
23532    return this._drawingOptions.stroke;
23533  }
23534  get opacity() {
23535    return this._drawingOptions["stroke-opacity"];
23536  }
23537  onScaleChanging() {
23538    if (!this.parent) {
23539      return;
23540    }
23541    super.onScaleChanging();
23542    const {
23543      _drawId,
23544      _drawingOptions,
23545      parent
23546    } = this;
23547    _drawingOptions.updateSVGProperty("stroke-width");
23548    parent.drawLayer.updateProperties(_drawId, _drawingOptions.toSVGProperties());
23549  }
23550  static onScaleChangingWhenDrawing() {
23551    const parent = this._currentParent;
23552    if (!parent) {
23553      return;
23554    }
23555    super.onScaleChangingWhenDrawing();
23556    this._defaultDrawingOptions.updateSVGProperty("stroke-width");
23557    parent.drawLayer.updateProperties(this._currentDrawId, this._defaultDrawingOptions.toSVGProperties());
23558  }
23559  createDrawingOptions({
23560    color,
23561    thickness,
23562    opacity
23563  }) {
23564    this._drawingOptions = InkEditor.getDefaultDrawingOptions({
23565      stroke: Util.makeHexColor(...color),
23566      "stroke-width": thickness,
23567      "stroke-opacity": opacity
23568    });
23569  }
23570  serialize(isForCopying = false) {
23571    if (this.isEmpty()) {
23572      return null;
23573    }
23574    if (this.deleted) {
23575      return this.serializeDeleted();
23576    }
23577    const {
23578      lines,
23579      points
23580    } = this.serializeDraw(isForCopying);
23581    const {
23582      _drawingOptions: {
23583        stroke,
23584        "stroke-opacity": opacity,
23585        "stroke-width": thickness
23586      }
23587    } = this;
23588    const serialized = Object.assign(super.serialize(isForCopying), {
23589      color: AnnotationEditor._colorManager.convert(stroke),
23590      opacity,
23591      thickness,
23592      paths: {
23593        lines,
23594        points
23595      }
23596    });
23597    this.addComment(serialized);
23598    if (isForCopying) {
23599      serialized.isCopy = true;
23600      return serialized;
23601    }
23602    if (this.annotationElementId && !this.#hasElementChanged(serialized)) {
23603      return null;
23604    }
23605    serialized.id = this.annotationElementId;
23606    return serialized;
23607  }
23608  #hasElementChanged(serialized) {
23609    const {
23610      color,
23611      thickness,
23612      opacity,
23613      pageIndex
23614    } = this._initialData;
23615    return this.hasEditedComment || this._hasBeenMoved || this._hasBeenResized || serialized.color.some((c, i) => c !== color[i]) || serialized.thickness !== thickness || serialized.opacity !== opacity || serialized.pageIndex !== pageIndex;
23616  }
23617  renderAnnotationElement(annotation) {
23618    if (this.deleted) {
23619      annotation.hide();
23620      return null;
23621    }
23622    const {
23623      points,
23624      rect
23625    } = this.serializeDraw(false);
23626    annotation.updateEdited({
23627      rect,
23628      thickness: this._drawingOptions["stroke-width"],
23629      points,
23630      popup: this.comment
23631    });
23632    return null;
23633  }
23634}
23635
23636;// ./src/display/editor/drawers/contour.js
23637
23638class ContourDrawOutline extends InkDrawOutline {
23639  toSVGPath() {
23640    let path = super.toSVGPath();
23641    if (!path.endsWith("Z")) {
23642      path += "Z";
23643    }
23644    return path;
23645  }
23646}
23647
23648;// ./src/display/editor/drawers/signaturedraw.js
23649
23650
23651
vendor: 4,991 bytes, lines 23652-23824
23652
23653const BASE_HEADER_LENGTH = 8;
23654const POINTS_PROPERTIES_NUMBER = 3;
23655class SignatureExtractor {
23656  static #PARAMETERS = {
23657    maxDim: 512,
23658    sigmaSFactor: 0.02,
23659    sigmaR: 25,
23660    kernelSize: 16
23661  };
23662  static #neighborIndexToId(i0, j0, i, j) {
23663    i -= i0;
23664    j -= j0;
23665    if (i === 0) {
23666      return j > 0 ? 0 : 4;
23667    }
23668    if (i === 1) {
23669      return j + 6;
23670    }
23671    return 2 - j;
23672  }
23673  static #neighborIdToIndex = new Int32Array([0, 1, -1, 1, -1, 0, -1, -1, 0, -1, 1, -1, 1, 0, 1, 1]);
23674  static #clockwiseNonZero(buf, width, i0, j0, i, j, offset) {
23675    const id = this.#neighborIndexToId(i0, j0, i, j);
23676    for (let k = 0; k < 8; k++) {
23677      const kk = (-k + id - offset + 16) % 8;
23678      const shiftI = this.#neighborIdToIndex[2 * kk];
23679      const shiftJ = this.#neighborIdToIndex[2 * kk + 1];
23680      if (buf[(i0 + shiftI) * width + (j0 + shiftJ)] !== 0) {
23681        return kk;
23682      }
23683    }
23684    return -1;
23685  }
23686  static #counterClockwiseNonZero(buf, width, i0, j0, i, j, offset) {
23687    const id = this.#neighborIndexToId(i0, j0, i, j);
23688    for (let k = 0; k < 8; k++) {
23689      const kk = (k + id + offset + 16) % 8;
23690      const shiftI = this.#neighborIdToIndex[2 * kk];
23691      const shiftJ = this.#neighborIdToIndex[2 * kk + 1];
23692      if (buf[(i0 + shiftI) * width + (j0 + shiftJ)] !== 0) {
23693        return kk;
23694      }
23695    }
23696    return -1;
23697  }
23698  static #findContours(buf, width, height, threshold) {
23699    const N = buf.length;
23700    const types = new Int32Array(N);
23701    for (let i = 0; i < N; i++) {
23702      types[i] = buf[i] <= threshold ? 1 : 0;
23703    }
23704    for (let i = 1; i < height - 1; i++) {
23705      types[i * width] = types[i * width + width - 1] = 0;
23706    }
23707    for (let i = 0; i < width; i++) {
23708      types[i] = types[width * height - 1 - i] = 0;
23709    }
23710    let nbd = 1;
23711    let lnbd;
23712    const contours = [];
23713    for (let i = 1; i < height - 1; i++) {
23714      lnbd = 1;
23715      for (let j = 1; j < width - 1; j++) {
23716        const ij = i * width + j;
23717        const pix = types[ij];
23718        if (pix === 0) {
23719          continue;
23720        }
23721        let i2 = i;
23722        let j2 = j;
23723        if (pix === 1 && types[ij - 1] === 0) {
23724          nbd += 1;
23725          j2 -= 1;
23726        } else if (pix >= 1 && types[ij + 1] === 0) {
23727          nbd += 1;
23728          j2 += 1;
23729          if (pix > 1) {
23730            lnbd = pix;
23731          }
23732        } else {
23733          if (pix !== 1) {
23734            lnbd = Math.abs(pix);
23735          }
23736          continue;
23737        }
23738        const points = [j, i];
23739        const isHole = j2 === j + 1;
23740        const contour = {
23741          isHole,
23742          points,
23743          id: nbd,
23744          parent: 0
23745        };
23746        contours.push(contour);
23747        let contour0;
23748        for (const c of contours) {
23749          if (c.id === lnbd) {
23750            contour0 = c;
23751            break;
23752          }
23753        }
23754        if (!contour0) {
23755          contour.parent = isHole ? lnbd : 0;
23756        } else if (contour0.isHole) {
23757          contour.parent = isHole ? contour0.parent : lnbd;
23758        } else {
23759          contour.parent = isHole ? lnbd : contour0.parent;
23760        }
23761        const k = this.#clockwiseNonZero(types, width, i, j, i2, j2, 0);
23762        if (k === -1) {
23763          types[ij] = -nbd;
23764          if (types[ij] !== 1) {
23765            lnbd = Math.abs(types[ij]);
23766          }
23767          continue;
23768        }
23769        let shiftI = this.#neighborIdToIndex[2 * k];
23770        let shiftJ = this.#neighborIdToIndex[2 * k + 1];
23771        const i1 = i + shiftI;
23772        const j1 = j + shiftJ;
23773        i2 = i1;
23774        j2 = j1;
23775        let i3 = i;
23776        let j3 = j;
23777        while (true) {
23778          const kk = this.#counterClockwiseNonZero(types, width, i3, j3, i2, j2, 1);
23779          shiftI = this.#neighborIdToIndex[2 * kk];
23780          shiftJ = this.#neighborIdToIndex[2 * kk + 1];
23781          const i4 = i3 + shiftI;
23782          const j4 = j3 + shiftJ;
23783          points.push(j4, i4);
23784          const ij3 = i3 * width + j3;
23785          if (types[ij3 + 1] === 0) {
23786            types[ij3] = -nbd;
23787          } else if (types[ij3] === 1) {
23788            types[ij3] = nbd;
23789          }
23790          if (i4 === i && j4 === j && i3 === i1 && j3 === j1) {
23791            if (types[ij] !== 1) {
23792              lnbd = Math.abs(types[ij]);
23793            }
23794            break;
23795          } else {
23796            i2 = i3;
23797            j2 = j3;
23798            i3 = i4;
23799            j3 = j4;
23800          }
23801        }
23802      }
23803    }
23804    return contours;
23805  }
23806  static #douglasPeuckerHelper(points, start, end, output) {
23807    if (end - start <= 4) {
23808      for (let i = start; i < end - 2; i += 2) {
23809        output.push(points[i], points[i + 1]);
23810      }
23811      return;
23812    }
23813    const ax = points[start];
23814    const ay = points[start + 1];
23815    const abx = points[end - 4] - ax;
23816    const aby = points[end - 3] - ay;
23817    const dist = Math.hypot(abx, aby);
23818    const nabx = abx / dist;
23819    const naby = aby / dist;
23820    const aa = nabx * ay - naby * ax;
23821    const m = aby / abx;
23822    const invS = 1 / dist;
23823    const phi = Math.atan(m);
23824    const cosPhi = Math.cos(phi);
vendor: 12,104 bytes, lines 23825-24191
23825    const sinPhi = Math.sin(phi);
23826    const tmax = invS * (Math.abs(cosPhi) + Math.abs(sinPhi));
23827    const poly = invS * (1 - tmax + tmax ** 2);
23828    const partialPhi = Math.max(Math.atan(Math.abs(sinPhi + cosPhi) * poly), Math.atan(Math.abs(sinPhi - cosPhi) * poly));
23829    let dmax = 0;
23830    let index = start;
23831    for (let i = start + 2; i < end - 2; i += 2) {
23832      const d = Math.abs(aa - nabx * points[i + 1] + naby * points[i]);
23833      if (d > dmax) {
23834        index = i;
23835        dmax = d;
23836      }
23837    }
23838    if (dmax > (dist * partialPhi) ** 2) {
23839      this.#douglasPeuckerHelper(points, start, index + 2, output);
23840      this.#douglasPeuckerHelper(points, index, end, output);
23841    } else {
23842      output.push(ax, ay);
23843    }
23844  }
23845  static #douglasPeucker(points) {
23846    const output = [];
23847    const len = points.length;
23848    this.#douglasPeuckerHelper(points, 0, len, output);
23849    output.push(points[len - 2], points[len - 1]);
23850    return output.length <= 4 ? null : output;
23851  }
23852  static #bilateralFilter(buf, width, height, sigmaS, sigmaR, kernelSize) {
23853    const kernel = new Float32Array(kernelSize ** 2);
23854    const sigmaS2 = -2 * sigmaS ** 2;
23855    const halfSize = kernelSize >> 1;
23856    for (let i = 0; i < kernelSize; i++) {
23857      const x = (i - halfSize) ** 2;
23858      for (let j = 0; j < kernelSize; j++) {
23859        kernel[i * kernelSize + j] = Math.exp((x + (j - halfSize) ** 2) / sigmaS2);
23860      }
23861    }
23862    const rangeValues = new Float32Array(256);
23863    const sigmaR2 = -2 * sigmaR ** 2;
23864    for (let i = 0; i < 256; i++) {
23865      rangeValues[i] = Math.exp(i ** 2 / sigmaR2);
23866    }
23867    const N = buf.length;
23868    const out = new Uint8Array(N);
23869    const histogram = new Uint32Array(256);
23870    for (let i = 0; i < height; i++) {
23871      for (let j = 0; j < width; j++) {
23872        const ij = i * width + j;
23873        const center = buf[ij];
23874        let sum = 0;
23875        let norm = 0;
23876        for (let k = 0; k < kernelSize; k++) {
23877          const y = i + k - halfSize;
23878          if (y < 0 || y >= height) {
23879            continue;
23880          }
23881          for (let l = 0; l < kernelSize; l++) {
23882            const x = j + l - halfSize;
23883            if (x < 0 || x >= width) {
23884              continue;
23885            }
23886            const neighbour = buf[y * width + x];
23887            const w = kernel[k * kernelSize + l] * rangeValues[Math.abs(neighbour - center)];
23888            sum += neighbour * w;
23889            norm += w;
23890          }
23891        }
23892        const pix = out[ij] = Math.round(sum / norm);
23893        histogram[pix]++;
23894      }
23895    }
23896    return [out, histogram];
23897  }
23898  static #getHistogram(buf) {
23899    const histogram = new Uint32Array(256);
23900    for (const g of buf) {
23901      histogram[g]++;
23902    }
23903    return histogram;
23904  }
23905  static #toUint8(buf) {
23906    const N = buf.length;
23907    const out = new Uint8ClampedArray(N >> 2);
23908    let max = -Infinity;
23909    let min = Infinity;
23910    for (let i = 0, ii = out.length; i < ii; i++) {
23911      const pix = out[i] = buf[i << 2];
23912      max = Math.max(max, pix);
23913      min = Math.min(min, pix);
23914    }
23915    const ratio = 255 / (max - min);
23916    for (let i = 0, ii = out.length; i < ii; i++) {
23917      out[i] = (out[i] - min) * ratio;
23918    }
23919    return out;
23920  }
23921  static #guessThreshold(histogram) {
23922    let i;
23923    let M = -Infinity;
23924    let L = -Infinity;
23925    const min = histogram.findIndex(v => v !== 0);
23926    let pos = min;
23927    let spos = min;
23928    for (i = min; i < 256; i++) {
23929      const v = histogram[i];
23930      if (v > M) {
23931        if (i - pos > L) {
23932          L = i - pos;
23933          spos = i - 1;
23934        }
23935        M = v;
23936        pos = i;
23937      }
23938    }
23939    for (i = spos - 1; i >= 0; i--) {
23940      if (histogram[i] > histogram[i + 1]) {
23941        break;
23942      }
23943    }
23944    return i;
23945  }
23946  static #getGrayPixels(bitmap) {
23947    const originalBitmap = bitmap;
23948    const {
23949      width,
23950      height
23951    } = bitmap;
23952    const {
23953      maxDim
23954    } = this.#PARAMETERS;
23955    let newWidth = width;
23956    let newHeight = height;
23957    if (width > maxDim || height > maxDim) {
23958      let prevWidth = width;
23959      let prevHeight = height;
23960      let steps = Math.log2(Math.max(width, height) / maxDim);
23961      const isteps = Math.floor(steps);
23962      steps = steps === isteps ? isteps - 1 : isteps;
23963      for (let i = 0; i < steps; i++) {
23964        newWidth = Math.ceil(prevWidth / 2);
23965        newHeight = Math.ceil(prevHeight / 2);
23966        const offscreen = new OffscreenCanvas(newWidth, newHeight);
23967        const ctx = offscreen.getContext("2d");
23968        ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight);
23969        prevWidth = newWidth;
23970        prevHeight = newHeight;
23971        if (bitmap !== originalBitmap) {
23972          bitmap.close();
23973        }
23974        bitmap = offscreen.transferToImageBitmap();
23975      }
23976      const ratio = Math.min(maxDim / newWidth, maxDim / newHeight);
23977      newWidth = Math.round(newWidth * ratio);
23978      newHeight = Math.round(newHeight * ratio);
23979    }
23980    const offscreen = new OffscreenCanvas(newWidth, newHeight);
23981    const ctx = offscreen.getContext("2d", {
23982      willReadFrequently: true
23983    });
23984    ctx.fillStyle = "white";
23985    ctx.fillRect(0, 0, newWidth, newHeight);
23986    ctx.filter = "grayscale(1)";
23987    ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, newWidth, newHeight);
23988    const grayImage = ctx.getImageData(0, 0, newWidth, newHeight).data;
23989    const uint8Buf = this.#toUint8(grayImage);
23990    return [uint8Buf, newWidth, newHeight];
23991  }
23992  static extractContoursFromText(text, {
23993    fontFamily,
23994    fontStyle,
23995    fontWeight
23996  }, pageWidth, pageHeight, rotation, innerMargin) {
23997    let canvas = new OffscreenCanvas(1, 1);
23998    let ctx = canvas.getContext("2d", {
23999      alpha: false
24000    });
24001    const fontSize = 200;
24002    const font = ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
24003    const {
24004      actualBoundingBoxLeft,
24005      actualBoundingBoxRight,
24006      actualBoundingBoxAscent,
24007      actualBoundingBoxDescent,
24008      fontBoundingBoxAscent,
24009      fontBoundingBoxDescent,
24010      width
24011    } = ctx.measureText(text);
24012    const SCALE = 1.5;
24013    const canvasWidth = Math.ceil(Math.max(Math.abs(actualBoundingBoxLeft) + Math.abs(actualBoundingBoxRight) || 0, width) * SCALE);
24014    const canvasHeight = Math.ceil(Math.max(Math.abs(actualBoundingBoxAscent) + Math.abs(actualBoundingBoxDescent) || fontSize, Math.abs(fontBoundingBoxAscent) + Math.abs(fontBoundingBoxDescent) || fontSize) * SCALE);
24015    canvas = new OffscreenCanvas(canvasWidth, canvasHeight);
24016    ctx = canvas.getContext("2d", {
24017      alpha: true,
24018      willReadFrequently: true
24019    });
24020    ctx.font = font;
24021    ctx.filter = "grayscale(1)";
24022    ctx.fillStyle = "white";
24023    ctx.fillRect(0, 0, canvasWidth, canvasHeight);
24024    ctx.fillStyle = "black";
24025    ctx.fillText(text, canvasWidth * (SCALE - 1) / 2, canvasHeight * (3 - SCALE) / 2);
24026    const uint8Buf = this.#toUint8(ctx.getImageData(0, 0, canvasWidth, canvasHeight).data);
24027    const histogram = this.#getHistogram(uint8Buf);
24028    const threshold = this.#guessThreshold(histogram);
24029    const contourList = this.#findContours(uint8Buf, canvasWidth, canvasHeight, threshold);
24030    return this.processDrawnLines({
24031      lines: {
24032        curves: contourList,
24033        width: canvasWidth,
24034        height: canvasHeight
24035      },
24036      pageWidth,
24037      pageHeight,
24038      rotation,
24039      innerMargin,
24040      mustSmooth: true,
24041      areContours: true
24042    });
24043  }
24044  static process(bitmap, pageWidth, pageHeight, rotation, innerMargin) {
24045    const [uint8Buf, width, height] = this.#getGrayPixels(bitmap);
24046    const [buffer, histogram] = this.#bilateralFilter(uint8Buf, width, height, Math.hypot(width, height) * this.#PARAMETERS.sigmaSFactor, this.#PARAMETERS.sigmaR, this.#PARAMETERS.kernelSize);
24047    const threshold = this.#guessThreshold(histogram);
24048    const contourList = this.#findContours(buffer, width, height, threshold);
24049    return this.processDrawnLines({
24050      lines: {
24051        curves: contourList,
24052        width,
24053        height
24054      },
24055      pageWidth,
24056      pageHeight,
24057      rotation,
24058      innerMargin,
24059      mustSmooth: true,
24060      areContours: true
24061    });
24062  }
24063  static processDrawnLines({
24064    lines,
24065    pageWidth,
24066    pageHeight,
24067    rotation,
24068    innerMargin,
24069    mustSmooth,
24070    areContours
24071  }) {
24072    if (rotation % 180 !== 0) {
24073      [pageWidth, pageHeight] = [pageHeight, pageWidth];
24074    }
24075    const {
24076      curves,
24077      width,
24078      height
24079    } = lines;
24080    const thickness = lines.thickness ?? 0;
24081    const linesAndPoints = [];
24082    const ratio = Math.min(pageWidth / width, pageHeight / height);
24083    const xScale = ratio / pageWidth;
24084    const yScale = ratio / pageHeight;
24085    const newCurves = [];
24086    for (const {
24087      points
24088    } of curves) {
24089      const reducedPoints = mustSmooth ? this.#douglasPeucker(points) : points;
24090      if (!reducedPoints) {
24091        continue;
24092      }
24093      newCurves.push(reducedPoints);
24094      const len = reducedPoints.length;
24095      const newPoints = new Float32Array(len);
24096      const line = new Float32Array(3 * (len === 2 ? 2 : len - 2));
24097      linesAndPoints.push({
24098        line,
24099        points: newPoints
24100      });
24101      if (len === 2) {
24102        newPoints[0] = reducedPoints[0] * xScale;
24103        newPoints[1] = reducedPoints[1] * yScale;
24104        line.set([NaN, NaN, NaN, NaN, newPoints[0], newPoints[1]], 0);
24105        continue;
24106      }
24107      let [x1, y1, x2, y2] = reducedPoints;
24108      x1 *= xScale;
24109      y1 *= yScale;
24110      x2 *= xScale;
24111      y2 *= yScale;
24112      newPoints.set([x1, y1, x2, y2], 0);
24113      line.set([NaN, NaN, NaN, NaN, x1, y1], 0);
24114      for (let i = 4; i < len; i += 2) {
24115        const x = newPoints[i] = reducedPoints[i] * xScale;
24116        const y = newPoints[i + 1] = reducedPoints[i + 1] * yScale;
24117        line.set(Outline.createBezierPoints(x1, y1, x2, y2, x, y), (i - 2) * 3);
24118        [x1, y1, x2, y2] = [x2, y2, x, y];
24119      }
24120    }
24121    if (linesAndPoints.length === 0) {
24122      return null;
24123    }
24124    const outline = areContours ? new ContourDrawOutline() : new InkDrawOutline();
24125    outline.build(linesAndPoints, pageWidth, pageHeight, 1, rotation, areContours ? 0 : thickness, innerMargin);
24126    return {
24127      outline,
24128      newCurves,
24129      areContours,
24130      thickness,
24131      width,
24132      height
24133    };
24134  }
24135  static async compressSignature({
24136    outlines,
24137    areContours,
24138    thickness,
24139    width,
24140    height
24141  }) {
24142    let minDiff = Infinity;
24143    let maxDiff = -Infinity;
24144    let outlinesLength = 0;
24145    for (const points of outlines) {
24146      outlinesLength += points.length;
24147      for (let i = 2, ii = points.length; i < ii; i++) {
24148        const dx = points[i] - points[i - 2];
24149        minDiff = Math.min(minDiff, dx);
24150        maxDiff = Math.max(maxDiff, dx);
24151      }
24152    }
24153    let bufferType;
24154    if (minDiff >= -128 && maxDiff <= 127) {
24155      bufferType = Int8Array;
24156    } else if (minDiff >= -32768 && maxDiff <= 32767) {
24157      bufferType = Int16Array;
24158    } else {
24159      bufferType = Int32Array;
24160    }
24161    const len = outlines.length;
24162    const headerLength = BASE_HEADER_LENGTH + POINTS_PROPERTIES_NUMBER * len;
24163    const header = new Uint32Array(headerLength);
24164    let offset = 0;
24165    header[offset++] = headerLength * Uint32Array.BYTES_PER_ELEMENT + (outlinesLength - 2 * len) * bufferType.BYTES_PER_ELEMENT;
24166    header[offset++] = 0;
24167    header[offset++] = width;
24168    header[offset++] = height;
24169    header[offset++] = areContours ? 0 : 1;
24170    header[offset++] = Math.max(0, Math.floor(thickness ?? 0));
24171    header[offset++] = len;
24172    header[offset++] = bufferType.BYTES_PER_ELEMENT;
24173    for (const points of outlines) {
24174      header[offset++] = points.length - 2;
24175      header[offset++] = points[0];
24176      header[offset++] = points[1];
24177    }
24178    const cs = new CompressionStream("deflate-raw");
24179    const writer = cs.writable.getWriter();
24180    await writer.ready;
24181    writer.write(header);
24182    const BufferCtor = bufferType.prototype.constructor;
24183    for (const points of outlines) {
24184      const diffs = new BufferCtor(points.length - 2);
24185      for (let i = 2, ii = points.length; i < ii; i++) {
24186        diffs[i - 2] = points[i] - points[i - 2];
24187      }
24188      writer.write(diffs);
24189    }
24190    writer.close();
24191    const b
vendor: 7,528 bytes, lines 24191-24477
24191uf = await new Response(cs.readable).arrayBuffer();
24192    const bytes = new Uint8Array(buf);
24193    return bytes.toBase64();
24194  }
24195  static async decompressSignature(signatureData) {
24196    try {
24197      const bytes = Uint8Array.fromBase64(signatureData);
24198      const {
24199        readable,
24200        writable
24201      } = new DecompressionStream("deflate-raw");
24202      const writer = writable.getWriter();
24203      await writer.ready;
24204      writer.write(bytes).then(async () => {
24205        await writer.ready;
24206        await writer.close();
24207      }).catch(() => {});
24208      let data = null;
24209      let offset = 0;
24210      for await (const chunk of readable) {
24211        data ||= new Uint8Array(new Uint32Array(chunk.buffer, 0, 4)[0]);
24212        data.set(chunk, offset);
24213        offset += chunk.length;
24214      }
24215      const header = new Uint32Array(data.buffer, 0, data.length >> 2);
24216      const version = header[1];
24217      if (version !== 0) {
24218        throw new Error(`Invalid version: ${version}`);
24219      }
24220      const width = header[2];
24221      const height = header[3];
24222      const areContours = header[4] === 0;
24223      const thickness = header[5];
24224      const numberOfDrawings = header[6];
24225      const bufferType = header[7];
24226      const outlines = [];
24227      const diffsOffset = (BASE_HEADER_LENGTH + POINTS_PROPERTIES_NUMBER * numberOfDrawings) * Uint32Array.BYTES_PER_ELEMENT;
24228      let diffs;
24229      switch (bufferType) {
24230        case Int8Array.BYTES_PER_ELEMENT:
24231          diffs = new Int8Array(data.buffer, diffsOffset);
24232          break;
24233        case Int16Array.BYTES_PER_ELEMENT:
24234          diffs = new Int16Array(data.buffer, diffsOffset);
24235          break;
24236        case Int32Array.BYTES_PER_ELEMENT:
24237          diffs = new Int32Array(data.buffer, diffsOffset);
24238          break;
24239      }
24240      offset = 0;
24241      for (let i = 0; i < numberOfDrawings; i++) {
24242        const len = header[POINTS_PROPERTIES_NUMBER * i + BASE_HEADER_LENGTH];
24243        const points = new Float32Array(len + 2);
24244        outlines.push(points);
24245        for (let j = 0; j < POINTS_PROPERTIES_NUMBER - 1; j++) {
24246          points[j] = header[POINTS_PROPERTIES_NUMBER * i + BASE_HEADER_LENGTH + j + 1];
24247        }
24248        for (let j = 0; j < len; j++) {
24249          points[j + 2] = points[j] + diffs[offset++];
24250        }
24251      }
24252      return {
24253        areContours,
24254        thickness,
24255        outlines,
24256        width,
24257        height
24258      };
24259    } catch (e) {
24260      warn(`decompressSignature: ${e}`);
24261      return null;
24262    }
24263  }
24264}
24265
24266;// ./src/display/editor/signature.js
24267
24268
24269
24270
24271
24272
24273
24274class SignatureOptions extends DrawingOptions {
24275  constructor() {
24276    super();
24277    super.updateProperties({
24278      fill: AnnotationEditor._defaultLineColor,
24279      "stroke-width": 0
24280    });
24281  }
24282  clone() {
24283    const clone = new SignatureOptions();
24284    clone.updateAll(this);
24285    return clone;
24286  }
24287}
24288class DrawnSignatureOptions extends InkDrawingOptions {
24289  constructor(viewerParameters) {
24290    super(viewerParameters);
24291    super.updateProperties({
24292      stroke: AnnotationEditor._defaultLineColor,
24293      "stroke-width": 1
24294    });
24295  }
24296  clone() {
24297    const clone = new DrawnSignatureOptions(this._viewParameters);
24298    clone.updateAll(this);
24299    return clone;
24300  }
24301}
24302class SignatureEditor extends DrawingEditor {
24303  #isExtracted = false;
24304  #description = null;
24305  #signatureData = null;
24306  #signatureUUID = null;
24307  static _type = "signature";
24308  static _editorType = AnnotationEditorType.SIGNATURE;
24309  static _defaultDrawingOptions = null;
24310  constructor(params) {
24311    super({
24312      ...params,
24313      mustBeCommitted: true,
24314      name: "signatureEditor"
24315    });
24316    this._willKeepAspectRatio = true;
24317    this.#signatureData = params.signatureData || null;
24318    this.#description = null;
24319    this.defaultL10nId = "pdfjs-editor-signature-editor1";
24320  }
24321  static initialize(l10n, uiManager) {
24322    AnnotationEditor.initialize(l10n, uiManager);
24323    this._defaultDrawingOptions = new SignatureOptions();
24324    this._defaultDrawnSignatureOptions = new DrawnSignatureOptions(uiManager.viewParameters);
24325  }
24326  static getDefaultDrawingOptions(options) {
24327    const clone = this._defaultDrawingOptions.clone();
24328    clone.updateProperties(options);
24329    return clone;
24330  }
24331  static get supportMultipleDrawings() {
24332    return false;
24333  }
24334  static get typesMap() {
24335    return shadow(this, "typesMap", new Map());
24336  }
24337  static get isDrawer() {
24338    return false;
24339  }
24340  get telemetryFinalData() {
24341    return {
24342      type: "signature",
24343      hasDescription: !!this.#description
24344    };
24345  }
24346  static computeTelemetryFinalData(data) {
24347    const hasDescriptionStats = data.get("hasDescription");
24348    return {
24349      hasAltText: hasDescriptionStats.get(true) ?? 0,
24350      hasNoAltText: hasDescriptionStats.get(false) ?? 0
24351    };
24352  }
24353  get isResizable() {
24354    return true;
24355  }
24356  onScaleChanging() {
24357    if (this._drawId === null) {
24358      return;
24359    }
24360    super.onScaleChanging();
24361  }
24362  render() {
24363    if (this.div) {
24364      return this.div;
24365    }
24366    let baseX, baseY;
24367    const {
24368      _isCopy
24369    } = this;
24370    if (_isCopy) {
24371      this._isCopy = false;
24372      baseX = this.x;
24373      baseY = this.y;
24374    }
24375    super.render();
24376    if (this._drawId === null) {
24377      if (this.#signatureData) {
24378        const {
24379          lines,
24380          mustSmooth,
24381          areContours,
24382          description,
24383          uuid,
24384          heightInPage
24385        } = this.#signatureData;
24386        const {
24387          rawDims: {
24388            pageWidth,
24389            pageHeight
24390          },
24391          rotation
24392        } = this.parent.viewport;
24393        const outline = SignatureExtractor.processDrawnLines({
24394          lines,
24395          pageWidth,
24396          pageHeight,
24397          rotation,
24398          innerMargin: SignatureEditor._INNER_MARGIN,
24399          mustSmooth,
24400          areContours
24401        });
24402        this.addSignature(outline, heightInPage, description, uuid);
24403      } else {
24404        this.div.setAttribute("data-l10n-args", JSON.stringify({
24405          description: ""
24406        }));
24407        this.div.hidden = true;
24408        this._uiManager.getSignature(this);
24409      }
24410    } else {
24411      this.div.setAttribute("data-l10n-args", JSON.stringify({
24412        description: this.#description || ""
24413      }));
24414    }
24415    if (_isCopy) {
24416      this._isCopy = true;
24417      this._moveAfterPaste(baseX, baseY);
24418    }
24419    return this.div;
24420  }
24421  setUuid(uuid) {
24422    this.#signatureUUID = uuid;
24423    this.addEditToolbar();
24424  }
24425  getUuid() {
24426    return this.#signatureUUID;
24427  }
24428  get description() {
24429    return this.#description;
24430  }
24431  set description(description) {
24432    this.#description = description;
24433    if (!this.div) {
24434      return;
24435    }
24436    this.div.setAttribute("data-l10n-args", JSON.stringify({
24437      description
24438    }));
24439    super.addEditToolbar().then(toolbar => {
24440      toolbar?.updateEditSignatureButton(description);
24441    });
24442  }
24443  getSignaturePreview() {
24444    const {
24445      newCurves,
24446      areContours,
24447      thickness,
24448      width,
24449      height
24450    } = this.#signatureData;
24451    const maxDim = Math.max(width, height);
24452    const outlineData = SignatureExtractor.processDrawnLines({
24453      lines: {
24454        curves: newCurves.map(points => ({
24455          points
24456        })),
24457        thickness,
24458        width,
24459        height
24460      },
24461      pageWidth: maxDim,
24462      pageHeight: maxDim,
24463      rotation: 0,
24464      innerMargin: 0,
24465      mustSmooth: false,
24466      areContours
24467    });
24468    return {
24469      areContours,
24470      outline: outlineData.outline
24471    };
24472  }
24473  get toolbarButtons() {
24474    if (this._uiManager.signatureManager) {
24475      return [["editSignature", this._uiManager.signatureManager]];
24476    }
24477    return
vendor: 13,796 bytes, lines 24477-24984
24477 super.toolbarButtons;
24478  }
24479  addSignature(data, heightInPage, description, uuid) {
24480    const {
24481      x: savedX,
24482      y: savedY
24483    } = this;
24484    const {
24485      outline
24486    } = this.#signatureData = data;
24487    this.#isExtracted = outline instanceof ContourDrawOutline;
24488    this.description = description;
24489    let drawingOptions;
24490    if (this.#isExtracted) {
24491      drawingOptions = SignatureEditor.getDefaultDrawingOptions();
24492    } else {
24493      drawingOptions = SignatureEditor._defaultDrawnSignatureOptions.clone();
24494      drawingOptions.updateProperties({
24495        "stroke-width": outline.thickness
24496      });
24497    }
24498    this._addOutlines({
24499      drawOutlines: outline,
24500      drawingOptions
24501    });
24502    const [, pageHeight] = this.pageDimensions;
24503    let newHeight = heightInPage / pageHeight;
24504    newHeight = newHeight >= 1 ? 0.5 : newHeight;
24505    this.width *= newHeight / this.height;
24506    if (this.width >= 1) {
24507      newHeight *= 0.9 / this.width;
24508      this.width = 0.9;
24509    }
24510    this.height = newHeight;
24511    this.setDims();
24512    this.x = savedX;
24513    this.y = savedY;
24514    this.center();
24515    this._onResized();
24516    this.onScaleChanging();
24517    this.rotate();
24518    this._uiManager.addToAnnotationStorage(this);
24519    this.setUuid(uuid);
24520    this._reportTelemetry({
24521      action: "pdfjs.signature.inserted",
24522      data: {
24523        hasBeenSaved: !!uuid,
24524        hasDescription: !!description
24525      }
24526    });
24527    this.div.hidden = false;
24528  }
24529  getFromImage(bitmap) {
24530    const {
24531      rawDims: {
24532        pageWidth,
24533        pageHeight
24534      },
24535      rotation
24536    } = this.parent.viewport;
24537    return SignatureExtractor.process(bitmap, pageWidth, pageHeight, rotation, SignatureEditor._INNER_MARGIN);
24538  }
24539  getFromText(text, fontInfo) {
24540    const {
24541      rawDims: {
24542        pageWidth,
24543        pageHeight
24544      },
24545      rotation
24546    } = this.parent.viewport;
24547    return SignatureExtractor.extractContoursFromText(text, fontInfo, pageWidth, pageHeight, rotation, SignatureEditor._INNER_MARGIN);
24548  }
24549  getDrawnSignature(curves) {
24550    const {
24551      rawDims: {
24552        pageWidth,
24553        pageHeight
24554      },
24555      rotation
24556    } = this.parent.viewport;
24557    return SignatureExtractor.processDrawnLines({
24558      lines: curves,
24559      pageWidth,
24560      pageHeight,
24561      rotation,
24562      innerMargin: SignatureEditor._INNER_MARGIN,
24563      mustSmooth: false,
24564      areContours: false
24565    });
24566  }
24567  createDrawingOptions({
24568    areContours,
24569    thickness
24570  }) {
24571    if (areContours) {
24572      this._drawingOptions = SignatureEditor.getDefaultDrawingOptions();
24573    } else {
24574      this._drawingOptions = SignatureEditor._defaultDrawnSignatureOptions.clone();
24575      this._drawingOptions.updateProperties({
24576        "stroke-width": thickness
24577      });
24578    }
24579  }
24580  serialize(isForCopying = false) {
24581    if (this.isEmpty()) {
24582      return null;
24583    }
24584    const {
24585      lines,
24586      points
24587    } = this.serializeDraw(isForCopying);
24588    const {
24589      _drawingOptions: {
24590        "stroke-width": thickness
24591      }
24592    } = this;
24593    const serialized = Object.assign(super.serialize(isForCopying), {
24594      isSignature: true,
24595      areContours: this.#isExtracted,
24596      color: [0, 0, 0],
24597      thickness: this.#isExtracted ? 0 : thickness
24598    });
24599    this.addComment(serialized);
24600    if (isForCopying) {
24601      serialized.paths = {
24602        lines,
24603        points
24604      };
24605      serialized.uuid = this.#signatureUUID;
24606      serialized.isCopy = true;
24607    } else {
24608      serialized.lines = lines;
24609    }
24610    if (this.#description) {
24611      serialized.accessibilityData = {
24612        type: "Figure",
24613        alt: this.#description
24614      };
24615    }
24616    return serialized;
24617  }
24618  static deserializeDraw(pageX, pageY, pageWidth, pageHeight, innerMargin, data) {
24619    if (data.areContours) {
24620      return ContourDrawOutline.deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, data);
24621    }
24622    return InkDrawOutline.deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, data);
24623  }
24624  static async deserialize(data, parent, uiManager) {
24625    const editor = await super.deserialize(data, parent, uiManager);
24626    editor.#isExtracted = data.areContours;
24627    editor.description = data.accessibilityData?.alt || "";
24628    editor.#signatureUUID = data.uuid;
24629    return editor;
24630  }
24631}
24632
24633;// ./src/display/editor/stamp.js
24634
24635
24636
24637
24638class StampEditor extends AnnotationEditor {
24639  #bitmap = null;
24640  #bitmapId = null;
24641  #bitmapPromise = null;
24642  #bitmapUrl = null;
24643  #bitmapFile = null;
24644  #bitmapFileName = "";
24645  #canvas = null;
24646  #missingCanvas = false;
24647  #resizeTimeoutId = null;
24648  #isSvg = false;
24649  #hasBeenAddedInUndoStack = false;
24650  static _type = "stamp";
24651  static _editorType = AnnotationEditorType.STAMP;
24652  constructor(params) {
24653    super({
24654      ...params,
24655      name: "stampEditor"
24656    });
24657    this.#bitmapUrl = params.bitmapUrl;
24658    this.#bitmapFile = params.bitmapFile;
24659    this.defaultL10nId = "pdfjs-editor-stamp-editor";
24660  }
24661  static initialize(l10n, uiManager) {
24662    AnnotationEditor.initialize(l10n, uiManager);
24663  }
24664  static isHandlingMimeForPasting(mime) {
24665    return SupportedImageMimeTypes.includes(mime);
24666  }
24667  static paste(item, parent) {
24668    parent.pasteEditor({
24669      mode: AnnotationEditorType.STAMP
24670    }, {
24671      bitmapFile: item.getAsFile()
24672    });
24673  }
24674  altTextFinish() {
24675    if (this._uiManager.useNewAltTextFlow) {
24676      this.div.hidden = false;
24677    }
24678    super.altTextFinish();
24679  }
24680  get telemetryFinalData() {
24681    return {
24682      type: "stamp",
24683      hasAltText: !!this.altTextData?.altText
24684    };
24685  }
24686  static computeTelemetryFinalData(data) {
24687    const hasAltTextStats = data.get("hasAltText");
24688    return {
24689      hasAltText: hasAltTextStats.get(true) ?? 0,
24690      hasNoAltText: hasAltTextStats.get(false) ?? 0
24691    };
24692  }
24693  #getBitmapFetched(data, fromId = false) {
24694    if (!data) {
24695      this.remove();
24696      return;
24697    }
24698    this.#bitmap = data.bitmap;
24699    if (!fromId) {
24700      this.#bitmapId = data.id;
24701      this.#isSvg = data.isSvg;
24702    }
24703    if (data.file) {
24704      this.#bitmapFileName = data.file.name;
24705    }
24706    this.#createCanvas();
24707  }
24708  #getBitmapDone() {
24709    this.#bitmapPromise = null;
24710    this._uiManager.enableWaiting(false);
24711    if (!this.#canvas) {
24712      return;
24713    }
24714    if (this._uiManager.useNewAltTextWhenAddingImage && this._uiManager.useNewAltTextFlow && this.#bitmap) {
24715      this.addEditToolbar().then(() => {
24716        this._editToolbar.hide();
24717        this._uiManager.editAltText(this, true);
24718      });
24719      return;
24720    }
24721    if (!this._uiManager.useNewAltTextWhenAddingImage && this._uiManager.useNewAltTextFlow && this.#bitmap) {
24722      this._reportTelemetry({
24723        action: "pdfjs.image.image_added",
24724        data: {
24725          alt_text_modal: false,
24726          alt_text_type: "empty"
24727        }
24728      });
24729      try {
24730        this.mlGuessAltText();
24731      } catch {}
24732    }
24733    this.div.focus();
24734  }
24735  async mlGuessAltText(imageData = null, updateAltTextData = true) {
24736    if (this.hasAltTextData()) {
24737      return null;
24738    }
24739    const {
24740      mlManager
24741    } = this._uiManager;
24742    if (!mlManager) {
24743      throw new Error("No ML.");
24744    }
24745    if (!(await mlManager.isEnabledFor("altText"))) {
24746      throw new Error("ML isn't enabled for alt text.");
24747    }
24748    const {
24749      data,
24750      width,
24751      height
24752    } = imageData || this.copyCanvas(null, null, true).imageData;
24753    const response = await mlManager.guess({
24754      name: "altText",
24755      request: {
24756        data,
24757        width,
24758        height,
24759        channels: data.length / (width * height)
24760      }
24761    });
24762    if (!response) {
24763      throw new Error("No response from the AI service.");
24764    }
24765    if (response.error) {
24766      throw new Error("Error from the AI service.");
24767    }
24768    if (response.cancel) {
24769      return null;
24770    }
24771    if (!response.output) {
24772      throw new Error("No valid response from the AI service.");
24773    }
24774    const altText = response.output;
24775    await this.setGuessedAltText(altText);
24776    if (updateAltTextData && !this.hasAltTextData()) {
24777      this.altTextData = {
24778        alt: altText,
24779        decorative: false
24780      };
24781    }
24782    return altText;
24783  }
24784  #getBitmap() {
24785    if (this.#bitmapId) {
24786      this._uiManager.enableWaiting(true);
24787      this._uiManager.imageManager.getFromId(this.#bitmapId).then(data => this.#getBitmapFetched(data, true)).finally(() => this.#getBitmapDone());
24788      return;
24789    }
24790    if (this.#bitmapUrl) {
24791      const url = this.#bitmapUrl;
24792      this.#bitmapUrl = null;
24793      this._uiManager.enableWaiting(true);
24794      this.#bitmapPromise = this._uiManager.imageManager.getFromUrl(url).then(data => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone());
24795      return;
24796    }
24797    if (this.#bitmapFile) {
24798      const file = this.#bitmapFile;
24799      this.#bitmapFile = null;
24800      this._uiManager.enableWaiting(true);
24801      this.#bitmapPromise = this._uiManager.imageManager.getFromFile(file).then(data => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone());
24802      return;
24803    }
24804    const input = document.createElement("input");
24805    input.type = "file";
24806    input.accept = SupportedImageMimeTypes.join(",");
24807    const signal = this._uiManager._signal;
24808    this.#bitmapPromise = new Promise(resolve => {
24809      input.addEventListener("change", async () => {
24810        if (!input.files || input.files.length === 0) {
24811          this.remove();
24812        } else {
24813          this._uiManager.enableWaiting(true);
24814          const data = await this._uiManager.imageManager.getFromFile(input.files[0]);
24815          this._reportTelemetry({
24816            action: "pdfjs.image.image_selected",
24817            data: {
24818              alt_text_modal: this._uiManager.useNewAltTextFlow
24819            }
24820          });
24821          this.#getBitmapFetched(data);
24822        }
24823        resolve();
24824      }, {
24825        signal
24826      });
24827      input.addEventListener("cancel", () => {
24828        this.remove();
24829        resolve();
24830      }, {
24831        signal
24832      });
24833    }).finally(() => this.#getBitmapDone());
24834    input.click();
24835  }
24836  remove() {
24837    if (this.#bitmapId) {
24838      this.#bitmap = null;
24839      this._uiManager.imageManager.deleteId(this.#bitmapId);
24840      this.#canvas?.remove();
24841      this.#canvas = null;
24842      if (this.#resizeTimeoutId) {
24843        clearTimeout(this.#resizeTimeoutId);
24844        this.#resizeTimeoutId = null;
24845      }
24846    }
24847    super.remove();
24848  }
24849  rebuild() {
24850    if (!this.parent) {
24851      if (this.#bitmapId) {
24852        this.#getBitmap();
24853      }
24854      return;
24855    }
24856    super.rebuild();
24857    if (this.div === null) {
24858      return;
24859    }
24860    if (this.#bitmapId && this.#canvas === null) {
24861      this.#getBitmap();
24862    }
24863    if (!this.isAttachedToDOM) {
24864      this.parent.add(this);
24865    }
24866  }
24867  onceAdded(focus) {
24868    this._isDraggable = true;
24869    if (focus) {
24870      this.div.focus();
24871    }
24872  }
24873  isEmpty() {
24874    return !(this.#bitmapPromise || this.#bitmap || this.#bitmapUrl || this.#bitmapFile || this.#bitmapId || this.#missingCanvas);
24875  }
24876  get toolbarButtons() {
24877    return [["altText", this.createAltText()]];
24878  }
24879  get isResizable() {
24880    return true;
24881  }
24882  render() {
24883    if (this.div) {
24884      return this.div;
24885    }
24886    let baseX, baseY;
24887    if (this._isCopy) {
24888      baseX = this.x;
24889      baseY = this.y;
24890    }
24891    super.render();
24892    this.div.hidden = true;
24893    this.createAltText();
24894    if (!this.#missingCanvas) {
24895      if (this.#bitmap) {
24896        this.#createCanvas();
24897      } else {
24898        this.#getBitmap();
24899      }
24900    }
24901    if (this._isCopy) {
24902      this._moveAfterPaste(baseX, baseY);
24903    }
24904    this._uiManager.addShouldRescale(this);
24905    return this.div;
24906  }
24907  setCanvas(annotationElementId, canvas) {
24908    const {
24909      id: bitmapId,
24910      bitmap
24911    } = this._uiManager.imageManager.getFromCanvas(annotationElementId, canvas);
24912    canvas.remove();
24913    if (bitmapId && this._uiManager.imageManager.isValidId(bitmapId)) {
24914      this.#bitmapId = bitmapId;
24915      if (bitmap) {
24916        this.#bitmap = bitmap;
24917      }
24918      this.#missingCanvas = false;
24919      this.#createCanvas();
24920    }
24921  }
24922  _onResized() {
24923    this.onScaleChanging();
24924  }
24925  onScaleChanging() {
24926    if (!this.parent) {
24927      return;
24928    }
24929    if (this.#resizeTimeoutId !== null) {
24930      clearTimeout(this.#resizeTimeoutId);
24931    }
24932    const TIME_TO_WAIT = 200;
24933    this.#resizeTimeoutId = setTimeout(() => {
24934      this.#resizeTimeoutId = null;
24935      this.#drawBitmap();
24936    }, TIME_TO_WAIT);
24937  }
24938  #createCanvas() {
24939    const {
24940      div
24941    } = this;
24942    let {
24943      width,
24944      height
24945    } = this.#bitmap;
24946    const [pageWidth, pageHeight] = this.pageDimensions;
24947    const MAX_RATIO = 0.75;
24948    if (this.width) {
24949      width = this.width * pageWidth;
24950      height = this.height * pageHeight;
24951    } else if (width > MAX_RATIO * pageWidth || height > MAX_RATIO * pageHeight) {
24952      const factor = Math.min(MAX_RATIO * pageWidth / width, MAX_RATIO * pageHeight / height);
24953      width *= factor;
24954      height *= factor;
24955    }
24956    this._uiManager.enableWaiting(false);
24957    const canvas = this.#canvas = document.createElement("canvas");
24958    canvas.setAttribute("role", "img");
24959    this.addContainer(canvas);
24960    this.width = width / pageWidth;
24961    this.height = height / pageHeight;
24962    this.setDims();
24963    if (this._initialOptions?.isCentered) {
24964      this.center();
24965    } else {
24966      this.fixAndSetPosition();
24967    }
24968    this._initialOptions = null;
24969    if (!this._uiManager.useNewAltTextWhenAddingImage || !this._uiManager.useNewAltTextFlow || this.annotationElementId) {
24970      div.hidden = false;
24971    }
24972    this.#drawBitmap();
24973    if (!this.#hasBeenAddedInUndoStack) {
24974      this.parent.addUndoableEditor(this);
24975      this.#hasBeenAddedInUndoStack = true;
24976    }
24977    this._reportTelemetry({
24978      action: "inserted_image"
24979    });
24980    if (this.#bitmapFileName) {
24981      this.div.setAttribute("aria-description", this.#bitmapFileName);
24982    }
24983    if (!this.annotationElementId) {
24984      this._uiManager.a11yAlert(
vendor: 4,524 bytes, lines 24984-25102
24984"pdfjs-editor-stamp-added-alert");
24985    }
24986  }
24987  copyCanvas(maxDataDimension, maxPreviewDimension, createImageData = false) {
24988    if (!maxDataDimension) {
24989      maxDataDimension = 224;
24990    }
24991    const {
24992      width: bitmapWidth,
24993      height: bitmapHeight
24994    } = this.#bitmap;
24995    const outputScale = new OutputScale();
24996    let bitmap = this.#bitmap;
24997    let width = bitmapWidth,
24998      height = bitmapHeight;
24999    let canvas = null;
25000    if (maxPreviewDimension) {
25001      if (bitmapWidth > maxPreviewDimension || bitmapHeight > maxPreviewDimension) {
25002        const ratio = Math.min(maxPreviewDimension / bitmapWidth, maxPreviewDimension / bitmapHeight);
25003        width = Math.floor(bitmapWidth * ratio);
25004        height = Math.floor(bitmapHeight * ratio);
25005      }
25006      canvas = document.createElement("canvas");
25007      const scaledWidth = canvas.width = Math.ceil(width * outputScale.sx);
25008      const scaledHeight = canvas.height = Math.ceil(height * outputScale.sy);
25009      if (!this.#isSvg) {
25010        bitmap = this.#scaleBitmap(scaledWidth, scaledHeight);
25011      }
25012      const ctx = canvas.getContext("2d");
25013      ctx.filter = this._uiManager.hcmFilter;
25014      let white = "white",
25015        black = "#cfcfd8";
25016      if (this._uiManager.hcmFilter !== "none") {
25017        black = "black";
25018      } else if (ColorScheme.isDarkMode) {
25019        white = "#8f8f9d";
25020        black = "#42414d";
25021      }
25022      const boxDim = 15;
25023      const boxDimWidth = boxDim * outputScale.sx;
25024      const boxDimHeight = boxDim * outputScale.sy;
25025      const pattern = new OffscreenCanvas(boxDimWidth * 2, boxDimHeight * 2);
25026      const patternCtx = pattern.getContext("2d");
25027      patternCtx.fillStyle = white;
25028      patternCtx.fillRect(0, 0, boxDimWidth * 2, boxDimHeight * 2);
25029      patternCtx.fillStyle = black;
25030      patternCtx.fillRect(0, 0, boxDimWidth, boxDimHeight);
25031      patternCtx.fillRect(boxDimWidth, boxDimHeight, boxDimWidth, boxDimHeight);
25032      ctx.fillStyle = ctx.createPattern(pattern, "repeat");
25033      ctx.fillRect(0, 0, scaledWidth, scaledHeight);
25034      ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, scaledWidth, scaledHeight);
25035    }
25036    let imageData = null;
25037    if (createImageData) {
25038      let dataWidth, dataHeight;
25039      if (outputScale.symmetric && bitmap.width < maxDataDimension && bitmap.height < maxDataDimension) {
25040        dataWidth = bitmap.width;
25041        dataHeight = bitmap.height;
25042      } else {
25043        bitmap = this.#bitmap;
25044        if (bitmapWidth > maxDataDimension || bitmapHeight > maxDataDimension) {
25045          const ratio = Math.min(maxDataDimension / bitmapWidth, maxDataDimension / bitmapHeight);
25046          dataWidth = Math.floor(bitmapWidth * ratio);
25047          dataHeight = Math.floor(bitmapHeight * ratio);
25048          if (!this.#isSvg) {
25049            bitmap = this.#scaleBitmap(dataWidth, dataHeight);
25050          }
25051        }
25052      }
25053      const offscreen = new OffscreenCanvas(dataWidth, dataHeight);
25054      const offscreenCtx = offscreen.getContext("2d", {
25055        willReadFrequently: true
25056      });
25057      offscreenCtx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, dataWidth, dataHeight);
25058      imageData = {
25059        width: dataWidth,
25060        height: dataHeight,
25061        data: offscreenCtx.getImageData(0, 0, dataWidth, dataHeight).data
25062      };
25063    }
25064    return {
25065      canvas,
25066      width,
25067      height,
25068      imageData
25069    };
25070  }
25071  #scaleBitmap(width, height) {
25072    const {
25073      width: bitmapWidth,
25074      height: bitmapHeight
25075    } = this.#bitmap;
25076    let newWidth = bitmapWidth;
25077    let newHeight = bitmapHeight;
25078    let bitmap = this.#bitmap;
25079    while (newWidth > 2 * width || newHeight > 2 * height) {
25080      const prevWidth = newWidth;
25081      const prevHeight = newHeight;
25082      if (newWidth > 2 * width) {
25083        newWidth = newWidth >= 16384 ? Math.floor(newWidth / 2) - 1 : Math.ceil(newWidth / 2);
25084      }
25085      if (newHeight > 2 * height) {
25086        newHeight = newHeight >= 16384 ? Math.floor(newHeight / 2) - 1 : Math.ceil(newHeight / 2);
25087      }
25088      const offscreen = new OffscreenCanvas(newWidth, newHeight);
25089      const ctx = offscreen.getContext("2d");
25090      ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight);
25091      bitmap = offscreen.transferToImageBitmap();
25092    }
25093    return bitmap;
25094  }
25095  #drawBitmap() {
25096    const [parentWidth, parentHeight] = this.parentDimensions;
25097    const {
25098      width,
25099      height
25100    } = this;
25101    const outputScale = new OutputScale();
25102    const scaledWidth = Math.ceil(width * parentWidth * outputScale.sx);
vendor: 15,596 bytes, lines 25103-25615
25103    const scaledHeight = Math.ceil(height * parentHeight * outputScale.sy);
25104    const canvas = this.#canvas;
25105    if (!canvas || canvas.width === scaledWidth && canvas.height === scaledHeight) {
25106      return;
25107    }
25108    canvas.width = scaledWidth;
25109    canvas.height = scaledHeight;
25110    const bitmap = this.#isSvg ? this.#bitmap : this.#scaleBitmap(scaledWidth, scaledHeight);
25111    const ctx = canvas.getContext("2d");
25112    ctx.filter = this._uiManager.hcmFilter;
25113    ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, scaledWidth, scaledHeight);
25114  }
25115  #serializeBitmap(toUrl) {
25116    if (toUrl) {
25117      if (this.#isSvg) {
25118        const url = this._uiManager.imageManager.getSvgUrl(this.#bitmapId);
25119        if (url) {
25120          return url;
25121        }
25122      }
25123      const canvas = document.createElement("canvas");
25124      ({
25125        width: canvas.width,
25126        height: canvas.height
25127      } = this.#bitmap);
25128      const ctx = canvas.getContext("2d");
25129      ctx.drawImage(this.#bitmap, 0, 0);
25130      return canvas.toDataURL();
25131    }
25132    if (this.#isSvg) {
25133      const [pageWidth, pageHeight] = this.pageDimensions;
25134      const width = Math.round(this.width * pageWidth * PixelsPerInch.PDF_TO_CSS_UNITS);
25135      const height = Math.round(this.height * pageHeight * PixelsPerInch.PDF_TO_CSS_UNITS);
25136      const offscreen = new OffscreenCanvas(width, height);
25137      const ctx = offscreen.getContext("2d");
25138      ctx.drawImage(this.#bitmap, 0, 0, this.#bitmap.width, this.#bitmap.height, 0, 0, width, height);
25139      return offscreen.transferToImageBitmap();
25140    }
25141    return structuredClone(this.#bitmap);
25142  }
25143  static async deserialize(data, parent, uiManager) {
25144    let initialData = null;
25145    let missingCanvas = false;
25146    if (data instanceof StampAnnotationElement) {
25147      const {
25148        data: {
25149          rect,
25150          rotation,
25151          id,
25152          structParent,
25153          popupRef,
25154          richText,
25155          contentsObj,
25156          creationDate,
25157          modificationDate
25158        },
25159        container,
25160        parent: {
25161          page: {
25162            pageNumber
25163          }
25164        },
25165        canvas
25166      } = data;
25167      let bitmapId, bitmap;
25168      if (canvas) {
25169        delete data.canvas;
25170        ({
25171          id: bitmapId,
25172          bitmap
25173        } = uiManager.imageManager.getFromCanvas(container.id, canvas));
25174        canvas.remove();
25175      } else {
25176        missingCanvas = true;
25177        data._hasNoCanvas = true;
25178      }
25179      const altText = (await parent._structTree.getAriaAttributes(`${AnnotationPrefix}${id}`))?.get("aria-label") || "";
25180      initialData = data = {
25181        annotationType: AnnotationEditorType.STAMP,
25182        bitmapId,
25183        bitmap,
25184        pageIndex: pageNumber - 1,
25185        rect: rect.slice(0),
25186        rotation,
25187        annotationElementId: id,
25188        id,
25189        deleted: false,
25190        accessibilityData: {
25191          decorative: false,
25192          altText
25193        },
25194        isSvg: false,
25195        structParent,
25196        popupRef,
25197        richText,
25198        comment: contentsObj?.str || null,
25199        creationDate,
25200        modificationDate
25201      };
25202    }
25203    const editor = await super.deserialize(data, parent, uiManager);
25204    const {
25205      rect,
25206      bitmap,
25207      bitmapUrl,
25208      bitmapId,
25209      isSvg,
25210      accessibilityData
25211    } = data;
25212    if (missingCanvas) {
25213      uiManager.addMissingCanvas(data.id, editor);
25214      editor.#missingCanvas = true;
25215    } else if (bitmapId && uiManager.imageManager.isValidId(bitmapId)) {
25216      editor.#bitmapId = bitmapId;
25217      if (bitmap) {
25218        editor.#bitmap = bitmap;
25219      }
25220    } else {
25221      editor.#bitmapUrl = bitmapUrl;
25222    }
25223    editor.#isSvg = isSvg;
25224    const [parentWidth, parentHeight] = editor.pageDimensions;
25225    editor.width = (rect[2] - rect[0]) / parentWidth;
25226    editor.height = (rect[3] - rect[1]) / parentHeight;
25227    if (accessibilityData) {
25228      editor.altTextData = accessibilityData;
25229    }
25230    editor._initialData = initialData;
25231    if (data.comment) {
25232      editor.setCommentData(data);
25233    }
25234    editor.#hasBeenAddedInUndoStack = !!initialData;
25235    return editor;
25236  }
25237  serialize(isForCopying = false, context = null) {
25238    if (this.isEmpty()) {
25239      return null;
25240    }
25241    if (this.deleted) {
25242      return this.serializeDeleted();
25243    }
25244    const serialized = Object.assign(super.serialize(isForCopying), {
25245      bitmapId: this.#bitmapId,
25246      isSvg: this.#isSvg
25247    });
25248    this.addComment(serialized);
25249    if (isForCopying) {
25250      serialized.bitmapUrl = this.#serializeBitmap(true);
25251      serialized.accessibilityData = this.serializeAltText(true);
25252      serialized.isCopy = true;
25253      return serialized;
25254    }
25255    const {
25256      decorative,
25257      altText
25258    } = this.serializeAltText(false);
25259    if (!decorative && altText) {
25260      serialized.accessibilityData = {
25261        type: "Figure",
25262        alt: altText
25263      };
25264    }
25265    if (this.annotationElementId) {
25266      const changes = this.#hasElementChanged(serialized);
25267      if (changes.isSame) {
25268        return null;
25269      }
25270      if (changes.isSameAltText) {
25271        delete serialized.accessibilityData;
25272      } else {
25273        serialized.accessibilityData.structParent = this._initialData.structParent ?? -1;
25274      }
25275      serialized.id = this.annotationElementId;
25276      delete serialized.bitmapId;
25277      return serialized;
25278    }
25279    if (context === null) {
25280      return serialized;
25281    }
25282    context.stamps ||= new Map();
25283    const area = this.#isSvg ? (serialized.rect[2] - serialized.rect[0]) * (serialized.rect[3] - serialized.rect[1]) : null;
25284    if (!context.stamps.has(this.#bitmapId)) {
25285      context.stamps.set(this.#bitmapId, {
25286        area,
25287        serialized
25288      });
25289      serialized.bitmap = this.#serializeBitmap(false);
25290    } else if (this.#isSvg) {
25291      const prevData = context.stamps.get(this.#bitmapId);
25292      if (area > prevData.area) {
25293        prevData.area = area;
25294        prevData.serialized.bitmap.close();
25295        prevData.serialized.bitmap = this.#serializeBitmap(false);
25296      }
25297    }
25298    return serialized;
25299  }
25300  #hasElementChanged(serialized) {
25301    const {
25302      pageIndex,
25303      accessibilityData: {
25304        altText
25305      }
25306    } = this._initialData;
25307    const isSamePageIndex = serialized.pageIndex === pageIndex;
25308    const isSameAltText = (serialized.accessibilityData?.alt || "") === altText;
25309    return {
25310      isSame: !this.hasEditedComment && !this._hasBeenMoved && !this._hasBeenResized && isSamePageIndex && isSameAltText,
25311      isSameAltText
25312    };
25313  }
25314  renderAnnotationElement(annotation) {
25315    if (this.deleted) {
25316      annotation.hide();
25317      return null;
25318    }
25319    annotation.updateEdited({
25320      rect: this.getPDFRect(),
25321      popup: this.comment
25322    });
25323    return null;
25324  }
25325}
25326
25327;// ./src/display/editor/annotation_editor_layer.js
25328
25329
25330
25331
25332
25333
25334
25335
25336class AnnotationEditorLayer {
25337  #accessibilityManager;
25338  #allowClick = false;
25339  #annotationLayer = null;
25340  #clickAC = null;
25341  #editorFocusTimeoutId = null;
25342  #editors = new Map();
25343  #hadPointerDown = false;
25344  #isDisabling = false;
25345  #isEnabling = false;
25346  #drawingAC = null;
25347  #focusedElement = null;
25348  #textLayer = null;
25349  #textSelectionAC = null;
25350  #textLayerDblClickAC = null;
25351  #lastPointerDownTimestamp = -1;
25352  #uiManager;
25353  static _initialized = false;
25354  static #editorTypes = new Map([FreeTextEditor, InkEditor, StampEditor, HighlightEditor, SignatureEditor].map(type => [type._editorType, type]));
25355  constructor({
25356    uiManager,
25357    pageIndex,
25358    div,
25359    structTreeLayer,
25360    accessibilityManager,
25361    annotationLayer,
25362    drawLayer,
25363    textLayer,
25364    viewport,
25365    l10n
25366  }) {
25367    const editorTypes = [...AnnotationEditorLayer.#editorTypes.values()];
25368    if (!AnnotationEditorLayer._initialized) {
25369      AnnotationEditorLayer._initialized = true;
25370      for (const editorType of editorTypes) {
25371        editorType.initialize(l10n, uiManager);
25372      }
25373    }
25374    uiManager.registerEditorTypes(editorTypes);
25375    this.#uiManager = uiManager;
25376    this.pageIndex = pageIndex;
25377    this.div = div;
25378    this.#accessibilityManager = accessibilityManager;
25379    this.#annotationLayer = annotationLayer;
25380    this.viewport = viewport;
25381    this.#textLayer = textLayer;
25382    this.drawLayer = drawLayer;
25383    this._structTree = structTreeLayer;
25384    this.#uiManager.addLayer(this);
25385  }
25386  updatePageIndex(newPageIndex) {
25387    this.pageIndex = newPageIndex;
25388  }
25389  get isEmpty() {
25390    return this.#editors.size === 0;
25391  }
25392  get isInvisible() {
25393    return this.isEmpty && this.#uiManager.getMode() === AnnotationEditorType.NONE;
25394  }
25395  updateToolbar(options) {
25396    this.#uiManager.updateToolbar(options);
25397  }
25398  updateMode(mode = this.#uiManager.getMode()) {
25399    this.#cleanup();
25400    switch (mode) {
25401      case AnnotationEditorType.NONE:
25402        this.div.classList.toggle("nonEditing", true);
25403        this.disableTextSelection();
25404        this.togglePointerEvents(false);
25405        this.toggleAnnotationLayerPointerEvents(true);
25406        this.disableClick();
25407        return;
25408      case AnnotationEditorType.INK:
25409        this.disableTextSelection();
25410        this.togglePointerEvents(true);
25411        this.enableClick();
25412        break;
25413      case AnnotationEditorType.HIGHLIGHT:
25414        this.enableTextSelection();
25415        this.togglePointerEvents(false);
25416        this.disableClick();
25417        break;
25418      default:
25419        this.disableTextSelection();
25420        this.togglePointerEvents(true);
25421        this.enableClick();
25422    }
25423    this.toggleAnnotationLayerPointerEvents(false);
25424    const {
25425      classList
25426    } = this.div;
25427    classList.toggle("nonEditing", false);
25428    if (mode === AnnotationEditorType.POPUP) {
25429      classList.toggle("commentEditing", true);
25430    } else {
25431      classList.toggle("commentEditing", false);
25432      for (const editorType of AnnotationEditorLayer.#editorTypes.values()) {
25433        classList.toggle(`${editorType._type}Editing`, mode === editorType._editorType);
25434      }
25435    }
25436    this.div.hidden = false;
25437  }
25438  hasTextLayer(textLayer) {
25439    return textLayer === this.#textLayer?.div;
25440  }
25441  setEditingState(isEditing) {
25442    this.#uiManager.setEditingState(isEditing);
25443  }
25444  addCommands(params) {
25445    this.#uiManager.addCommands(params);
25446  }
25447  cleanUndoStack(type) {
25448    this.#uiManager.cleanUndoStack(type);
25449  }
25450  toggleDrawing(enabled = false) {
25451    this.div.classList.toggle("drawing", !enabled);
25452  }
25453  togglePointerEvents(enabled = false) {
25454    this.div.classList.toggle("disabled", !enabled);
25455  }
25456  toggleAnnotationLayerPointerEvents(enabled = false) {
25457    this.#annotationLayer?.togglePointerEvents(enabled);
25458  }
25459  get #allEditorsIterator() {
25460    return this.#editors.size !== 0 ? this.#editors.values() : this.#uiManager.getEditors(this.pageIndex);
25461  }
25462  async enable() {
25463    this.#isEnabling = true;
25464    this.div.tabIndex = 0;
25465    this.togglePointerEvents(true);
25466    this.div.classList.toggle("nonEditing", false);
25467    this.#textLayerDblClickAC?.abort();
25468    this.#textLayerDblClickAC = null;
25469    const annotationElementIds = new Set();
25470    for (const editor of this.#allEditorsIterator) {
25471      editor.enableEditing();
25472      editor.show(true);
25473      if (editor.annotationElementId) {
25474        this.#uiManager.removeChangedExistingAnnotation(editor);
25475        annotationElementIds.add(editor.annotationElementId);
25476      }
25477    }
25478    const annotationLayer = this.#annotationLayer;
25479    if (annotationLayer) {
25480      for (const editable of annotationLayer.getEditableAnnotations()) {
25481        editable.hide();
25482        if (this.#uiManager.isDeletedAnnotationElement(editable.data.id)) {
25483          continue;
25484        }
25485        if (annotationElementIds.has(editable.data.id)) {
25486          continue;
25487        }
25488        const editor = await this.deserialize(editable);
25489        if (!editor) {
25490          continue;
25491        }
25492        this.addOrRebuild(editor);
25493        editor.enableEditing();
25494      }
25495    }
25496    this.#isEnabling = false;
25497    this.#uiManager._eventBus.dispatch("editorsrendered", {
25498      source: this,
25499      pageNumber: this.pageIndex + 1
25500    });
25501  }
25502  disable() {
25503    this.#isDisabling = true;
25504    this.div.tabIndex = -1;
25505    this.togglePointerEvents(false);
25506    this.div.classList.toggle("nonEditing", true);
25507    if (this.#textLayer && !this.#textLayerDblClickAC) {
25508      this.#textLayerDblClickAC = new AbortController();
25509      const signal = this.#uiManager.combinedSignal(this.#textLayerDblClickAC);
25510      this.#textLayer.div.addEventListener("pointerdown", e => {
25511        const DBL_CLICK_THRESHOLD = 500;
25512        const {
25513          clientX,
25514          clientY,
25515          timeStamp
25516        } = e;
25517        const lastPointerDownTimestamp = this.#lastPointerDownTimestamp;
25518        if (timeStamp - lastPointerDownTimestamp > DBL_CLICK_THRESHOLD) {
25519          this.#lastPointerDownTimestamp = timeStamp;
25520          return;
25521        }
25522        this.#lastPointerDownTimestamp = -1;
25523        const {
25524          classList
25525        } = this.div;
25526        classList.toggle("getElements", true);
25527        const elements = document.elementsFromPoint(clientX, clientY);
25528        classList.toggle("getElements", false);
25529        if (!this.div.contains(elements[0])) {
25530          return;
25531        }
25532        let id;
25533        const regex = new RegExp(`^${AnnotationEditorPrefix}[0-9]+$`);
25534        for (const element of elements) {
25535          if (regex.test(element.id)) {
25536            id = element.id;
25537            break;
25538          }
25539        }
25540        if (!id) {
25541          return;
25542        }
25543        const editor = this.#editors.get(id);
25544        if (editor?.annotationElementId === null) {
25545          e.stopPropagation();
25546          e.preventDefault();
25547          editor.dblclick(e);
25548        }
25549      }, {
25550        signal,
25551        capture: true
25552      });
25553    }
25554    const annotationLayer = this.#annotationLayer;
25555    const needFakeAnnotation = [];
25556    if (annotationLayer) {
25557      const changedAnnotations = new Map();
25558      const resetAnnotations = new Map();
25559      for (const editor of this.#allEditorsIterator) {
25560        editor.disableEditing();
25561        if (!editor.annotationElementId) {
25562          needFakeAnnotation.push(editor);
25563          continue;
25564        }
25565        if (editor.serialize() !== null) {
25566          changedAnnotations.set(editor.annotationElementId, editor);
25567          continue;
25568        } else {
25569          resetAnnotations.set(editor.annotationElementId, editor);
25570        }
25571        this.getEditableAnnotation(editor.annotationElementId)?.show();
25572        editor.remove();
25573      }
25574      const editables = annotationLayer.getEditableAnnotations();
25575      for (const editable of editables) {
25576        const {
25577          id
25578        } = editable.data;
25579        if (this.#uiManager.isDeletedAnnotationElement(id)) {
25580          editable.updateEdited({
25581            deleted: true
25582          });
25583          continue;
25584        }
25585        let editor = resetAnnotations.get(id);
25586        if (editor) {
25587          editor.resetAnnotationElement(editable);
25588          editor.show(false);
25589          editable.show();
25590          continue;
25591        }
25592        editor = changedAnnotations.get(id);
25593        if (editor) {
25594          this.#uiManager.addChangedExistingAnnotation(editor);
25595          if (editor.renderAnnotationElement(editable)) {
25596            editor.show(false);
25597          }
25598        }
25599        editable.show();
25600      }
25601    }
25602    this.#cleanup();
25603    if (this.isEmpty) {
25604      this.div.hidden = true;
25605    }
25606    const {
25607      classList
25608    } = this.div;
25609    for (const editorType of AnnotationEditorLayer.#editorTypes.values()) {
25610      classList.remove(`${editorType._type}Editing`);
25611    }
25612    this.disableTextSelection();
25613    this.toggleAnnotationLayerPointerEvents(true);
25614    annotationLayer?.updateFakeAnnotations(needFakeAnnotation);
25615    this.#isDisabling = false;
vendor: 17,553 bytes, lines 25616-26231
25616  }
25617  getEditableAnnotation(id) {
25618    return this.#annotationLayer?.getEditableAnnotation(id) || null;
25619  }
25620  setActiveEditor(editor) {
25621    const currentActive = this.#uiManager.getActive();
25622    if (currentActive === editor) {
25623      return;
25624    }
25625    this.#uiManager.setActiveEditor(editor);
25626  }
25627  enableTextSelection() {
25628    this.div.tabIndex = -1;
25629    if (this.#textLayer?.div && !this.#textSelectionAC) {
25630      this.#textSelectionAC = new AbortController();
25631      const signal = this.#uiManager.combinedSignal(this.#textSelectionAC);
25632      this.#textLayer.div.addEventListener("pointerdown", this.#textLayerPointerDown.bind(this), {
25633        signal
25634      });
25635      this.#textLayer.div.classList.add("highlighting");
25636    }
25637  }
25638  disableTextSelection() {
25639    this.div.tabIndex = 0;
25640    if (this.#textLayer?.div && this.#textSelectionAC) {
25641      this.#textSelectionAC.abort();
25642      this.#textSelectionAC = null;
25643      this.#textLayer.div.classList.remove("highlighting");
25644    }
25645  }
25646  #textLayerPointerDown(event) {
25647    this.#uiManager.unselectAll();
25648    const {
25649      target
25650    } = event;
25651    if (target === this.#textLayer.div || (target.getAttribute("role") === "img" || target.classList.contains("endOfContent")) && this.#textLayer.div.contains(target)) {
25652      const {
25653        isMac
25654      } = util_FeatureTest.platform;
25655      if (event.button !== 0 || event.ctrlKey && isMac) {
25656        return;
25657      }
25658      this.#uiManager.showAllEditors("highlight", true, true);
25659      this.#textLayer.div.classList.add("free");
25660      this.toggleDrawing();
25661      HighlightEditor.startHighlighting(this, this.#uiManager.direction === "ltr", {
25662        target: this.#textLayer.div,
25663        x: event.x,
25664        y: event.y
25665      });
25666      this.#textLayer.div.addEventListener("pointerup", () => {
25667        this.#textLayer.div.classList.remove("free");
25668        this.toggleDrawing(true);
25669      }, {
25670        once: true,
25671        signal: this.#uiManager._signal
25672      });
25673      event.preventDefault();
25674    }
25675  }
25676  enableClick() {
25677    if (this.#clickAC) {
25678      return;
25679    }
25680    this.#clickAC = new AbortController();
25681    const signal = this.#uiManager.combinedSignal(this.#clickAC);
25682    this.div.addEventListener("pointerdown", this.pointerdown.bind(this), {
25683      signal
25684    });
25685    const pointerup = this.pointerup.bind(this);
25686    this.div.addEventListener("pointerup", pointerup, {
25687      signal
25688    });
25689    this.div.addEventListener("pointercancel", pointerup, {
25690      signal
25691    });
25692  }
25693  disableClick() {
25694    this.#clickAC?.abort();
25695    this.#clickAC = null;
25696  }
25697  attach(editor) {
25698    this.#editors.set(editor.id, editor);
25699    const {
25700      annotationElementId
25701    } = editor;
25702    if (annotationElementId && this.#uiManager.isDeletedAnnotationElement(annotationElementId)) {
25703      this.#uiManager.removeDeletedAnnotationElement(editor);
25704    }
25705  }
25706  detach(editor) {
25707    this.#editors.delete(editor.id);
25708    this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv);
25709    if (!this.#isDisabling && editor.annotationElementId) {
25710      this.#uiManager.addDeletedAnnotationElement(editor);
25711    }
25712  }
25713  remove(editor) {
25714    this.detach(editor);
25715    this.#uiManager.removeEditor(editor);
25716    editor.div.remove();
25717    editor.isAttachedToDOM = false;
25718  }
25719  changeParent(editor) {
25720    if (editor.parent === this) {
25721      return;
25722    }
25723    if (editor.parent && editor.annotationElementId) {
25724      this.#uiManager.addDeletedAnnotationElement(editor);
25725      AnnotationEditor.deleteAnnotationElement(editor);
25726      editor.annotationElementId = null;
25727    }
25728    this.attach(editor);
25729    editor.parent?.detach(editor);
25730    editor.setParent(this);
25731    if (editor.div && editor.isAttachedToDOM) {
25732      editor.div.remove();
25733      this.div.append(editor.div);
25734    }
25735  }
25736  add(editor) {
25737    if (editor.parent === this && editor.isAttachedToDOM) {
25738      return;
25739    }
25740    this.changeParent(editor);
25741    this.#uiManager.addEditor(editor);
25742    this.attach(editor);
25743    if (!editor.isAttachedToDOM) {
25744      const div = editor.render();
25745      this.div.append(div);
25746      editor.isAttachedToDOM = true;
25747    }
25748    editor.fixAndSetPosition();
25749    editor.onceAdded(!this.#isEnabling);
25750    this.#uiManager.addToAnnotationStorage(editor);
25751    editor._reportTelemetry(editor.telemetryInitialData);
25752  }
25753  moveEditorInDOM(editor) {
25754    if (!editor.isAttachedToDOM) {
25755      return;
25756    }
25757    const {
25758      activeElement
25759    } = document;
25760    if (editor.div.contains(activeElement) && !this.#editorFocusTimeoutId) {
25761      editor._focusEventsAllowed = false;
25762      this.#editorFocusTimeoutId = setTimeout(() => {
25763        this.#editorFocusTimeoutId = null;
25764        if (!editor.div.contains(document.activeElement)) {
25765          editor.div.addEventListener("focusin", () => {
25766            editor._focusEventsAllowed = true;
25767          }, {
25768            once: true,
25769            signal: this.#uiManager._signal
25770          });
25771          activeElement.focus();
25772        } else {
25773          editor._focusEventsAllowed = true;
25774        }
25775      }, 0);
25776    }
25777    editor._structTreeParentId = this.#accessibilityManager?.moveElementInDOM(this.div, editor.div, editor.contentDiv, true);
25778  }
25779  addOrRebuild(editor) {
25780    if (editor.needsToBeRebuilt()) {
25781      editor.parent ||= this;
25782      editor.rebuild();
25783      editor.show();
25784    } else {
25785      this.add(editor);
25786    }
25787  }
25788  addUndoableEditor(editor) {
25789    const cmd = () => editor._uiManager.rebuild(editor);
25790    const undo = () => {
25791      editor.remove();
25792    };
25793    this.addCommands({
25794      cmd,
25795      undo,
25796      mustExec: false
25797    });
25798  }
25799  getEditorByUID(uid) {
25800    for (const editor of this.#editors.values()) {
25801      if (editor.uid === uid) {
25802        return editor;
25803      }
25804    }
25805    return null;
25806  }
25807  getNextId() {
25808    return this.#uiManager.getId();
25809  }
25810  get #currentEditorType() {
25811    return AnnotationEditorLayer.#editorTypes.get(this.#uiManager.getMode());
25812  }
25813  combinedSignal(ac) {
25814    return this.#uiManager.combinedSignal(ac);
25815  }
25816  #createNewEditor(params) {
25817    const editorType = this.#currentEditorType;
25818    return editorType ? new editorType.prototype.constructor(params) : null;
25819  }
25820  canCreateNewEmptyEditor() {
25821    return this.#currentEditorType?.canCreateNewEmptyEditor();
25822  }
25823  async pasteEditor(options, params) {
25824    this.updateToolbar(options);
25825    await this.#uiManager.updateMode(options.mode);
25826    const {
25827      offsetX,
25828      offsetY
25829    } = this.#getCenterPoint();
25830    const id = this.getNextId();
25831    const editor = this.#createNewEditor({
25832      parent: this,
25833      id,
25834      x: offsetX,
25835      y: offsetY,
25836      uiManager: this.#uiManager,
25837      isCentered: true,
25838      ...params
25839    });
25840    if (editor) {
25841      this.add(editor);
25842    }
25843  }
25844  async deserialize(data) {
25845    return (await AnnotationEditorLayer.#editorTypes.get(data.annotationType ?? data.annotationEditorType)?.deserialize(data, this, this.#uiManager)) || null;
25846  }
25847  createAndAddNewEditor(event, isCentered, data = {}) {
25848    const id = this.getNextId();
25849    const editor = this.#createNewEditor({
25850      parent: this,
25851      id,
25852      x: event.offsetX,
25853      y: event.offsetY,
25854      uiManager: this.#uiManager,
25855      isCentered,
25856      ...data
25857    });
25858    if (editor) {
25859      this.add(editor);
25860    }
25861    return editor;
25862  }
25863  get boundingClientRect() {
25864    return this.div.getBoundingClientRect();
25865  }
25866  #getCenterPoint() {
25867    const {
25868      x,
25869      y,
25870      width,
25871      height
25872    } = this.boundingClientRect;
25873    const tlX = Math.max(0, x);
25874    const tlY = Math.max(0, y);
25875    const brX = Math.min(window.innerWidth, x + width);
25876    const brY = Math.min(window.innerHeight, y + height);
25877    const centerX = (tlX + brX) / 2 - x;
25878    const centerY = (tlY + brY) / 2 - y;
25879    const [offsetX, offsetY] = this.viewport.rotation % 180 === 0 ? [centerX, centerY] : [centerY, centerX];
25880    return {
25881      offsetX,
25882      offsetY
25883    };
25884  }
25885  addNewEditor(data = {}) {
25886    this.createAndAddNewEditor(this.#getCenterPoint(), true, data);
25887  }
25888  setSelected(editor) {
25889    this.#uiManager.setSelected(editor);
25890  }
25891  toggleSelected(editor) {
25892    this.#uiManager.toggleSelected(editor);
25893  }
25894  unselect(editor) {
25895    this.#uiManager.unselect(editor);
25896  }
25897  pointerup(event) {
25898    const {
25899      isMac
25900    } = util_FeatureTest.platform;
25901    if (event.button !== 0 || event.ctrlKey && isMac) {
25902      return;
25903    }
25904    if (event.target !== this.div) {
25905      return;
25906    }
25907    if (!this.#hadPointerDown) {
25908      return;
25909    }
25910    this.#hadPointerDown = false;
25911    if (this.#currentEditorType?.isDrawer && this.#currentEditorType.supportMultipleDrawings) {
25912      return;
25913    }
25914    if (!this.#allowClick) {
25915      this.#allowClick = true;
25916      return;
25917    }
25918    const currentMode = this.#uiManager.getMode();
25919    if (currentMode === AnnotationEditorType.STAMP || currentMode === AnnotationEditorType.SIGNATURE) {
25920      this.#uiManager.unselectAll();
25921      return;
25922    }
25923    this.createAndAddNewEditor(event, false);
25924  }
25925  pointerdown(event) {
25926    if (this.#uiManager.getMode() === AnnotationEditorType.HIGHLIGHT) {
25927      this.enableTextSelection();
25928    }
25929    if (this.#hadPointerDown) {
25930      this.#hadPointerDown = false;
25931      return;
25932    }
25933    const {
25934      isMac
25935    } = util_FeatureTest.platform;
25936    if (event.button !== 0 || event.ctrlKey && isMac) {
25937      return;
25938    }
25939    if (event.target !== this.div) {
25940      return;
25941    }
25942    this.#hadPointerDown = true;
25943    if (this.#currentEditorType?.isDrawer) {
25944      this.startDrawingSession(event);
25945      return;
25946    }
25947    const editor = this.#uiManager.getActive();
25948    this.#allowClick = !editor || editor.isEmpty();
25949  }
25950  startDrawingSession(event) {
25951    this.div.focus({
25952      preventScroll: true
25953    });
25954    if (this.#drawingAC) {
25955      this.#currentEditorType.startDrawing(this, this.#uiManager, false, event);
25956      return;
25957    }
25958    this.#uiManager.setCurrentDrawingSession(this);
25959    this.#drawingAC = new AbortController();
25960    const signal = this.#uiManager.combinedSignal(this.#drawingAC);
25961    this.div.addEventListener("blur", ({
25962      relatedTarget
25963    }) => {
25964      if (relatedTarget && !this.div.contains(relatedTarget)) {
25965        this.#focusedElement = null;
25966        this.commitOrRemove();
25967      }
25968    }, {
25969      signal
25970    });
25971    this.#currentEditorType.startDrawing(this, this.#uiManager, false, event);
25972  }
25973  pause(on) {
25974    if (on) {
25975      const {
25976        activeElement
25977      } = document;
25978      if (this.div.contains(activeElement)) {
25979        this.#focusedElement = activeElement;
25980      }
25981      return;
25982    }
25983    if (this.#focusedElement) {
25984      setTimeout(() => {
25985        this.#focusedElement?.focus();
25986        this.#focusedElement = null;
25987      }, 0);
25988    }
25989  }
25990  endDrawingSession(isAborted = false) {
25991    if (!this.#drawingAC) {
25992      return null;
25993    }
25994    this.#uiManager.setCurrentDrawingSession(null);
25995    this.#drawingAC.abort();
25996    this.#drawingAC = null;
25997    this.#focusedElement = null;
25998    return this.#currentEditorType.endDrawing(isAborted);
25999  }
26000  findNewParent(editor, x, y) {
26001    const layer = this.#uiManager.findParent(x, y);
26002    if (layer === null || layer === this) {
26003      return false;
26004    }
26005    layer.changeParent(editor);
26006    return true;
26007  }
26008  commitOrRemove() {
26009    if (this.#drawingAC) {
26010      this.endDrawingSession();
26011      return true;
26012    }
26013    return false;
26014  }
26015  onScaleChanging() {
26016    if (!this.#drawingAC) {
26017      return;
26018    }
26019    this.#currentEditorType.onScaleChangingWhenDrawing(this);
26020  }
26021  destroy() {
26022    this.commitOrRemove();
26023    if (this.#uiManager.getActive()?.parent === this) {
26024      this.#uiManager.commitOrRemove();
26025      this.#uiManager.setActiveEditor(null);
26026    }
26027    if (this.#editorFocusTimeoutId) {
26028      clearTimeout(this.#editorFocusTimeoutId);
26029      this.#editorFocusTimeoutId = null;
26030    }
26031    for (const editor of this.#editors.values()) {
26032      this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv);
26033      editor.setParent(null);
26034      editor.isAttachedToDOM = false;
26035      editor.div.remove();
26036    }
26037    this.div = null;
26038    this.#editors.clear();
26039    this.#uiManager.removeLayer(this);
26040  }
26041  #cleanup() {
26042    for (const editor of this.#editors.values()) {
26043      if (editor.isEmpty()) {
26044        editor.remove();
26045      }
26046    }
26047  }
26048  render({
26049    viewport
26050  }) {
26051    this.viewport = viewport;
26052    setLayerDimensions(this.div, viewport);
26053    for (const editor of this.#uiManager.getEditors(this.pageIndex)) {
26054      this.add(editor);
26055      editor.rebuild();
26056    }
26057    this.updateMode();
26058  }
26059  update({
26060    viewport
26061  }) {
26062    this.#uiManager.commitOrRemove();
26063    this.#cleanup();
26064    const oldRotation = this.viewport.rotation;
26065    const rotation = viewport.rotation;
26066    this.viewport = viewport;
26067    setLayerDimensions(this.div, {
26068      rotation
26069    });
26070    if (oldRotation !== rotation) {
26071      for (const editor of this.#editors.values()) {
26072        editor.rotate(rotation);
26073      }
26074    }
26075  }
26076  get pageDimensions() {
26077    const {
26078      pageWidth,
26079      pageHeight
26080    } = this.viewport.rawDims;
26081    return [pageWidth, pageHeight];
26082  }
26083  get scale() {
26084    return this.#uiManager.viewParameters.realScale;
26085  }
26086}
26087
26088;// ./src/display/draw_layer.js
26089
26090
26091class DrawLayer {
26092  #parent = null;
26093  #mapping = new Map();
26094  #toUpdate = new Map();
26095  static #id = 0;
26096  setParent(parent) {
26097    if (!this.#parent) {
26098      this.#parent = parent;
26099      return;
26100    }
26101    if (this.#parent !== parent) {
26102      if (this.#mapping.size > 0) {
26103        for (const root of this.#mapping.values()) {
26104          root.remove();
26105          parent.append(root);
26106        }
26107      }
26108      this.#parent = parent;
26109    }
26110  }
26111  static get _svgFactory() {
26112    return shadow(this, "_svgFactory", new DOMSVGFactory());
26113  }
26114  static #setBox(element, [x, y, width, height]) {
26115    const {
26116      style
26117    } = element;
26118    style.top = `${100 * y}%`;
26119    style.left = `${100 * x}%`;
26120    style.width = `${100 * width}%`;
26121    style.height = `${100 * height}%`;
26122  }
26123  #createSVG() {
26124    const svg = DrawLayer._svgFactory.create(1, 1, true);
26125    this.#parent.append(svg);
26126    svg.setAttribute("aria-hidden", true);
26127    return svg;
26128  }
26129  #createClipPath(defs, pathId) {
26130    const clipPath = DrawLayer._svgFactory.createElement("clipPath");
26131    defs.append(clipPath);
26132    const clipPathId = `clip_${pathId}`;
26133    clipPath.setAttribute("id", clipPathId);
26134    clipPath.setAttribute("clipPathUnits", "objectBoundingBox");
26135    const clipPathUse = DrawLayer._svgFactory.createElement("use");
26136    clipPath.append(clipPathUse);
26137    clipPathUse.setAttribute("href", `#${pathId}`);
26138    clipPathUse.classList.add("clip");
26139    return clipPathId;
26140  }
26141  #updateProperties(element, properties) {
26142    for (const [key, value] of Object.entries(properties)) {
26143      if (value === null) {
26144        element.removeAttribute(key);
26145      } else {
26146        element.setAttribute(key, value);
26147      }
26148    }
26149  }
26150  draw(properties, isPathUpdatable = false, hasClip = false) {
26151    const id = DrawLayer.#id++;
26152    const root = this.#createSVG();
26153    const defs = DrawLayer._svgFactory.createElement("defs");
26154    root.append(defs);
26155    const path = DrawLayer._svgFactory.createElement("path");
26156    defs.append(path);
26157    const pathId = `path_${id}`;
26158    path.setAttribute("id", pathId);
26159    path.setAttribute("vector-effect", "non-scaling-stroke");
26160    if (isPathUpdatable) {
26161      this.#toUpdate.set(id, path);
26162    }
26163    const clipPathId = hasClip ? this.#createClipPath(defs, pathId) : null;
26164    const use = DrawLayer._svgFactory.createElement("use");
26165    root.append(use);
26166    use.setAttribute("href", `#${pathId}`);
26167    this.updateProperties(root, properties);
26168    this.#mapping.set(id, root);
26169    return {
26170      id,
26171      clipPathId: `url(#${clipPathId})`
26172    };
26173  }
26174  drawOutline(properties, mustRemoveSelfIntersections) {
26175    const id = DrawLayer.#id++;
26176    const root = this.#createSVG();
26177    const defs = DrawLayer._svgFactory.createElement("defs");
26178    root.append(defs);
26179    const path = DrawLayer._svgFactory.createElement("path");
26180    defs.append(path);
26181    const pathId = `path_${id}`;
26182    path.setAttribute("id", pathId);
26183    path.setAttribute("vector-effect", "non-scaling-stroke");
26184    let maskId;
26185    if (mustRemoveSelfIntersections) {
26186      const mask = DrawLayer._svgFactory.createElement("mask");
26187      defs.append(mask);
26188      maskId = `mask_${id}`;
26189      mask.setAttribute("id", maskId);
26190      mask.setAttribute("maskUnits", "objectBoundingBox");
26191      const rect = DrawLayer._svgFactory.createElement("rect");
26192      mask.append(rect);
26193      rect.setAttribute("width", "1");
26194      rect.setAttribute("height", "1");
26195      rect.setAttribute("fill", "white");
26196      const use = DrawLayer._svgFactory.createElement("use");
26197      mask.append(use);
26198      use.setAttribute("href", `#${pathId}`);
26199      use.setAttribute("stroke", "none");
26200      use.setAttribute("fill", "black");
26201      use.setAttribute("fill-rule", "nonzero");
26202      use.classList.add("mask");
26203    }
26204    const use1 = DrawLayer._svgFactory.createElement("use");
26205    root.append(use1);
26206    use1.setAttribute("href", `#${pathId}`);
26207    if (maskId) {
26208      use1.setAttribute("mask", `url(#${maskId})`);
26209    }
26210    const use2 = use1.cloneNode();
26211    root.append(use2);
26212    use1.classList.add("mainOutline");
26213    use2.classList.add("secondaryOutline");
26214    this.updateProperties(root, properties);
26215    this.#mapping.set(id, root);
26216    return id;
26217  }
26218  finalizeDraw(id, properties) {
26219    this.#toUpdate.delete(id);
26220    this.updateProperties(id, properties);
26221  }
26222  updateProperties(elementOrId, properties) {
26223    if (!properties) {
26224      return;
26225    }
26226    const {
26227      root,
26228      bbox,
26229      rootClass,
26230      path
26231    } = properties;
vendor: 4,258 bytes, lines 26232-26369
26232    const element = typeof elementOrId === "number" ? this.#mapping.get(elementOrId) : elementOrId;
26233    if (!element) {
26234      return;
26235    }
26236    if (root) {
26237      this.#updateProperties(element, root);
26238    }
26239    if (bbox) {
26240      DrawLayer.#setBox(element, bbox);
26241    }
26242    if (rootClass) {
26243      const {
26244        classList
26245      } = element;
26246      for (const [className, value] of Object.entries(rootClass)) {
26247        classList.toggle(className, value);
26248      }
26249    }
26250    if (path) {
26251      const defs = element.firstElementChild;
26252      const pathElement = defs.firstElementChild;
26253      this.#updateProperties(pathElement, path);
26254    }
26255  }
26256  updateParent(id, layer) {
26257    if (layer === this) {
26258      return;
26259    }
26260    const root = this.#mapping.get(id);
26261    if (!root) {
26262      return;
26263    }
26264    layer.#parent.append(root);
26265    this.#mapping.delete(id);
26266    layer.#mapping.set(id, root);
26267  }
26268  remove(id) {
26269    this.#toUpdate.delete(id);
26270    if (this.#parent === null) {
26271      return;
26272    }
26273    this.#mapping.get(id).remove();
26274    this.#mapping.delete(id);
26275  }
26276  destroy() {
26277    this.#parent = null;
26278    for (const root of this.#mapping.values()) {
26279      root.remove();
26280    }
26281    this.#mapping.clear();
26282    this.#toUpdate.clear();
26283  }
26284}
26285
26286;// ./src/pdf.js
26287
26288
26289
26290
26291
26292
26293
26294
26295
26296
26297
26298
26299
26300
26301
26302
26303{
26304  globalThis._pdfjsTestingUtils = {
26305    HighlightOutliner: HighlightOutliner
26306  };
26307}
26308globalThis.pdfjsLib = {
26309  AbortException: AbortException,
26310  AnnotationEditorLayer: AnnotationEditorLayer,
26311  AnnotationEditorParamsType: AnnotationEditorParamsType,
26312  AnnotationEditorType: AnnotationEditorType,
26313  AnnotationEditorUIManager: AnnotationEditorUIManager,
26314  AnnotationLayer: AnnotationLayer,
26315  AnnotationMode: AnnotationMode,
26316  AnnotationType: AnnotationType,
26317  applyOpacity: applyOpacity,
26318  build: build,
26319  ColorPicker: ColorPicker,
26320  createValidAbsoluteUrl: createValidAbsoluteUrl,
26321  CSSConstants: CSSConstants,
26322  DOMSVGFactory: DOMSVGFactory,
26323  DrawLayer: DrawLayer,
26324  FeatureTest: util_FeatureTest,
26325  fetchData: fetchData,
26326  findContrastColor: findContrastColor,
26327  getDocument: getDocument,
26328  getFilenameFromUrl: getFilenameFromUrl,
26329  getPdfFilenameFromUrl: getPdfFilenameFromUrl,
26330  getRGB: getRGB,
26331  getUuid: getUuid,
26332  getXfaPageViewport: getXfaPageViewport,
26333  GlobalWorkerOptions: GlobalWorkerOptions,
26334  ImageKind: util_ImageKind,
26335  InvalidPDFException: InvalidPDFException,
26336  isDataScheme: isDataScheme,
26337  isPdfFile: isPdfFile,
26338  isValidExplicitDest: isValidExplicitDest,
26339  MathClamp: MathClamp,
26340  noContextMenu: noContextMenu,
26341  normalizeUnicode: normalizeUnicode,
26342  OPS: OPS,
26343  OutputScale: OutputScale,
26344  PagesMapper: PagesMapper,
26345  PasswordResponses: PasswordResponses,
26346  PDFDataRangeTransport: PDFDataRangeTransport,
26347  PDFDateString: PDFDateString,
26348  PDFWorker: PDFWorker,
26349  PermissionFlag: PermissionFlag,
26350  PixelsPerInch: PixelsPerInch,
26351  RenderingCancelledException: RenderingCancelledException,
26352  renderRichText: renderRichText,
26353  ResponseException: ResponseException,
26354  setLayerDimensions: setLayerDimensions,
26355  shadow: shadow,
26356  SignatureExtractor: SignatureExtractor,
26357  stopEvent: stopEvent,
26358  SupportedImageMimeTypes: SupportedImageMimeTypes,
26359  TextLayer: TextLayer,
26360  TouchManager: TouchManager,
26361  updateUrlHash: updateUrlHash,
26362  Util: Util,
26363  VerbosityLevel: VerbosityLevel,
26364  version: version,
26365  XfaLayer: XfaLayer
26366};
26367
26368export { AbortException, AnnotationEditorLayer, AnnotationEditorParamsType, AnnotationEditorType, AnnotationEditorUIManager, AnnotationLayer, AnnotationMode, AnnotationType, CSSConstants, ColorPicker, DOMSVGFactory, DrawLayer, util_FeatureTest as FeatureTest, GlobalWorkerOptions, util_ImageKind as ImageKind, InvalidPDFException, MathClamp, OPS, OutputScale, PDFDataRangeTransport, PDFDateString, PDFWorker, PagesMapper, PasswordResponses, PermissionFlag, PixelsPerInch, RenderingCancelledException, ResponseException, SignatureExtractor, SupportedImageMimeTypes, TextLayer, TouchManager, Util, VerbosityLevel, XfaLayer, applyOpacity, build, createValidAbsoluteUrl, fetchData, findContrastColor, getDocument, getFilenameFromUrl, getPdfFilenameFromUrl, getRGB, getUuid, getXfaPageViewport, isDataScheme, isPdfFile, isValidExplicitDest, noContextMenu, normalizeUnicode, renderRichText, setLayerDimensions, shadow, stopEvent, updateUrlHash, version };
26369
26370//# sourceMappingURL=pdf.mjs.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.