Remove unnecessary closure in src/display/text_layer.js, and use standard classes

With modern JavaScript modules, where you explicitly list the properties that should be exported, it's no longer necessary to wrap all of the code in a closure.[1]

This patch also tries to clean-up/improve a couple of the existing JSDoc-comments.

---
[1] This reduces the size, even of the *built* `pdf.js` file, since there's now a lot less unnecessary whitespace.
This commit is contained in:
Jonas Jenwald 2021-05-05 16:36:18 +02:00
parent 52961197d3
commit 9a1758c6b8

View File

@ -42,24 +42,13 @@ import {
* selection enhancement. * selection enhancement.
*/ */
/** const MAX_TEXT_DIVS_TO_RENDER = 100000;
* @typedef {Object} TextLayerRenderTask const DEFAULT_FONT_SIZE = 30;
* @property {Promise<void>} promise const DEFAULT_FONT_ASCENT = 0.8;
* @property {() => void} cancel const ascentCache = new Map();
* @property {(expandDivs: boolean) => void} expandTextDivs const AllWhitespaceRegexp = /^\s+$/g;
*/
/** function getAscent(fontFamily, ctx) {
* @type {(renderParameters: TextLayerRenderParameters) => TextLayerRenderTask}
*/
const renderTextLayer = (function renderTextLayerClosure() {
const MAX_TEXT_DIVS_TO_RENDER = 100000;
const DEFAULT_FONT_SIZE = 30;
const DEFAULT_FONT_ASCENT = 0.8;
const ascentCache = new Map();
const AllWhitespaceRegexp = /^\s+$/g;
function getAscent(fontFamily, ctx) {
const cachedAscent = ascentCache.get(fontFamily); const cachedAscent = ascentCache.get(fontFamily);
if (cachedAscent) { if (cachedAscent) {
return cachedAscent; return cachedAscent;
@ -120,9 +109,9 @@ const renderTextLayer = (function renderTextLayerClosure() {
ascentCache.set(fontFamily, DEFAULT_FONT_ASCENT); ascentCache.set(fontFamily, DEFAULT_FONT_ASCENT);
return DEFAULT_FONT_ASCENT; return DEFAULT_FONT_ASCENT;
} }
function appendText(task, geom, styles, ctx) { function appendText(task, geom, styles, ctx) {
// Initialize all used properties to keep the caches monomorphic. // Initialize all used properties to keep the caches monomorphic.
const textDiv = document.createElement("span"); const textDiv = document.createElement("span");
const textDivProperties = { const textDivProperties = {
@ -138,7 +127,6 @@ const renderTextLayer = (function renderTextLayerClosure() {
scale: 1, scale: 1,
}; };
textDiv.textContent = geom.str;
task._textDivs.push(textDiv); task._textDivs.push(textDiv);
const tx = Util.transform(task._viewport.transform, geom.transform); const tx = Util.transform(task._viewport.transform, geom.transform);
@ -168,6 +156,7 @@ const renderTextLayer = (function renderTextLayerClosure() {
// Keeps screen readers from pausing on every new text span. // Keeps screen readers from pausing on every new text span.
textDiv.setAttribute("role", "presentation"); textDiv.setAttribute("role", "presentation");
textDiv.textContent = geom.str;
// geom.dir may be 'ttb' for vertical texts. // geom.dir may be 'ttb' for vertical texts.
textDiv.dir = geom.dir; textDiv.dir = geom.dir;
@ -241,9 +230,9 @@ const renderTextLayer = (function renderTextLayerClosure() {
m, m,
}); });
} }
} }
function render(task) { function render(task) {
if (task._canceled) { if (task._canceled) {
return; return;
} }
@ -267,9 +256,9 @@ const renderTextLayer = (function renderTextLayerClosure() {
task._renderingDone = true; task._renderingDone = true;
capability.resolve(); capability.resolve();
} }
function findPositiveMin(ts, offset, count) { function findPositiveMin(ts, offset, count) {
let result = 0; let result = 0;
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const t = ts[offset++]; const t = ts[offset++];
@ -278,9 +267,9 @@ const renderTextLayer = (function renderTextLayerClosure() {
} }
} }
return result; return result;
} }
function expand(task) { function expand(task) {
const bounds = task._bounds; const bounds = task._bounds;
const viewport = task._viewport; const viewport = task._viewport;
@ -337,9 +326,9 @@ const renderTextLayer = (function renderTextLayerClosure() {
divProperties.paddingBottom = findPositiveMin(ts, 16, 16) / boxScale; divProperties.paddingBottom = findPositiveMin(ts, 16, 16) / boxScale;
task._textDivProperties.set(div, divProperties); task._textDivProperties.set(div, divProperties);
} }
} }
function expandBounds(width, height, boxes) { function expandBounds(width, height, boxes) {
const bounds = boxes.map(function (box, i) { const bounds = boxes.map(function (box, i) {
return { return {
x1: box.left, x1: box.left,
@ -385,9 +374,9 @@ const renderTextLayer = (function renderTextLayerClosure() {
expanded[i].bottom = b.x2New; expanded[i].bottom = b.x2New;
} }
return expanded; return expanded;
} }
function expandBoundsLTR(width, bounds) { function expandBoundsLTR(width, bounds) {
// Sorting by x1 coordinate and walk by the bounds in the same order. // Sorting by x1 coordinate and walk by the bounds in the same order.
bounds.sort(function (a, b) { bounds.sort(function (a, b) {
return a.x1 - b.x1 || a.index - b.index; return a.x1 - b.x1 || a.index - b.index;
@ -559,19 +548,10 @@ const renderTextLayer = (function renderTextLayerClosure() {
affectedBoundary.x2New = Math.max(width, affectedBoundary.x2); affectedBoundary.x2New = Math.max(width, affectedBoundary.x2);
} }
} }
} }
/** class TextLayerRenderTask {
* Text layer rendering task. constructor({
*
* @param {TextContent} textContent
* @param {HTMLElement} container
* @param {PageViewport} viewport
* @param {Array} textDivs
* @param {boolean} enhanceTextSelection
* @private
*/
function TextLayerRenderTask({
textContent, textContent,
textContentStream, textContentStream,
container, container,
@ -616,12 +596,19 @@ const renderTextLayer = (function renderTextLayerClosure() {
/* Avoid "Uncaught promise" messages in the console. */ /* Avoid "Uncaught promise" messages in the console. */
}); });
} }
TextLayerRenderTask.prototype = {
/**
* Promise for textLayer rendering task completion.
* @type {Promise<void>}
*/
get promise() { get promise() {
return this._capability.promise; return this._capability.promise;
}, }
cancel: function TextLayer_cancel() { /**
* Cancel rendering of the textLayer.
*/
cancel() {
this._canceled = true; this._canceled = true;
if (this._reader) { if (this._reader) {
this._reader.cancel(new AbortException("TextLayer task cancelled.")); this._reader.cancel(new AbortException("TextLayer task cancelled."));
@ -632,8 +619,11 @@ const renderTextLayer = (function renderTextLayerClosure() {
this._renderTimer = null; this._renderTimer = null;
} }
this._capability.reject(new Error("TextLayer task cancelled.")); this._capability.reject(new Error("TextLayer task cancelled."));
}, }
/**
* @private
*/
_processItems(items, styleCache) { _processItems(items, styleCache) {
for (let i = 0, len = items.length; i < len; i++) { for (let i = 0, len = items.length; i < len; i++) {
if (items[i].str === undefined) { if (items[i].str === undefined) {
@ -656,8 +646,11 @@ const renderTextLayer = (function renderTextLayerClosure() {
this._textContentItemsStr.push(items[i].str); this._textContentItemsStr.push(items[i].str);
appendText(this, items[i], styleCache, this._layoutTextCtx); appendText(this, items[i], styleCache, this._layoutTextCtx);
} }
}, }
/**
* @private
*/
_layoutText(textDiv) { _layoutText(textDiv) {
const textDivProperties = this._textDivProperties.get(textDiv); const textDivProperties = this._textDivProperties.get(textDiv);
@ -700,9 +693,12 @@ const renderTextLayer = (function renderTextLayerClosure() {
br.setAttribute("role", "presentation"); br.setAttribute("role", "presentation");
this._container.appendChild(br); this._container.appendChild(br);
} }
}, }
_render: function TextLayer_render(timeout) { /**
* @private
*/
_render(timeout = 0) {
const capability = createPromiseCapability(); const capability = createPromiseCapability();
let styleCache = Object.create(null); let styleCache = Object.create(null);
@ -759,9 +755,12 @@ const renderTextLayer = (function renderTextLayerClosure() {
}, timeout); }, timeout);
} }
}, this._capability.reject); }, this._capability.reject);
}, }
expandTextDivs: function TextLayer_expandTextDivs(expandDivs) { /**
* @param {boolean} [expandDivs]
*/
expandTextDivs(expandDivs = false) {
if (!this._enhanceTextSelection || !this._renderingDone) { if (!this._enhanceTextSelection || !this._renderingDone) {
return; return;
} }
@ -820,11 +819,14 @@ const renderTextLayer = (function renderTextLayerClosure() {
div.style.transform = divProps.originalTransform; div.style.transform = divProps.originalTransform;
} }
} }
}, }
}; }
// eslint-disable-next-line no-shadow /**
function renderTextLayer(renderParameters) { * @param {TextLayerRenderParameters} renderParameters
* @returns {TextLayerRenderTask}
*/
function renderTextLayer(renderParameters) {
const task = new TextLayerRenderTask({ const task = new TextLayerRenderTask({
textContent: renderParameters.textContent, textContent: renderParameters.textContent,
textContentStream: renderParameters.textContentStream, textContentStream: renderParameters.textContentStream,
@ -836,9 +838,6 @@ const renderTextLayer = (function renderTextLayerClosure() {
}); });
task._render(renderParameters.timeout); task._render(renderParameters.timeout);
return task; return task;
} }
return renderTextLayer;
})();
export { renderTextLayer }; export { renderTextLayer };