Skip to content

[api-minor] Re-factor the *internal* renderingIntent, and change the default intent value in the PDFPageProxy.getAnnotations method #13867

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions src/core/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
isString,
OPS,
PageActionEventType,
RenderingIntentFlag,
shadow,
stringToBytes,
stringToPDFString,
Expand Down Expand Up @@ -319,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",
Expand Down Expand Up @@ -383,26 +377,26 @@ class Page {
pageOpList.flush(true);
return { length: pageOpList.totalLength };
}
const renderForms = !!(intent & RenderingIntentFlag.ANNOTATION_FORMS),
intentAny = !!(intent & RenderingIntentFlag.ANY),
intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY),
intentPrint = !!(intent & RenderingIntentFlag.PRINT);

// Collect the operator list promises for the annotations. Each promise
// is resolved with the complete operator list for a single annotation.
const annotationIntent = intent.startsWith("oplist-")
? intent.split("-")[1]
: intent;
const opListPromises = [];
for (const annotation of annotations) {
if (
(annotationIntent === "display" &&
annotation.mustBeViewed(annotationStorage)) ||
(annotationIntent === "print" &&
annotation.mustBePrinted(annotationStorage))
intentAny ||
(intentDisplay && annotation.mustBeViewed(annotationStorage)) ||
(intentPrint && annotation.mustBePrinted(annotationStorage))
) {
opListPromises.push(
annotation
.getOperatorList(
partialEvaluator,
task,
renderInteractiveForms,
renderForms,
annotationStorage
)
.catch(function (reason) {
Expand Down Expand Up @@ -496,15 +490,23 @@ class Page {
getAnnotationsData(intent) {
return this._parsedAnnotations.then(function (annotations) {
const annotationsData = [];
for (let i = 0, ii = annotations.length; i < ii; i++) {

if (annotations.length === 0) {
return annotationsData;
}
const intentAny = !!(intent & RenderingIntentFlag.ANY),
intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY),
intentPrint = !!(intent & RenderingIntentFlag.PRINT);

for (const annotation of annotations) {
// Get the annotation even if it's hidden because
// JS can change its display.
if (
!intent ||
(intent === "display" && annotations[i].viewable) ||
(intent === "print" && annotations[i].printable)
intentAny ||
(intentDisplay && annotation.viewable) ||
(intentPrint && annotation.printable)
) {
annotationsData.push(annotations[i].data);
annotationsData.push(annotation.data);
}
}
return annotationsData;
Expand Down
13 changes: 10 additions & 3 deletions src/core/operator_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@
* limitations under the License.
*/

import { assert, ImageKind, OPS, shadow, warn } from "../shared/util.js";
import {
assert,
ImageKind,
OPS,
RenderingIntentFlag,
shadow,
warn,
} from "../shared/util.js";

function addState(parentState, pattern, checkFn, iterateFn, processFn) {
let state = parentState;
Expand Down Expand Up @@ -597,11 +604,11 @@ class OperatorList {
return shadow(this, "CHUNK_SIZE_ABOUT", this.CHUNK_SIZE - 5);
}

constructor(intent, streamSink) {
constructor(intent = 0, streamSink) {
this._streamSink = streamSink;
this.fnArray = [];
this.argsArray = [];
if (streamSink && !(intent && intent.startsWith("oplist-"))) {
if (streamSink && !(intent & RenderingIntentFlag.OPLIST)) {
this.optimizer = new QueueOptimizer(this);
} else {
this.optimizer = new NullOptimizer(this);
Expand Down
1 change: 0 additions & 1 deletion src/core/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,6 @@ class WorkerMessageHandler {
sink,
task,
intent: data.intent,
renderInteractiveForms: data.renderInteractiveForms,
annotationStorage: data.annotationStorage,
})
.then(
Expand Down
59 changes: 42 additions & 17 deletions src/display/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
isSameOrigin,
MissingPDFException,
PasswordException,
RenderingIntentFlag,
setVerbosityLevel,
shadow,
stringToBytes,
Expand Down Expand Up @@ -514,6 +515,29 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
});
}

function getRenderingIntent(intent, { renderForms = false, isOpList = false }) {
let renderingIntent = RenderingIntentFlag.DISPLAY; // Default value.
switch (intent) {
case "any":
renderingIntent = RenderingIntentFlag.ANY;
break;
case "display":
break;
case "print":
renderingIntent = RenderingIntentFlag.PRINT;
break;
default:
warn(`getRenderingIntent - invalid intent: ${intent}`);
}
if (renderForms) {
renderingIntent += RenderingIntentFlag.ANNOTATION_FORMS;
}
if (isOpList) {
renderingIntent += RenderingIntentFlag.OPLIST;
}
return renderingIntent;
}

/**
* @typedef {Object} OnProgressParameters
* @property {number} loaded - Currently loaded number of bytes.
Expand Down Expand Up @@ -1120,8 +1144,8 @@ class PDFDocumentProxy {
*
* @typedef {Object} GetAnnotationsParameters
* @property {string} [intent] - Determines the annotations that are fetched,
* can be either 'display' (viewable annotations) or 'print' (printable
* annotations). If the parameter is omitted, all annotations are fetched.
* can be 'display' (viewable annotations), 'print' (printable annotations),
* or 'any' (all annotations). The default value is 'display'.
*/

/**
Expand All @@ -1131,8 +1155,8 @@ class PDFDocumentProxy {
* @property {Object} canvasContext - A 2D context of a DOM Canvas object.
* @property {PageViewport} viewport - Rendering viewport obtained by calling
* the `PDFPageProxy.getViewport` method.
* @property {string} [intent] - Rendering intent, can be 'display' or 'print'.
* The default value is 'display'.
* @property {string} [intent] - Rendering intent, can be 'display', 'print',
* or 'any'. The default value is 'display'.
* @property {boolean} [renderInteractiveForms] - Whether or not interactive
* form elements are rendered in the display layer. If so, we do not render
* them on the canvas as well. The default value is `false`.
Expand Down Expand Up @@ -1161,8 +1185,8 @@ class PDFDocumentProxy {
* Page getOperatorList parameters.
*
* @typedef {Object} GetOperatorListParameters
* @property {string} [intent] - Rendering intent, can be 'display' or 'print'.
* The default value is 'display'.
* @property {string} [intent] - Rendering intent, can be 'display', 'print',
* or 'any'. The default value is 'display'.
*/

/**
Expand Down Expand Up @@ -1276,9 +1300,8 @@ class PDFPageProxy {
* @returns {Promise<Array<any>>} A promise that is resolved with an
* {Array} of the annotation objects.
*/
getAnnotations({ intent = null } = {}) {
const renderingIntent =
intent === "display" || intent === "print" ? intent : null;
getAnnotations({ intent = "display" } = {}) {
const renderingIntent = getRenderingIntent(intent, {});

if (
!this._annotationsPromise ||
Expand Down Expand Up @@ -1336,7 +1359,9 @@ class PDFPageProxy {
this._stats.time("Overall");
}

const renderingIntent = intent === "print" ? "print" : "display";
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;
Expand Down Expand Up @@ -1380,7 +1405,6 @@ class PDFPageProxy {
this._pumpOperatorList({
pageIndex: this._pageIndex,
intent: renderingIntent,
renderInteractiveForms: renderInteractiveForms === true,
annotationStorage,
});
}
Expand All @@ -1390,7 +1414,10 @@ class PDFPageProxy {

// Attempt to reduce memory usage during *printing*, by always running
// cleanup once rendering has finished (regardless of cleanupAfterRender).
if (this.cleanupAfterRender || renderingIntent === "print") {
if (
this.cleanupAfterRender ||
renderingIntent & RenderingIntentFlag.PRINT
) {
this.pendingCleanup = true;
}
this._tryCleanup();
Expand Down Expand Up @@ -1426,7 +1453,7 @@ class PDFPageProxy {
operatorList: intentState.operatorList,
pageIndex: this._pageIndex,
canvasFactory: canvasFactoryInstance,
useRequestAnimationFrame: renderingIntent !== "print",
useRequestAnimationFrame: !(renderingIntent & RenderingIntentFlag.PRINT),
pdfBug: this._pdfBug,
});

Expand Down Expand Up @@ -1471,9 +1498,7 @@ class PDFPageProxy {
}
}

const renderingIntent = `oplist-${
intent === "print" ? "print" : "display"
}`;
const renderingIntent = getRenderingIntent(intent, { isOpList: true });
let intentState = this._intentStates.get(renderingIntent);
if (!intentState) {
intentState = Object.create(null);
Expand Down Expand Up @@ -1588,7 +1613,7 @@ class PDFPageProxy {
force: true,
});

if (intent.startsWith("oplist-")) {
if (intent & RenderingIntentFlag.OPLIST) {
// Avoid errors below, since the renderTasks are just stubs.
continue;
}
Expand Down
9 changes: 9 additions & 0 deletions src/shared/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ import "./compatibility.js";
const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];

const RenderingIntentFlag = {
ANY: 0x01,
DISPLAY: 0x02,
PRINT: 0x04,
ANNOTATION_FORMS: 0x20,
OPLIST: 0x100,
};

// Permission flags from Table 22, Section 7.6.3.2 of the PDF specification.
const PermissionFlag = {
PRINT: 0x04,
Expand Down Expand Up @@ -1033,6 +1041,7 @@ export {
PasswordResponses,
PermissionFlag,
removeNullCharacters,
RenderingIntentFlag,
setVerbosityLevel,
shadow,
StreamType,
Expand Down
13 changes: 12 additions & 1 deletion test/unit/api_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,12 @@ describe("api", function () {
expect(data.length).toEqual(4);
});

const anyPromise = page
.getAnnotations({ intent: "any" })
.then(function (data) {
expect(data.length).toEqual(4);
});

const displayPromise = page
.getAnnotations({ intent: "display" })
.then(function (data) {
Expand All @@ -1455,7 +1461,12 @@ describe("api", function () {
expect(data.length).toEqual(4);
});

await Promise.all([defaultPromise, displayPromise, printPromise]);
await Promise.all([
defaultPromise,
anyPromise,
displayPromise,
printPromise,
]);
});

it("gets annotations containing relative URLs (bug 766086)", async function () {
Expand Down