1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-19 22:58:07 +02:00

[api-minor] Re-factor the basic textLayer-functionality

This is very old code, and predates e.g. the introduction of JavaScript classes, which creates unnecessarily unwieldy code in the viewer.
By introducing a new `TextLayer` class in the API, similar to how e.g. the `AnnotationLayer` looks, we're able to keep most parameters on the class-instance itself. This removes the need to manually track them in the viewer, and simplifies the call-sites.

This also removes the `numTextDivs` parameter from the "textlayerrendered" event, since that's only added to support default-viewer functionality that no longer exists.

Finally we try, as far as possible, to polyfill the old `renderTextLayer` and `updateTextLayer` functions since they are exposed in the library API.
For *simple* invocations of `renderTextLayer` the behaviour should thus be the same, with only a warning printed in the console.
This commit is contained in:
Jonas Jenwald 2024-05-16 11:28:06 +02:00
parent 63b66b412c
commit 15b5808eee
9 changed files with 383 additions and 377 deletions

View file

@ -458,7 +458,6 @@ class PDFPageView {
this.eventBus.dispatch("textlayerrendered", {
source: this,
pageNumber: this.id,
numTextDivs: textLayer.numTextDivs,
error,
});

View file

@ -53,6 +53,7 @@ const {
renderTextLayer,
setLayerDimensions,
shadow,
TextLayer,
UnexpectedResponseException,
updateTextLayer,
Util,
@ -101,6 +102,7 @@ export {
renderTextLayer,
setLayerDimensions,
shadow,
TextLayer,
UnexpectedResponseException,
updateTextLayer,
Util,

View file

@ -20,7 +20,7 @@
// eslint-disable-next-line max-len
/** @typedef {import("./text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
import { normalizeUnicode, renderTextLayer, updateTextLayer } from "pdfjs-lib";
import { normalizeUnicode, TextLayer } from "pdfjs-lib";
import { removeNullCharacters } from "./ui_utils.js";
/**
@ -41,12 +41,10 @@ class TextLayerBuilder {
#onAppend = null;
#rotation = 0;
#scale = 0;
#textContentSource = null;
#textLayer = null;
static #textLayers = new Map();
static #selectionChangeAbortController = null;
@ -57,11 +55,7 @@ class TextLayerBuilder {
enablePermissions = false,
onAppend = null,
}) {
this.textContentItemsStr = [];
this.renderingDone = false;
this.textDivs = [];
this.textDivProperties = new WeakMap();
this.textLayerRenderTask = null;
this.highlighter = highlighter;
this.accessibilityManager = accessibilityManager;
this.#enablePermissions = enablePermissions === true;
@ -82,10 +76,6 @@ class TextLayerBuilder {
this.#bindMouse(endOfContent);
}
get numTextDivs() {
return this.textDivs.length;
}
/**
* Renders the text layer.
* @param {PageViewport} viewport
@ -95,45 +85,28 @@ class TextLayerBuilder {
throw new Error('No "textContentSource" parameter specified.');
}
const scale = viewport.scale * (globalThis.devicePixelRatio || 1);
const { rotation } = viewport;
if (this.renderingDone) {
const mustRotate = rotation !== this.#rotation;
const mustRescale = scale !== this.#scale;
if (mustRotate || mustRescale) {
this.hide();
updateTextLayer({
container: this.div,
viewport,
textDivs: this.textDivs,
textDivProperties: this.textDivProperties,
mustRescale,
mustRotate,
});
this.#scale = scale;
this.#rotation = rotation;
}
if (this.renderingDone && this.#textLayer) {
this.#textLayer.update({
viewport,
onBefore: this.hide.bind(this),
});
this.show();
return;
}
this.cancel();
this.highlighter?.setTextMapping(this.textDivs, this.textContentItemsStr);
this.accessibilityManager?.setTextMapping(this.textDivs);
this.textLayerRenderTask = renderTextLayer({
this.#textLayer = new TextLayer({
textContentSource: this.#textContentSource,
container: this.div,
viewport,
textDivs: this.textDivs,
textDivProperties: this.textDivProperties,
textContentItemsStr: this.textContentItemsStr,
});
await this.textLayerRenderTask.promise;
const { textDivs, textContentItemsStr } = this.#textLayer;
this.highlighter?.setTextMapping(textDivs, textContentItemsStr);
this.accessibilityManager?.setTextMapping(textDivs);
await this.#textLayer.render();
this.#finishRendering();
this.#scale = scale;
this.#rotation = rotation;
// Ensure that the textLayer is appended to the DOM *before* handling
// e.g. a pending search operation.
this.#onAppend?.(this.div);
@ -161,15 +134,11 @@ class TextLayerBuilder {
* Cancel rendering of the text layer.
*/
cancel() {
if (this.textLayerRenderTask) {
this.textLayerRenderTask.cancel();
this.textLayerRenderTask = null;
}
this.#textLayer?.cancel();
this.#textLayer = null;
this.highlighter?.disable();
this.accessibilityManager?.disable();
this.textContentItemsStr.length = 0;
this.textDivs.length = 0;
this.textDivProperties = new WeakMap();
TextLayerBuilder.#removeGlobalSelectionListener(this.div);
}