diff --git a/src/core/evaluator.js b/src/core/evaluator.js index eb6c0b7fc..d15df86cf 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -71,6 +71,7 @@ import { getGlyphsUnicode } from "./glyphlist.js"; import { getLookupTableFactory } from "./core_utils.js"; import { getMetrics } from "./metrics.js"; import { getUnicodeForGlyph } from "./unicode.js"; +import { ImageResizer } from "./image_resizer.js"; import { MurmurHash3_64 } from "../shared/murmurhash3.js"; import { OperatorList } from "./operator_list.js"; import { PDFImage } from "./image.js"; @@ -81,6 +82,7 @@ const DefaultPartialEvaluatorOptions = Object.freeze({ ignoreErrors: false, isEvalSupported: true, isOffscreenCanvasSupported: false, + canvasMaxAreaInBytes: -1, fontExtraProperties: false, useSystemFonts: true, cMapUrl: null, @@ -229,6 +231,7 @@ class PartialEvaluator { this.parsingType3Font = false; this._fetchBuiltInCMapBound = this.fetchBuiltInCMap.bind(this); + ImageResizer.setMaxArea(this.options.canvasMaxAreaInBytes); } /** diff --git a/src/core/image_resizer.js b/src/core/image_resizer.js index be09c9b35..ae0d43fa2 100644 --- a/src/core/image_resizer.js +++ b/src/core/image_resizer.js @@ -103,8 +103,17 @@ class ImageResizer { } static set MAX_AREA(area) { - this._hasMaxArea = true; - shadow(this, "MAX_AREA", area); + if (area >= 0) { + this._hasMaxArea = true; + shadow(this, "MAX_AREA", area); + } + } + + static setMaxArea(area) { + if (!this._hasMaxArea) { + // Divide by 4 to have the value in pixels. + this.MAX_AREA = area >> 2; + } } static _areGoodDims(width, height) { diff --git a/src/display/api.js b/src/display/api.js index 521142c0a..76fe6b93d 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -201,6 +201,9 @@ if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")) { * `OffscreenCanvas` in the worker. Primarily used to improve performance of * image conversion/rendering. * The default value is `true` in web environments and `false` in Node.js. + * @property {boolean} [canvasMaxAreaInBytes] - The integer value is used to + * know when an image must be resized (uses `OffscreenCanvas` in the worker). + * If it's -1 then a possibly slow algorithm is used to guess the max value. * @property {boolean} [disableFontFace] - By default fonts are converted to * OpenType fonts and loaded via the Font Loading API or `@font-face` rules. * If disabled, fonts will be rendered using a built-in font renderer that @@ -306,6 +309,9 @@ function getDocument(src) { typeof src.isOffscreenCanvasSupported === "boolean" ? src.isOffscreenCanvasSupported : !isNodeJS; + const canvasMaxAreaInBytes = Number.isInteger(src.canvasMaxAreaInBytes) + ? src.canvasMaxAreaInBytes + : -1; const disableFontFace = typeof src.disableFontFace === "boolean" ? src.disableFontFace : isNodeJS; const fontExtraProperties = src.fontExtraProperties === true; @@ -393,6 +399,7 @@ function getDocument(src) { ignoreErrors, isEvalSupported, isOffscreenCanvasSupported, + canvasMaxAreaInBytes, fontExtraProperties, useSystemFonts, cMapUrl: useWorkerFetch ? cMapUrl : null, diff --git a/web/app.js b/web/app.js index 58a6e20ae..685930551 100644 --- a/web/app.js +++ b/web/app.js @@ -149,6 +149,10 @@ class DefaultExternalServices { static updateEditorStates(data) { throw new Error("Not implemented: updateEditorStates"); } + + static get canvasMaxAreaInBytes() { + return shadow(this, "canvasMaxAreaInBytes", -1); + } } const PDFViewerApplication = { @@ -945,7 +949,11 @@ const PDFViewerApplication = { } // Set the necessary API parameters, using all the available options. const apiParams = AppOptions.getAll(OptionKind.API); - const params = { ...apiParams, ...args }; + const params = { + canvasMaxAreaInBytes: this.externalServices.canvasMaxAreaInBytes, + ...apiParams, + ...args, + }; if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")) { params.docBaseUrl ||= document.URL.split("#")[0]; diff --git a/web/firefoxcom.js b/web/firefoxcom.js index f0e574ac9..af8071751 100644 --- a/web/firefoxcom.js +++ b/web/firefoxcom.js @@ -434,6 +434,11 @@ class FirefoxExternalServices extends DefaultExternalServices { const isInAutomation = FirefoxCom.requestSync("isInAutomation"); return shadow(this, "isInAutomation", isInAutomation); } + + static get canvasMaxAreaInBytes() { + const maxArea = FirefoxCom.requestSync("getCanvasMaxArea"); + return shadow(this, "canvasMaxAreaInBytes", maxArea); + } } PDFViewerApplication.externalServices = FirefoxExternalServices;