Compare commits

..

No commits in common. "2d1833b56662fd6c6f9e8db1f2c587e205a97b3e" and "4b2683ecb6bf0bc1c5e5482ac41eb22cc1cdd38c" have entirely different histories.

2 changed files with 56 additions and 47 deletions

View File

@ -1,5 +1,5 @@
{ {
"stableVersion": "5.0.375", "stableVersion": "4.10.38",
"baseVersion": "7a57af12e13a47927c460e6b739a6ca132e7603d", "baseVersion": "7a57af12e13a47927c460e6b739a6ca132e7603d",
"versionPrefix": "5.0." "versionPrefix": "5.0."
} }

View File

@ -31,13 +31,6 @@ const DRAW_UPSCALE_FACTOR = 2; // See comment in `PDFThumbnailView.draw` below.
const MAX_NUM_SCALING_STEPS = 3; const MAX_NUM_SCALING_STEPS = 3;
const THUMBNAIL_WIDTH = 98; // px const THUMBNAIL_WIDTH = 98; // px
function zeroCanvas(c) {
// Zeroing the width and height causes Firefox to release graphics
// resources immediately, which can greatly reduce memory consumption.
c.width = 0;
c.height = 0;
}
/** /**
* @typedef {Object} PDFThumbnailViewOptions * @typedef {Object} PDFThumbnailViewOptions
* @property {HTMLDivElement} container - The viewer element. * @property {HTMLDivElement} container - The viewer element.
@ -81,8 +74,12 @@ class TempImageFactory {
} }
static destroyCanvas() { static destroyCanvas() {
if (this.#tempCanvas) { const tempCanvas = this.#tempCanvas;
zeroCanvas(this.#tempCanvas); if (tempCanvas) {
// Zeroing the width and height causes Firefox to release graphics
// resources immediately, which can greatly reduce memory consumption.
tempCanvas.width = 0;
tempCanvas.height = 0;
} }
this.#tempCanvas = null; this.#tempCanvas = null;
} }
@ -258,15 +255,37 @@ class PDFThumbnailView {
this.div.setAttribute("data-loaded", true); this.div.setAttribute("data-loaded", true);
this._placeholderImg.replaceWith(image); this._placeholderImg.replaceWith(image);
zeroCanvas(reducedCanvas); // Zeroing the width and height causes Firefox to release graphics
// resources immediately, which can greatly reduce memory consumption.
reducedCanvas.width = 0;
reducedCanvas.height = 0;
}
async #finishRenderTask(renderTask, canvas, error = null) {
// The renderTask may have been replaced by a new one, so only remove
// the reference to the renderTask if it matches the one that is
// triggering this callback.
if (renderTask === this.renderTask) {
this.renderTask = null;
}
if (error instanceof RenderingCancelledException) {
return;
}
this.renderingState = RenderingStates.FINISHED;
this.#convertCanvasToImage(canvas);
if (error) {
throw error;
}
} }
async draw() { async draw() {
if (this.renderingState !== RenderingStates.INITIAL) { if (this.renderingState !== RenderingStates.INITIAL) {
console.error("Must be in new state before drawing"); console.error("Must be in new state before drawing");
return; return undefined;
} }
const { pageColors, pdfPage } = this; const { pdfPage } = this;
if (!pdfPage) { if (!pdfPage) {
this.renderingState = RenderingStates.FINISHED; this.renderingState = RenderingStates.FINISHED;
@ -302,42 +321,29 @@ class PDFThumbnailView {
transform, transform,
viewport: drawViewport, viewport: drawViewport,
optionalContentConfigPromise: this._optionalContentConfigPromise, optionalContentConfigPromise: this._optionalContentConfigPromise,
pageColors, pageColors: this.pageColors,
}; };
const renderTask = (this.renderTask = pdfPage.render(renderContext)); const renderTask = (this.renderTask = pdfPage.render(renderContext));
renderTask.onContinue = renderContinueCallback; renderTask.onContinue = renderContinueCallback;
let error = null; const resultPromise = renderTask.promise.then(
try { () => this.#finishRenderTask(renderTask, canvas),
await renderTask.promise; error => this.#finishRenderTask(renderTask, canvas, error)
} catch (e) { );
if (e instanceof RenderingCancelledException) { resultPromise.finally(() => {
zeroCanvas(canvas); // Zeroing the width and height causes Firefox to release graphics
return; // resources immediately, which can greatly reduce memory consumption.
} canvas.width = 0;
error = e; canvas.height = 0;
} finally {
// The renderTask may have been replaced by a new one, so only remove
// the reference to the renderTask if it matches the one that is
// triggering this callback.
if (renderTask === this.renderTask) {
this.renderTask = null;
}
}
this.renderingState = RenderingStates.FINISHED;
this.#convertCanvasToImage(canvas);
zeroCanvas(canvas);
this.eventBus.dispatch("thumbnailrendered", { this.eventBus.dispatch("thumbnailrendered", {
source: this, source: this,
pageNumber: this.id, pageNumber: this.id,
pdfPage, pdfPage: this.pdfPage,
});
}); });
if (error) { return resultPromise;
throw error;
}
} }
setImage(pageView) { setImage(pageView) {
@ -360,8 +366,8 @@ class PDFThumbnailView {
} }
#getReducedImageDims(canvas) { #getReducedImageDims(canvas) {
const width = canvas.width << MAX_NUM_SCALING_STEPS, let reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS,
height = canvas.height << MAX_NUM_SCALING_STEPS; reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS;
const outputScale = new OutputScale(); const outputScale = new OutputScale();
// Here we're not actually "rendering" to the canvas and the `OutputScale` // Here we're not actually "rendering" to the canvas and the `OutputScale`
@ -369,12 +375,15 @@ class PDFThumbnailView {
outputScale.sx = outputScale.sy = 1; outputScale.sx = outputScale.sy = 1;
outputScale.limitCanvas( outputScale.limitCanvas(
width, reducedWidth,
height, reducedHeight,
this.maxCanvasPixels, this.maxCanvasPixels,
this.maxCanvasDim this.maxCanvasDim
); );
return [(width * outputScale.sx) | 0, (height * outputScale.sy) | 0]; reducedWidth = (reducedWidth * outputScale.sx) | 0;
reducedHeight = (reducedHeight * outputScale.sy) | 0;
return [reducedWidth, reducedHeight];
} }
#reduceImage(img) { #reduceImage(img) {