mirror of
https://github.com/zen-browser/pdf.js.git
synced 2025-07-08 09:20:06 +02:00
[Editor] Provide an element to render in the annotation layer after a freetext has been edited (bug 1890535)
This commit is contained in:
parent
7290faf840
commit
71ea8499f0
11 changed files with 379 additions and 42 deletions
|
@ -20,6 +20,8 @@
|
|||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("../../web/interfaces").IDownloadManager} IDownloadManager */
|
||||
/** @typedef {import("../../web/interfaces").IPDFLinkService} IPDFLinkService */
|
||||
// eslint-disable-next-line max-len
|
||||
/** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */
|
||||
|
||||
import {
|
||||
AnnotationBorderStyleType,
|
||||
|
@ -157,6 +159,8 @@ class AnnotationElementFactory {
|
|||
}
|
||||
|
||||
class AnnotationElement {
|
||||
#updates = null;
|
||||
|
||||
#hasBorder = false;
|
||||
|
||||
constructor(
|
||||
|
@ -197,6 +201,52 @@ class AnnotationElement {
|
|||
return AnnotationElement._hasPopupData(this.data);
|
||||
}
|
||||
|
||||
updateEdited(params) {
|
||||
if (!this.container) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#updates ||= {
|
||||
rect: this.data.rect.slice(0),
|
||||
};
|
||||
|
||||
const { rect } = params;
|
||||
|
||||
if (rect) {
|
||||
this.#setRectEdited(rect);
|
||||
}
|
||||
}
|
||||
|
||||
resetEdited() {
|
||||
if (!this.#updates) {
|
||||
return;
|
||||
}
|
||||
this.#setRectEdited(this.#updates.rect);
|
||||
this.#updates = null;
|
||||
}
|
||||
|
||||
#setRectEdited(rect) {
|
||||
const {
|
||||
container: { style },
|
||||
data: { rect: currentRect, rotation },
|
||||
parent: {
|
||||
viewport: {
|
||||
rawDims: { pageWidth, pageHeight, pageX, pageY },
|
||||
},
|
||||
},
|
||||
} = this;
|
||||
currentRect?.splice(0, 4, ...rect);
|
||||
const { width, height } = getRectDims(rect);
|
||||
style.left = `${(100 * (rect[0] - pageX)) / pageWidth}%`;
|
||||
style.top = `${(100 * (pageHeight - rect[3] + pageY)) / pageHeight}%`;
|
||||
if (rotation === 0) {
|
||||
style.width = `${(100 * width) / pageWidth}%`;
|
||||
style.height = `${(100 * height) / pageHeight}%`;
|
||||
} else {
|
||||
this.setRotation(rotation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty container for the annotation's HTML element.
|
||||
*
|
||||
|
@ -216,13 +266,14 @@ class AnnotationElement {
|
|||
if (!(this instanceof WidgetAnnotationElement)) {
|
||||
container.tabIndex = DEFAULT_TAB_INDEX;
|
||||
}
|
||||
const { style } = container;
|
||||
|
||||
// The accessibility manager will move the annotation in the DOM in
|
||||
// order to match the visual ordering.
|
||||
// But if an annotation is above an other one, then we must draw it
|
||||
// after the other one whatever the order is in the DOM, hence the
|
||||
// use of the z-index.
|
||||
container.style.zIndex = this.parent.zIndex++;
|
||||
style.zIndex = this.parent.zIndex++;
|
||||
|
||||
if (data.popupRef) {
|
||||
container.setAttribute("aria-haspopup", "dialog");
|
||||
|
@ -236,8 +287,6 @@ class AnnotationElement {
|
|||
container.classList.add("norotate");
|
||||
}
|
||||
|
||||
const { pageWidth, pageHeight, pageX, pageY } = viewport.rawDims;
|
||||
|
||||
if (!data.rect || this instanceof PopupAnnotationElement) {
|
||||
const { rotation } = data;
|
||||
if (!data.hasOwnCanvas && rotation !== 0) {
|
||||
|
@ -248,35 +297,26 @@ class AnnotationElement {
|
|||
|
||||
const { width, height } = getRectDims(data.rect);
|
||||
|
||||
// Do *not* modify `data.rect`, since that will corrupt the annotation
|
||||
// position on subsequent calls to `_createContainer` (see issue 6804).
|
||||
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],
|
||||
]);
|
||||
|
||||
if (!ignoreBorder && data.borderStyle.width > 0) {
|
||||
container.style.borderWidth = `${data.borderStyle.width}px`;
|
||||
style.borderWidth = `${data.borderStyle.width}px`;
|
||||
|
||||
const horizontalRadius = data.borderStyle.horizontalCornerRadius;
|
||||
const verticalRadius = data.borderStyle.verticalCornerRadius;
|
||||
if (horizontalRadius > 0 || verticalRadius > 0) {
|
||||
const radius = `calc(${horizontalRadius}px * var(--scale-factor)) / calc(${verticalRadius}px * var(--scale-factor))`;
|
||||
container.style.borderRadius = radius;
|
||||
style.borderRadius = radius;
|
||||
} else if (this instanceof RadioButtonWidgetAnnotationElement) {
|
||||
const radius = `calc(${width}px * var(--scale-factor)) / calc(${height}px * var(--scale-factor))`;
|
||||
container.style.borderRadius = radius;
|
||||
style.borderRadius = radius;
|
||||
}
|
||||
|
||||
switch (data.borderStyle.style) {
|
||||
case AnnotationBorderStyleType.SOLID:
|
||||
container.style.borderStyle = "solid";
|
||||
style.borderStyle = "solid";
|
||||
break;
|
||||
|
||||
case AnnotationBorderStyleType.DASHED:
|
||||
container.style.borderStyle = "dashed";
|
||||
style.borderStyle = "dashed";
|
||||
break;
|
||||
|
||||
case AnnotationBorderStyleType.BEVELED:
|
||||
|
@ -288,7 +328,7 @@ class AnnotationElement {
|
|||
break;
|
||||
|
||||
case AnnotationBorderStyleType.UNDERLINE:
|
||||
container.style.borderBottomStyle = "solid";
|
||||
style.borderBottomStyle = "solid";
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -298,24 +338,34 @@ class AnnotationElement {
|
|||
const borderColor = data.borderColor || null;
|
||||
if (borderColor) {
|
||||
this.#hasBorder = true;
|
||||
container.style.borderColor = Util.makeHexColor(
|
||||
style.borderColor = Util.makeHexColor(
|
||||
borderColor[0] | 0,
|
||||
borderColor[1] | 0,
|
||||
borderColor[2] | 0
|
||||
);
|
||||
} else {
|
||||
// Transparent (invisible) border, so do not draw it at all.
|
||||
container.style.borderWidth = 0;
|
||||
style.borderWidth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
container.style.left = `${(100 * (rect[0] - pageX)) / pageWidth}%`;
|
||||
container.style.top = `${(100 * (rect[1] - pageY)) / pageHeight}%`;
|
||||
// Do *not* modify `data.rect`, since that will corrupt the annotation
|
||||
// position on subsequent calls to `_createContainer` (see issue 6804).
|
||||
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],
|
||||
]);
|
||||
const { pageWidth, pageHeight, pageX, pageY } = viewport.rawDims;
|
||||
|
||||
style.left = `${(100 * (rect[0] - pageX)) / pageWidth}%`;
|
||||
style.top = `${(100 * (rect[1] - pageY)) / pageHeight}%`;
|
||||
|
||||
const { rotation } = data;
|
||||
if (data.hasOwnCanvas || rotation === 0) {
|
||||
container.style.width = `${(100 * width) / pageWidth}%`;
|
||||
container.style.height = `${(100 * height) / pageHeight}%`;
|
||||
style.width = `${(100 * width) / pageWidth}%`;
|
||||
style.height = `${(100 * height) / pageHeight}%`;
|
||||
} else {
|
||||
this.setRotation(rotation, container);
|
||||
}
|
||||
|
@ -2897,6 +2947,7 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
|
|||
* @property {Object<string, Array<Object>> | null} [fieldObjects]
|
||||
* @property {Map<string, HTMLCanvasElement>} [annotationCanvasMap]
|
||||
* @property {TextAccessibilityManager} [accessibilityManager]
|
||||
* @property {AnnotationEditorUIManager} [annotationEditorUIManager]
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -2913,6 +2964,7 @@ class AnnotationLayer {
|
|||
div,
|
||||
accessibilityManager,
|
||||
annotationCanvasMap,
|
||||
annotationEditorUIManager,
|
||||
page,
|
||||
viewport,
|
||||
}) {
|
||||
|
@ -2922,6 +2974,7 @@ class AnnotationLayer {
|
|||
this.page = page;
|
||||
this.viewport = viewport;
|
||||
this.zIndex = 0;
|
||||
this._annotationEditorUIManager = annotationEditorUIManager;
|
||||
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
||||
// For testing purposes.
|
||||
|
@ -3011,15 +3064,16 @@ class AnnotationLayer {
|
|||
}
|
||||
}
|
||||
|
||||
if (element.annotationEditorType > 0) {
|
||||
this.#editableAnnotations.set(element.data.id, element);
|
||||
}
|
||||
|
||||
const rendered = element.render();
|
||||
if (data.hidden) {
|
||||
rendered.style.visibility = "hidden";
|
||||
}
|
||||
this.#appendElement(rendered, data.id);
|
||||
|
||||
if (element.annotationEditorType > 0) {
|
||||
this.#editableAnnotations.set(element.data.id, element);
|
||||
this._annotationEditorUIManager?.renderAnnotationElement(element);
|
||||
}
|
||||
}
|
||||
|
||||
this.#setAnnotationCanvasMap();
|
||||
|
@ -3051,13 +3105,16 @@ class AnnotationLayer {
|
|||
continue;
|
||||
}
|
||||
|
||||
canvas.className = "annotationContent";
|
||||
const { firstChild } = element;
|
||||
if (!firstChild) {
|
||||
element.append(canvas);
|
||||
} else if (firstChild.nodeName === "CANVAS") {
|
||||
firstChild.replaceWith(canvas);
|
||||
} else {
|
||||
} else if (!firstChild.classList.contains("annotationContent")) {
|
||||
firstChild.before(canvas);
|
||||
} else {
|
||||
firstChild.after(canvas);
|
||||
}
|
||||
}
|
||||
this.#annotationCanvasMap.clear();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue