: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
window.addEventListener("pointerup", pointerUpCallback);
window.addEventListener("blur", pointerUpCallback);
if (this.#moveInDOMTimeout) {
clearTimeout(this.#moveInDOMTimeout);
this.#moveInDOMTimeout = setTimeout(() => {
this.#moveInDOMTimeout = null;
this.parent?.moveEditorInDOM(this);
_setParentAndPosition(parent, x, y) {
parent.changeParent(this);
this.fixAndSetPosition();
getRect(tx, ty, rotation = this.rotation) {
const scale = this.parentScale;
const [pageWidth, pageHeight] = this.pageDimensions;
const [pageX, pageY] = this.pageTranslation;
const shiftX = tx / scale;
const shiftY = ty / scale;
const x = this.x * pageWidth;
const y = this.y * pageHeight;
const width = this.width * pageWidth;
const height = this.height * pageHeight;
return [x + shiftX + pageX, pageHeight - y - shiftY - height + pageY, x + shiftX + width + pageX, pageHeight - y - shiftY + pageY];
return [x + shiftY + pageX, pageHeight - y + shiftX + pageY, x + shiftY + height + pageX, pageHeight - y + shiftX + width + pageY];
return [x - shiftX - width + pageX, pageHeight - y + shiftY + pageY, x - shiftX + pageX, pageHeight - y + shiftY + height + pageY];
return [x - shiftY - height + pageX, pageHeight - y - shiftX - width + pageY, x - shiftY + pageX, pageHeight - y - shiftX + pageY];
throw new Error("Invalid rotation");
getRectInCurrentCoords(rect, pageHeight) {
const [x1, y1, x2, y2] = rect;
return [x1, pageHeight - y2, width, height];
return [x1, pageHeight - y1, height, width];
return [x2, pageHeight - y1, width, height];
return [x2, pageHeight - y2, height, width];
throw new Error("Invalid rotation");
this.#isInEditMode = true;
this.#isInEditMode = false;
return this.#isInEditMode;
shouldGetKeyboardEvents() {
return this.#isResizerEnabledForKeyboard;
return this.div && !this.isAttachedToDOM;
this.div?.addEventListener("focusin", this.#boundFocusin);
this.div?.addEventListener("focusout", this.#boundFocusout);
serialize(isForCopying = false, context = null) {
unreachable("An editor must be serializable");
static deserialize(data, parent, uiManager) {
const editor = new this.prototype.constructor({
editor.rotation = data.rotation;
const [pageWidth, pageHeight] = editor.pageDimensions;
const [x, y, width, height] = editor.getRectInCurrentCoords(data.rect, pageHeight);
editor.x = x / pageWidth;
editor.y = y / pageHeight;
editor.width = width / pageWidth;
editor.height = height / pageHeight;
return !!this.annotationElementId && (this.deleted || this.serialize() !== null);
this.div.removeEventListener("focusin", this.#boundFocusin);
this.div.removeEventListener("focusout", this.#boundFocusout);
this.parent.remove(this);
this._uiManager.removeEditor(this);
if (this.#moveInDOMTimeout) {
clearTimeout(this.#moveInDOMTimeout);
this.#moveInDOMTimeout = null;
this.removeEditToolbar();
if (this.#telemetryTimeouts) {
for (const timeout of this.#telemetryTimeouts.values()) {
this.#telemetryTimeouts = null;
this.#resizersDiv.classList.remove("hidden");
bindEvents(this, this.div, ["keydown"]);
if (!this.isResizable || event.target !== this.div || event.key !== "Enter") {
this._uiManager.setSelected(this);
this.#savedDimensions = {
const children = this.#resizersDiv.children;
if (!this.#allResizerDivs) {
this.#allResizerDivs = Array.from(children);
const boundResizerKeydown = this.#resizerKeydown.bind(this);
const boundResizerBlur = this.#resizerBlur.bind(this);
for (const div of this.#allResizerDivs) {
const name = div.getAttribute("data-resizer-name");
div.setAttribute("role", "spinbutton");
div.addEventListener("keydown", boundResizerKeydown);
div.addEventListener("blur", boundResizerBlur);
div.addEventListener("focus", this.#resizerFocus.bind(this, name));
AnnotationEditor._l10nPromise.get(`pdfjs-editor-resizer-label-${name}`).then(msg => div.setAttribute("aria-label", msg));
const first = this.#allResizerDivs[0];
for (const div of children) {
const nextFirstPosition = (360 - this.rotation + this.parentRotation) % 360 / 90 * (this.#allResizerDivs.length / 4);
if (nextFirstPosition !== firstPosition) {
if (nextFirstPosition < firstPosition) {
for (let i = 0; i < firstPosition - nextFirstPosition; i++) {
this.#resizersDiv.append(this.#resizersDiv.firstChild);
} else if (nextFirstPosition > firstPosition) {
for (let i = 0; i < nextFirstPosition - firstPosition; i++) {
this.#resizersDiv.firstChild.before(this.#resizersDiv.lastChild);
for (const child of children) {
const div = this.#allResizerDivs[i++];
const name = div.getAttribute("data-resizer-name");
AnnotationEditor._l10nPromise.get(`pdfjs-editor-resizer-label-${name}`).then(msg => child.setAttribute("aria-label", msg));
this.#setResizerTabIndex(0);
this.#isResizerEnabledForKeyboard = true;
this.#resizersDiv.firstChild.focus({
event.stopImmediatePropagation();
AnnotationEditor._resizerKeyboardManager.exec(this, event);
if (this.#isResizerEnabledForKeyboard && event.relatedTarget?.parentNode !== this.#resizersDiv) {
this.#focusedResizerName = this.#isResizerEnabledForKeyboard ? name : "";
#setResizerTabIndex(value) {
if (!this.#allResizerDivs) {
for (const div of this.#allResizerDivs) {
_resizeWithKeyboard(x, y) {
if (!this.#isResizerEnabledForKeyboard) {
this.#resizerPointermove(this.#focusedResizerName, {
this.#isResizerEnabledForKeyboard = false;
this.#setResizerTabIndex(-1);
if (this.#savedDimensions) {
} = this.#savedDimensions;
this.#addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight);
this.#savedDimensions = null;
_stopResizingWithKeyboard() {
this.div?.classList.add("selectedEditor");
if (!this.#editToolbar) {
this.addEditToolbar().then(() => {
if (this.div?.classList.contains("selectedEditor")) {
this.#editToolbar?.show();
this.#editToolbar?.show();
this.#resizersDiv?.classList.add("hidden");
this.div?.classList.remove("selectedEditor");
if (this.div?.contains(document.activeElement)) {
this._uiManager.currentLayer.div.focus({
this.#editToolbar?.hide();
updateParams(type, value) {}
this.parent.setSelected(this);
this.parent.setActiveEditor(this);
this.parent.setActiveEditor(null);
setAspectRatio(width, height) {
this.#keepAspectRatio = true;
const aspectRatio = width / height;
style.aspectRatio = aspectRatio;
static canCreateNewEmptyEditor() {
get telemetryInitialData() {
get telemetryFinalData() {
_reportTelemetry(data, mustWait = false) {
this.#telemetryTimeouts ||= new Map();
let timeout = this.#telemetryTimeouts.get(action);
timeout = setTimeout(() => {
this._reportTelemetry(data);
this.#telemetryTimeouts.delete(action);
if (this.#telemetryTimeouts.size === 0) {
this.#telemetryTimeouts = null;
}, AnnotationEditor._telemetryTimeout);
this.#telemetryTimeouts.set(action, timeout);
data.type ||= this.editorType;
this._uiManager._eventBus.dispatch("reporttelemetry", {
show(visible = this._isVisible) {
this.div.classList.toggle("hidden", !visible);
this._isVisible = visible;
renderAnnotationElement(annotation) {
let content = annotation.container.querySelector(".annotationContent");
content = document.createElement("div");
content.classList.add("annotationContent", this.editorType);
annotation.container.prepend(content);
} else if (content.nodeName === "CANVAS") {
content = document.createElement("div");
content.classList.add("annotationContent", this.editorType);
resetAnnotationElement(annotation) {
} = annotation.container;
if (firstChild.nodeName === "DIV" && firstChild.classList.contains("annotationContent")) {
class FakeEditor extends AnnotationEditor {
this.annotationElementId = params.annotationElementId;
id: this.annotationElementId,
pageIndex: this.pageIndex
;// CONCATENATED MODULE: ./src/shared/murmurhash3.js
const MASK_HIGH = 0xffff0000;
this.h1 = seed ? seed & 0xffffffff : SEED;
this.h2 = seed ? seed & 0xffffffff : SEED;
if (typeof input === "string") {
data = new Uint8Array(input.length * 2);
for (let i = 0, ii = input.length; i < ii; i++) {
const code = input.charCodeAt(i);
data[length++] = code >>> 8;
data[length++] = code & 0xff;
} else if (ArrayBuffer.isView(input)) {
length = data.byteLength;
throw new Error("Invalid data format, must be a string or TypedArray.");
const blockCounts = length >> 2;
const tailLength = length - blockCounts * 4;
const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts);
const C1_LOW = C1 & MASK_LOW,
for (let i = 0; i < blockCounts; i++) {
k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
k1 = k1 << 15 | k1 >>> 17;
k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
h1 = h1 << 13 | h1 >>> 19;
h1 = h1 * 5 + 0xe6546b64;
k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW;
k2 = k2 << 15 | k2 >>> 17;
k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW;
h2 = h2 << 13 | h2 >>> 19;
h2 = h2 * 5 + 0xe6546b64;
k1 ^= data[blockCounts * 4 + 2] << 16;
k1 ^= data[blockCounts * 4 + 1] << 8;
k1 ^= data[blockCounts * 4];
k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
k1 = k1 << 15 | k1 >>> 17;
k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW;
h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16;
h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW;
h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16;
return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0");
;// CONCATENATED MODULE: ./src/display/annotation_storage.js