commit baedb7894c76552439fbf59b328a851ccb76c140
parent 5d95a0922d711aabc29e3b3e5ab9dd2d16d1f084
Author: Updatebot <updatebot@mozilla.com>
Date: Fri, 17 Oct 2025 07:55:35 +0000
Bug 1994502 - Update PDF.js to 3eca60735ba27d0c6ec16b60b88dd6f1f5297e1c r=pdfjs-reviewers,calixte
Differential Revision: https://phabricator.services.mozilla.com/D268746
Diffstat:
6 files changed, 288 insertions(+), 153 deletions(-)
diff --git a/toolkit/components/pdfjs/content/build/pdf.mjs b/toolkit/components/pdfjs/content/build/pdf.mjs
@@ -21,8 +21,8 @@
*/
/**
- * pdfjsVersion = 5.4.315
- * pdfjsBuild = 8ba18075f
+ * pdfjsVersion = 5.4.329
+ * pdfjsBuild = 3eca60735
*/
/******/ // The require scope
/******/ var __webpack_require__ = {};
@@ -108,6 +108,11 @@ const PermissionFlag = {
ASSEMBLE: 0x400,
PRINT_HIGH_QUALITY: 0x800
};
+const MeshFigureType = {
+ TRIANGLES: 1,
+ LATTICE: 2,
+ PATCH: 3
+};
const TextRenderingMode = {
FILL: 0,
STROKE: 1,
@@ -5572,6 +5577,9 @@ class AnnotationEditor {
return this.#comment ||= new Comment(this);
}
addStandaloneCommentButton() {
+ if (!this._uiManager.hasCommentManager()) {
+ return;
+ }
if (this.#commentStandaloneButton) {
if (this._uiManager.isEditingMode()) {
this.#commentStandaloneButton.classList.remove("hidden");
@@ -8292,7 +8300,7 @@ function drawFigure(data, figure, context) {
const cs = figure.colors;
let i, ii;
switch (figure.type) {
- case "lattice":
+ case MeshFigureType.LATTICE:
const verticesPerRow = figure.verticesPerRow;
const rows = Math.floor(ps.length / verticesPerRow) - 1;
const cols = verticesPerRow - 1;
@@ -8304,7 +8312,7 @@ function drawFigure(data, figure, context) {
}
}
break;
- case "triangles":
+ case MeshFigureType.TRIANGLES:
for (i = 0, ii = ps.length; i < ii; i += 3) {
drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]);
}
@@ -12794,7 +12802,7 @@ function getDocument(src = {}) {
}
const docParams = {
docId,
- apiVersion: "5.4.315",
+ apiVersion: "5.4.329",
data,
password,
disableAutoFetch,
@@ -14371,8 +14379,8 @@ class InternalRenderTask {
}
}
}
-const version = "5.4.315";
-const build = "8ba18075f";
+const version = "5.4.329";
+const build = "3eca60735";
;// ./src/display/editor/color_picker.js
@@ -14844,6 +14852,7 @@ class AnnotationElement {
this.hasJSActions = parameters.hasJSActions;
this._fieldObjects = parameters.fieldObjects;
this.parent = parameters.parent;
+ this.hasOwnCommentButton = false;
if (isRenderable) {
this.contentElement = this.container = this._createContainer(ignoreBorder);
}
@@ -15348,7 +15357,7 @@ class AnnotationElement {
contentsObj = data.contentsObj;
modificationDate = data.modificationDate;
}
- const popup = this.#popupElement = new PopupAnnotationElement({
+ this.#popupElement = new PopupAnnotationElement({
data: {
color: data.color,
titleObj: data.titleObj,
@@ -15365,9 +15374,6 @@ class AnnotationElement {
parent: this.parent,
elements: [this]
});
- if (!this.parent._commentManager) {
- this.parent.div.append(popup.render());
- }
}
get hasPopupElement() {
return !!(this.#popupElement || this.popup || this.data.popupRef);
@@ -15499,7 +15505,6 @@ class EditorAnnotationElement extends AnnotationElement {
return;
}
this._createPopup(editor.comment);
- this.extraPopupElement.popup.renderCommentButton();
}
get hasCommentButton() {
return this.enableComment && this.editor.hasComment;
@@ -15520,6 +15525,7 @@ class EditorAnnotationElement extends AnnotationElement {
return this.editor.getData();
}
remove() {
+ this.parent.removeAnnotation(this.data.id);
this.container.remove();
this.container = null;
this.removePopup();
@@ -15775,6 +15781,7 @@ class TextAnnotationElement extends AnnotationElement {
type: this.data.name
}));
if (!this.data.popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
this.container.append(image);
@@ -16773,9 +16780,7 @@ class PopupElement {
this.#firstElement = elements[0];
this.#dateObj = PDFDateString.toDateObject(modificationDate);
this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup());
- if (commentManager) {
- this.renderCommentButton();
- } else {
+ if (!commentManager) {
this.#addEventListeners();
this.#container.hidden = true;
if (open) {
@@ -16818,6 +16823,9 @@ class PopupElement {
}
renderCommentButton() {
if (this.#commentButton) {
+ if (!this.#commentButton.parentNode) {
+ this.#firstElement.container.after(this.#commentButton);
+ }
return;
}
if (!this.#commentButtonPosition) {
@@ -16829,7 +16837,7 @@ class PopupElement {
const {
signal
} = this.#popupAbortController = new AbortController();
- const hasOwnButton = !!this.#firstElement.extraPopupElement;
+ const hasOwnButton = this.#firstElement.hasOwnCommentButton;
const togglePopup = () => {
this.#commentManager.toggleCommentPopup(this, true, undefined, !hasOwnButton);
};
@@ -16888,7 +16896,9 @@ class PopupElement {
if (this.#firstElement.extraPopupElement && !this.#firstElement.editor) {
return;
}
- this.renderCommentButton();
+ if (!this.#commentButton) {
+ this.renderCommentButton();
+ }
const [x, y] = this.#commentButtonPosition;
const {
style
@@ -16900,7 +16910,9 @@ class PopupElement {
if (this.#firstElement.extraPopupElement) {
return;
}
- this.renderCommentButton();
+ if (!this.#commentButton) {
+ this.renderCommentButton();
+ }
this.#commentButton.style.backgroundColor = this.commentButtonColor || "";
}
get commentButtonColor() {
@@ -17298,6 +17310,7 @@ class FreeTextAnnotationElement extends AnnotationElement {
this.container.append(content);
}
if (!this.data.popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
this._editOnDoubleClick();
@@ -17331,6 +17344,7 @@ class LineAnnotationElement extends AnnotationElement {
svg.append(line);
this.container.append(svg);
if (!data.popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
return this.container;
@@ -17370,6 +17384,7 @@ class SquareAnnotationElement extends AnnotationElement {
svg.append(square);
this.container.append(svg);
if (!data.popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
return this.container;
@@ -17409,6 +17424,7 @@ class CircleAnnotationElement extends AnnotationElement {
svg.append(circle);
this.container.append(svg);
if (!data.popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
return this.container;
@@ -17461,6 +17477,7 @@ class PolylineAnnotationElement extends AnnotationElement {
svg.append(polyline);
this.container.append(svg);
if (!popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
return this.container;
@@ -17489,6 +17506,7 @@ class CaretAnnotationElement extends AnnotationElement {
render() {
this.container.classList.add("caretAnnotation");
if (!this.data.popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
return this.container;
@@ -17567,6 +17585,7 @@ class InkAnnotationElement extends AnnotationElement {
g.append(polyline);
}
if (!popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
this.container.append(svg);
@@ -17624,6 +17643,7 @@ class HighlightAnnotationElement extends AnnotationElement {
}
} = this;
if (!popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
this.container.classList.add("highlightAnnotation");
@@ -17653,6 +17673,7 @@ class UnderlineAnnotationElement extends AnnotationElement {
}
} = this;
if (!popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
this.container.classList.add("underlineAnnotation");
@@ -17681,6 +17702,7 @@ class SquigglyAnnotationElement extends AnnotationElement {
}
} = this;
if (!popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
this.container.classList.add("squigglyAnnotation");
@@ -17709,6 +17731,7 @@ class StrikeOutAnnotationElement extends AnnotationElement {
}
} = this;
if (!popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
this.container.classList.add("strikeoutAnnotation");
@@ -17733,6 +17756,7 @@ class StampAnnotationElement extends AnnotationElement {
this.container.classList.add("stampAnnotation");
this.container.setAttribute("role", "img");
if (!this.data.popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
}
this._editOnDoubleClick();
@@ -17782,6 +17806,7 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
}
});
if (!data.popupRef && this.hasPopupData) {
+ this.hasOwnCommentButton = true;
this._createPopup();
} else {
trigger.classList.add("popupTriggerArea");
@@ -17806,6 +17831,8 @@ class AnnotationLayer {
#editableAnnotations = new Map();
#structTreeLayer = null;
#linkService = null;
+ #elements = [];
+ #hasAriaAttributesFromStructTree = false;
constructor({
div,
accessibilityManager,
@@ -17833,34 +17860,6 @@ class AnnotationLayer {
hasEditableAnnotations() {
return this.#editableAnnotations.size > 0;
}
- async #appendElement(element, id, popupElements) {
- const {
- contentElement,
- container
- } = element;
- const annotationId = contentElement.id = `${AnnotationPrefix}${id}`;
- const ariaAttributes = await this.#structTreeLayer?.getAriaAttributes(annotationId);
- if (ariaAttributes) {
- for (const [key, value] of ariaAttributes) {
- contentElement.setAttribute(key, value);
- }
- }
- if (popupElements) {
- popupElements.at(-1).container.after(container);
- } else {
- this.#moveElementInDOM(container, contentElement);
- }
- }
- #moveElementInDOM(container, contentElement) {
- this.div.append(container);
- this.#accessibilityManager?.moveElementInDOM(this.div, container, contentElement, false, node => node.nodeName === "SECTION", (prevNode, node) => {
- if (prevNode.nextElementSibling.nodeName === "BUTTON") {
- prevNode.nextElementSibling.after(node);
- } else {
- prevNode.after(node);
- }
- });
- }
async render(params) {
const {
annotations
@@ -17868,6 +17867,7 @@ class AnnotationLayer {
const layer = this.div;
setLayerDimensions(layer, this.viewport);
const popupToElements = new Map();
+ const popupAnnotations = [];
const elementParams = {
data: null,
layer,
@@ -17898,6 +17898,10 @@ class AnnotationLayer {
if (!elements) {
continue;
}
+ if (!this._commentManager) {
+ popupAnnotations.push(data);
+ continue;
+ }
elementParams.elements = elements;
}
elementParams.data = data;
@@ -17905,27 +17909,115 @@ class AnnotationLayer {
if (!element.isRenderable) {
continue;
}
- if (!isPopupAnnotation && data.popupRef) {
- const elements = popupToElements.get(data.popupRef);
- if (!elements) {
- popupToElements.set(data.popupRef, [element]);
- } else {
- elements.push(element);
+ if (!isPopupAnnotation) {
+ this.#elements.push(element);
+ if (data.popupRef) {
+ const elements = popupToElements.get(data.popupRef);
+ if (!elements) {
+ popupToElements.set(data.popupRef, [element]);
+ } else {
+ elements.push(element);
+ }
}
}
const rendered = element.render();
if (data.hidden) {
rendered.style.visibility = "hidden";
}
- await this.#appendElement(element, data.id, elementParams.elements);
- element.extraPopupElement?.popup?.renderCommentButton();
if (element._isEditable) {
this.#editableAnnotations.set(element.data.id, element);
this._annotationEditorUIManager?.renderAnnotationElement(element);
}
}
+ await this.#addElementsToDOM();
+ for (const data of popupAnnotations) {
+ const elements = elementParams.elements = popupToElements.get(data.id);
+ elementParams.data = data;
+ const element = AnnotationElementFactory.create(elementParams);
+ if (!element.isRenderable) {
+ continue;
+ }
+ const rendered = element.render();
+ element.contentElement.id = `${AnnotationPrefix}${data.id}`;
+ if (data.hidden) {
+ rendered.style.visibility = "hidden";
+ }
+ elements.at(-1).container.after(rendered);
+ }
this.#setAnnotationCanvasMap();
}
+ async #addElementsToDOM() {
+ if (this.#elements.length === 0) {
+ return;
+ }
+ this.div.replaceChildren();
+ const promises = [];
+ if (!this.#hasAriaAttributesFromStructTree) {
+ this.#hasAriaAttributesFromStructTree = true;
+ for (const {
+ contentElement,
+ data: {
+ id
+ }
+ } of this.#elements) {
+ const annotationId = contentElement.id = `${AnnotationPrefix}${id}`;
+ promises.push(this.#structTreeLayer?.getAriaAttributes(annotationId).then(ariaAttributes => {
+ if (ariaAttributes) {
+ for (const [key, value] of ariaAttributes) {
+ contentElement.setAttribute(key, value);
+ }
+ }
+ }));
+ }
+ }
+ this.#elements.sort(({
+ data: {
+ rect: [a0, a1, a2, a3]
+ }
+ }, {
+ data: {
+ rect: [b0, b1, b2, b3]
+ }
+ }) => {
+ if (a0 === a2 && a1 === a3) {
+ return +1;
+ }
+ if (b0 === b2 && b1 === b3) {
+ return -1;
+ }
+ const top1 = a3;
+ const bot1 = a1;
+ const mid1 = (a1 + a3) / 2;
+ const top2 = b3;
+ const bot2 = b1;
+ const mid2 = (b1 + b3) / 2;
+ if (mid1 >= top2 && mid2 <= bot1) {
+ return -1;
+ }
+ if (mid2 >= top1 && mid1 <= bot2) {
+ return +1;
+ }
+ const centerX1 = (a0 + a2) / 2;
+ const centerX2 = (b0 + b2) / 2;
+ return centerX1 - centerX2;
+ });
+ const fragment = document.createDocumentFragment();
+ for (const element of this.#elements) {
+ fragment.append(element.container);
+ if (this._commentManager) {
+ (element.extraPopupElement?.popup || element.popup)?.renderCommentButton();
+ } else if (element.extraPopupElement) {
+ fragment.append(element.extraPopupElement.render());
+ }
+ }
+ this.div.append(fragment);
+ await Promise.all(promises);
+ if (this.#accessibilityManager) {
+ for (const element of this.#elements) {
+ this.#accessibilityManager.addPointerInTextLayer(element.contentElement, false);
+ }
+ }
+ }
async addLinkAnnotations(annotations) {
const elementParams = {
data: null,
@@ -17942,8 +18034,10 @@ class AnnotationLayer {
continue;
}
element.render();
- await this.#appendElement(element, data.id, null);
+ element.contentElement.id = `${AnnotationPrefix}${data.id}`;
+ this.#elements.push(element);
}
+ await this.#addElementsToDOM();
}
update({
viewport
@@ -18019,24 +18113,31 @@ class AnnotationLayer {
linkService: this.#linkService,
annotationStorage: this.#annotationStorage
});
- const rendered = element.render();
- rendered.id = `${AnnotationPrefix}${id}`;
- this.#moveElementInDOM(rendered, rendered);
+ element.render();
+ element.contentElement.id = `${AnnotationPrefix}${id}`;
element.createOrUpdatePopup();
+ this.#elements.push(element);
return element;
}
- togglePointerEvents(enabled = false) {
- this.div.classList.toggle("disabled", !enabled);
+ removeAnnotation(id) {
+ const index = this.#elements.findIndex(el => el.data.id === id);
+ if (index < 0) {
+ return;
+ }
+ const [element] = this.#elements.splice(index, 1);
+ this.#accessibilityManager?.removePointerInTextLayer(element.contentElement);
}
updateFakeAnnotations(editors) {
if (editors.length === 0) {
return;
}
- window.requestAnimationFrame(() => setTimeout(() => {
- for (const editor of editors) {
- editor.updateFakeAnnotationElement(this);
- }
- }, 10));
+ for (const editor of editors) {
+ editor.updateFakeAnnotationElement(this);
+ }
+ this.#addElementsToDOM();
+ }
+ togglePointerEvents(enabled = false) {
+ this.div.classList.toggle("disabled", !enabled);
}
static get _defaultBorderStyle() {
return shadow(this, "_defaultBorderStyle", Object.freeze({
diff --git a/toolkit/components/pdfjs/content/build/pdf.scripting.mjs b/toolkit/components/pdfjs/content/build/pdf.scripting.mjs
@@ -21,8 +21,8 @@
*/
/**
- * pdfjsVersion = 5.4.315
- * pdfjsBuild = 8ba18075f
+ * pdfjsVersion = 5.4.329
+ * pdfjsBuild = 3eca60735
*/
var __webpack_exports__ = {};
diff --git a/toolkit/components/pdfjs/content/build/pdf.worker.mjs b/toolkit/components/pdfjs/content/build/pdf.worker.mjs
@@ -21,8 +21,8 @@
*/
/**
- * pdfjsVersion = 5.4.315
- * pdfjsBuild = 8ba18075f
+ * pdfjsVersion = 5.4.329
+ * pdfjsBuild = 3eca60735
*/
/******/ // The require scope
/******/ var __webpack_require__ = {};
@@ -108,6 +108,11 @@ const PermissionFlag = {
ASSEMBLE: 0x400,
PRINT_HIGH_QUALITY: 0x800
};
+const MeshFigureType = {
+ TRIANGLES: 1,
+ LATTICE: 2,
+ PATCH: 3
+};
const TextRenderingMode = {
FILL: 0,
STROKE: 1,
@@ -27583,7 +27588,7 @@ class MeshShading extends BaseShading {
reader.align();
}
this.figures.push({
- type: "triangles",
+ type: MeshFigureType.TRIANGLES,
coords: new Int32Array(ps),
colors: new Int32Array(ps)
});
@@ -27600,7 +27605,7 @@ class MeshShading extends BaseShading {
colors.push(color);
}
this.figures.push({
- type: "lattice",
+ type: MeshFigureType.LATTICE,
coords: new Int32Array(ps),
colors: new Int32Array(ps),
verticesPerRow
@@ -27717,7 +27722,7 @@ class MeshShading extends BaseShading {
ps[10] = coords.length;
coords.push([(-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9]);
this.figures.push({
- type: "patch",
+ type: MeshFigureType.PATCH,
coords: new Int32Array(ps),
colors: new Int32Array(cs)
});
@@ -27842,7 +27847,7 @@ class MeshShading extends BaseShading {
break;
}
this.figures.push({
- type: "patch",
+ type: MeshFigureType.PATCH,
coords: new Int32Array(ps),
colors: new Int32Array(cs)
});
@@ -27850,7 +27855,7 @@ class MeshShading extends BaseShading {
}
_buildFigureFromPatch(index) {
const figure = this.figures[index];
- assert(figure.type === "patch", "Unexpected patch mesh figure");
+ assert(figure.type === MeshFigureType.PATCH, "Unexpected patch mesh figure");
const coords = this.coords,
colors = this.colors;
const pi = figure.coords;
@@ -27915,7 +27920,7 @@ class MeshShading extends BaseShading {
figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
this.figures[index] = {
- type: "lattice",
+ type: MeshFigureType.LATTICE,
coords: figureCoords,
colors: figureColors,
verticesPerRow
@@ -36848,6 +36853,28 @@ class StructTreeRoot {
this.ref = rootRef instanceof Ref ? rootRef : null;
this.roleMap = new Map();
this.structParentIds = null;
+ this.kidRefToPosition = undefined;
+ }
+ getKidPosition(kidRef) {
+ if (this.kidRefToPosition === undefined) {
+ const obj = this.dict.get("K");
+ if (Array.isArray(obj)) {
+ const map = this.kidRefToPosition = new Map();
+ for (let i = 0, ii = obj.length; i < ii; i++) {
+ const ref = obj[i];
+ if (ref) {
+ map.set(ref.toString(), i);
+ }
+ }
+ } else if (obj instanceof Dict) {
+ this.kidRefToPosition = new Map([[obj.objId, 0]]);
+ } else if (!obj) {
+ this.kidRefToPosition = new Map();
+ } else {
+ this.kidRefToPosition = null;
+ }
+ }
+ return this.kidRefToPosition ? this.kidRefToPosition.get(kidRef) ?? NaN : -1;
}
init() {
this.readRoleMap();
@@ -37502,29 +37529,14 @@ class StructTreePage {
return element;
}
addTopLevelNode(dict, element) {
- const obj = this.rootDict.get("K");
- if (!obj) {
+ const index = this.root.getKidPosition(dict.objId);
+ if (isNaN(index)) {
return false;
}
- if (obj instanceof Dict) {
- if (obj.objId !== dict.objId) {
- return false;
- }
- this.nodes[0] = element;
- return true;
- }
- if (!Array.isArray(obj)) {
- return true;
- }
- let save = false;
- for (let i = 0; i < obj.length; i++) {
- const kidRef = obj[i];
- if (kidRef?.toString() === dict.objId) {
- this.nodes[i] = element;
- save = true;
- }
+ if (index !== -1) {
+ this.nodes[index] = element;
}
- return save;
+ return true;
}
get serializable() {
function nodeToSerializable(node, parent, level = 0) {
@@ -53477,10 +53489,10 @@ class DatasetReader {
;// ./src/core/intersector.js
class SingleIntersector {
#annotation;
- #minX = Infinity;
- #minY = Infinity;
- #maxX = -Infinity;
- #maxY = -Infinity;
+ minX = Infinity;
+ minY = Infinity;
+ maxX = -Infinity;
+ maxY = -Infinity;
#quadPoints = null;
#text = [];
#extraChars = [];
@@ -53490,24 +53502,21 @@ class SingleIntersector {
this.#annotation = annotation;
const quadPoints = annotation.data.quadPoints;
if (!quadPoints) {
- [this.#minX, this.#minY, this.#maxX, this.#maxY] = annotation.data.rect;
+ [this.minX, this.minY, this.maxX, this.maxY] = annotation.data.rect;
return;
}
for (let i = 0, ii = quadPoints.length; i < ii; i += 8) {
- this.#minX = Math.min(this.#minX, quadPoints[i]);
- this.#maxX = Math.max(this.#maxX, quadPoints[i + 2]);
- this.#minY = Math.min(this.#minY, quadPoints[i + 5]);
- this.#maxY = Math.max(this.#maxY, quadPoints[i + 1]);
+ this.minX = Math.min(this.minX, quadPoints[i]);
+ this.maxX = Math.max(this.maxX, quadPoints[i + 2]);
+ this.minY = Math.min(this.minY, quadPoints[i + 5]);
+ this.maxY = Math.max(this.maxY, quadPoints[i + 1]);
}
if (quadPoints.length > 8) {
this.#quadPoints = quadPoints;
}
}
- overlaps(other) {
- return !(this.#minX >= other.#maxX || this.#maxX <= other.#minX || this.#minY >= other.#maxY || this.#maxY <= other.#minY);
- }
#intersects(x, y) {
- if (this.#minX >= x || this.#maxX <= x || this.#minY >= y || this.#maxY <= y) {
+ if (this.minX >= x || this.maxX <= x || this.minY >= y || this.maxY <= y) {
return false;
}
const quadPoints = this.#quadPoints;
@@ -53558,52 +53567,81 @@ class SingleIntersector {
this.#annotation.data.overlaidText = this.#text.join("");
}
}
+const STEPS = 64;
class Intersector {
- #intersectors = new Map();
+ #intersectors = [];
+ #grid = [];
+ #minX;
+ #maxX;
+ #minY;
+ #maxY;
+ #invXRatio;
+ #invYRatio;
constructor(annotations) {
+ let minX = Infinity;
+ let minY = Infinity;
+ let maxX = -Infinity;
+ let maxY = -Infinity;
+ const intersectors = this.#intersectors;
for (const annotation of annotations) {
if (!annotation.data.quadPoints && !annotation.data.rect) {
continue;
}
const intersector = new SingleIntersector(annotation);
- for (const [otherIntersector, overlapping] of this.#intersectors) {
- if (otherIntersector.overlaps(intersector)) {
- if (!overlapping) {
- this.#intersectors.set(otherIntersector, new Set([intersector]));
- } else {
- overlapping.add(intersector);
- }
- }
- }
- this.#intersectors.set(intersector, null);
- }
+ intersectors.push(intersector);
+ minX = Math.min(minX, intersector.minX);
+ minY = Math.min(minY, intersector.minY);
+ maxX = Math.max(maxX, intersector.maxX);
+ maxY = Math.max(maxY, intersector.maxY);
+ }
+ this.#minX = minX;
+ this.#minY = minY;
+ this.#maxX = maxX;
+ this.#maxY = maxY;
+ this.#invXRatio = (STEPS - 1) / (maxX - minX);
+ this.#invYRatio = (STEPS - 1) / (maxY - minY);
+ for (const intersector of intersectors) {
+ const iMin = this.#getGridIndex(intersector.minX, intersector.minY);
+ const iMax = this.#getGridIndex(intersector.maxX, intersector.maxY);
+ const w = (iMax - iMin) % STEPS;
+ const h = Math.floor((iMax - iMin) / STEPS);
+ for (let i = iMin; i <= iMin + h * STEPS; i += STEPS) {
+ for (let j = 0; j <= w; j++) {
+ let existing = this.#grid[i + j];
+ if (!existing) {
+ this.#grid[i + j] = existing = [];
+ }
+ existing.push(intersector);
+ }
+ }
+ }
+ }
+ #getGridIndex(x, y) {
+ const i = Math.floor((x - this.#minX) * this.#invXRatio);
+ const j = Math.floor((y - this.#minY) * this.#invYRatio);
+ return i + j * STEPS;
}
addGlyph(transform, width, height, glyph) {
const x = transform[4] + width / 2;
const y = transform[5] + height / 2;
- let overlappingIntersectors;
- for (const [intersector, overlapping] of this.#intersectors) {
- if (overlappingIntersectors) {
- if (overlappingIntersectors.has(intersector)) {
- intersector.addGlyph(x, y, glyph);
- } else {
- intersector.disableExtraChars();
- }
- continue;
- }
- if (!intersector.addGlyph(x, y, glyph)) {
- continue;
- }
- overlappingIntersectors = overlapping;
+ if (x < this.#minX || y < this.#minY || x > this.#maxX || y > this.#maxY) {
+ return;
+ }
+ const intersectors = this.#grid[this.#getGridIndex(x, y)];
+ if (!intersectors) {
+ return;
+ }
+ for (const intersector of intersectors) {
+ intersector.addGlyph(x, y, glyph);
}
}
addExtraChar(char) {
- for (const intersector of this.#intersectors.keys()) {
+ for (const intersector of this.#intersectors) {
intersector.addExtraChar(char);
}
}
setText() {
- for (const intersector of this.#intersectors.keys()) {
+ for (const intersector of this.#intersectors) {
intersector.setText();
}
}
@@ -58126,7 +58164,7 @@ class WorkerMessageHandler {
docId,
apiVersion
} = docParams;
- const workerVersion = "5.4.315";
+ const workerVersion = "5.4.329";
if (apiVersion !== workerVersion) {
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
}
diff --git a/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs b/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs
@@ -21,8 +21,8 @@
*/
/**
- * pdfjsVersion = 5.4.315
- * pdfjsBuild = 8ba18075f
+ * pdfjsVersion = 5.4.329
+ * pdfjsBuild = 3eca60735
*/
/******/ // The require scope
/******/ var __webpack_require__ = {};
@@ -6941,21 +6941,19 @@ class TextAccessibilityManager {
const parent = child.parentNode;
return parent?.classList.contains("markedContent") ? parent.id : null;
}
- moveElementInDOM(container, element, contentElement, isRemovable, filter, inserter) {
+ moveElementInDOM(container, element, contentElement, isRemovable) {
const id = this.addPointerInTextLayer(contentElement, isRemovable);
if (!container.hasChildNodes()) {
container.append(element);
return id;
}
- const children = Array.from(container.childNodes).filter(node => node !== element && (!filter || filter(node)));
+ const children = Array.from(container.childNodes).filter(node => node !== element);
if (children.length === 0) {
return id;
}
const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(element, node) < 0);
if (index === 0) {
children[0].before(element);
- } else if (inserter) {
- inserter(children[index - 1], element);
} else {
children[index - 1].after(element);
}
@@ -8215,7 +8213,7 @@ class PDFViewer {
#textLayerMode = TextLayerMode.ENABLE;
#viewerAlert = null;
constructor(options) {
- const viewerVersion = "5.4.315";
+ const viewerVersion = "5.4.329";
if (version !== viewerVersion) {
throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
}
diff --git a/toolkit/components/pdfjs/content/web/viewer.mjs b/toolkit/components/pdfjs/content/web/viewer.mjs
@@ -21,8 +21,8 @@
*/
/**
- * pdfjsVersion = 5.4.315
- * pdfjsBuild = 8ba18075f
+ * pdfjsVersion = 5.4.329
+ * pdfjsBuild = 3eca60735
*/
/******/ // The require scope
/******/ var __webpack_require__ = {};
@@ -10126,21 +10126,19 @@ class TextAccessibilityManager {
const parent = child.parentNode;
return parent?.classList.contains("markedContent") ? parent.id : null;
}
- moveElementInDOM(container, element, contentElement, isRemovable, filter, inserter) {
+ moveElementInDOM(container, element, contentElement, isRemovable) {
const id = this.addPointerInTextLayer(contentElement, isRemovable);
if (!container.hasChildNodes()) {
container.append(element);
return id;
}
- const children = Array.from(container.childNodes).filter(node => node !== element && (!filter || filter(node)));
+ const children = Array.from(container.childNodes).filter(node => node !== element);
if (children.length === 0) {
return id;
}
const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(element, node) < 0);
if (index === 0) {
children[0].before(element);
- } else if (inserter) {
- inserter(children[index - 1], element);
} else {
children[index - 1].after(element);
}
@@ -11400,7 +11398,7 @@ class PDFViewer {
#textLayerMode = TextLayerMode.ENABLE;
#viewerAlert = null;
constructor(options) {
- const viewerVersion = "5.4.315";
+ const viewerVersion = "5.4.329";
if (version !== viewerVersion) {
throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
}
diff --git a/toolkit/components/pdfjs/moz.yaml b/toolkit/components/pdfjs/moz.yaml
@@ -20,8 +20,8 @@ origin:
# Human-readable identifier for this version/release
# Generally "version NNN", "tag SSS", "bookmark SSS"
- release: 8ba18075f2655361795a34930ea6cd4f7ac891c8 (2025-10-08T14:55:01Z).
- revision: 8ba18075f2655361795a34930ea6cd4f7ac891c8
+ release: 3eca60735ba27d0c6ec16b60b88dd6f1f5297e1c (2025-10-14T18:25:40Z).
+ revision: 3eca60735ba27d0c6ec16b60b88dd6f1f5297e1c
# The package's license, where possible using the mnemonic from
# https://spdx.org/licenses/