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:
parent
63b66b412c
commit
15b5808eee
9 changed files with 383 additions and 377 deletions
|
@ -458,7 +458,6 @@ class PDFPageView {
|
|||
this.eventBus.dispatch("textlayerrendered", {
|
||||
source: this,
|
||||
pageNumber: this.id,
|
||||
numTextDivs: textLayer.numTextDivs,
|
||||
error,
|
||||
});
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ const {
|
|||
renderTextLayer,
|
||||
setLayerDimensions,
|
||||
shadow,
|
||||
TextLayer,
|
||||
UnexpectedResponseException,
|
||||
updateTextLayer,
|
||||
Util,
|
||||
|
@ -101,6 +102,7 @@ export {
|
|||
renderTextLayer,
|
||||
setLayerDimensions,
|
||||
shadow,
|
||||
TextLayer,
|
||||
UnexpectedResponseException,
|
||||
updateTextLayer,
|
||||
Util,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue