From 107efdb1788d3ca1c680de7b00e86d9a2a4a6ce4 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Thu, 5 Aug 2021 11:04:09 +0200 Subject: [PATCH] [Regression] Re-factor the *internal* `renderInteractiveForms` handling, since it's currently subtly wrong The value of the `renderInteractiveForms` parameter, as passed to the `PDFPageProxy.render` method, will (potentially) affect the size/content of the operatorList that's returned from the worker (for documents with forms). Given that operatorLists will generally, unless they contain huge images, be cached in the API, repeated `PDFPageProxy.render` calls that *only* change the `renderInteractiveForms` parameter can thus return an incorrect operatorList. As far as I can tell, this *subtle* bug has existed ever since `renderInteractiveForms`-support was first added in PR 7633 (which is almost five years ago). With the previous patch, fixing this is now really simple by "encoding" the `renderInteractiveForms` parameter in the *internal* renderingIntent handling. --- src/core/document.js | 14 ++++---------- src/core/worker.js | 1 - src/display/api.js | 10 +++++++--- src/shared/util.js | 1 + 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/core/document.js b/src/core/document.js index 45eda09cc..361a9acab 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -320,14 +320,7 @@ class Page { }); } - getOperatorList({ - handler, - sink, - task, - intent, - renderInteractiveForms, - annotationStorage, - }) { + getOperatorList({ handler, sink, task, intent, annotationStorage }) { const contentStreamPromise = this.getContentStream(handler); const resourcesPromise = this.loadResources([ "ColorSpace", @@ -384,7 +377,8 @@ class Page { pageOpList.flush(true); return { length: pageOpList.totalLength }; } - const intentAny = !!(intent & RenderingIntentFlag.ANY), + const renderForms = !!(intent & RenderingIntentFlag.ANNOTATION_FORMS), + intentAny = !!(intent & RenderingIntentFlag.ANY), intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY), intentPrint = !!(intent & RenderingIntentFlag.PRINT); @@ -402,7 +396,7 @@ class Page { .getOperatorList( partialEvaluator, task, - renderInteractiveForms, + renderForms, annotationStorage ) .catch(function (reason) { diff --git a/src/core/worker.js b/src/core/worker.js index 5b9164301..949044d08 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -688,7 +688,6 @@ class WorkerMessageHandler { sink, task, intent: data.intent, - renderInteractiveForms: data.renderInteractiveForms, annotationStorage: data.annotationStorage, }) .then( diff --git a/src/display/api.js b/src/display/api.js index c944a24a6..4deb70350 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -515,7 +515,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { }); } -function getRenderingIntent(intent, { isOpList = false }) { +function getRenderingIntent(intent, { renderForms = false, isOpList = false }) { let renderingIntent = RenderingIntentFlag.DISPLAY; // Default value. switch (intent) { case "any": @@ -529,6 +529,9 @@ function getRenderingIntent(intent, { isOpList = false }) { default: warn(`getRenderingIntent - invalid intent: ${intent}`); } + if (renderForms) { + renderingIntent += RenderingIntentFlag.ANNOTATION_FORMS; + } if (isOpList) { renderingIntent += RenderingIntentFlag.OPLIST; } @@ -1356,7 +1359,9 @@ class PDFPageProxy { this._stats.time("Overall"); } - const renderingIntent = getRenderingIntent(intent, {}); + const renderingIntent = getRenderingIntent(intent, { + renderForms: renderInteractiveForms === true, + }); // If there was a pending destroy, cancel it so no cleanup happens during // this call to render. this.pendingCleanup = false; @@ -1400,7 +1405,6 @@ class PDFPageProxy { this._pumpOperatorList({ pageIndex: this._pageIndex, intent: renderingIntent, - renderInteractiveForms: renderInteractiveForms === true, annotationStorage, }); } diff --git a/src/shared/util.js b/src/shared/util.js index 75c3e60f3..92d0ae9a0 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -22,6 +22,7 @@ const RenderingIntentFlag = { ANY: 0x01, DISPLAY: 0x02, PRINT: 0x04, + ANNOTATION_FORMS: 0x20, OPLIST: 0x100, };