Merge pull request #15246 from Snuffleupagus/thumbnail-setImage-improvements

[api-minor] Improve `thumbnail` handling in documents that contain interactive forms
This commit is contained in:
Tim van der Meij 2022-07-31 11:42:55 +02:00 committed by GitHub
commit b8aa9c6221
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 185 additions and 101 deletions

View File

@ -881,7 +881,11 @@ class Annotation {
);
if (!appearance) {
if (!isUsingOwnCanvas) {
return new OperatorList();
return {
opList: new OperatorList(),
separateForm: false,
separateCanvas: false,
};
}
appearance = new StringStream("");
appearance.dict = new Dict();
@ -930,7 +934,7 @@ class Annotation {
opList.addOp(OPS.endMarkedContent, []);
}
this.reset();
return opList;
return { opList, separateForm: false, separateCanvas: isUsingOwnCanvas };
}
async save(evaluator, task, annotationStorage) {
@ -1619,7 +1623,11 @@ class WidgetAnnotation extends Annotation {
// Do not render form elements on the canvas when interactive forms are
// enabled. The display layer is responsible for rendering them instead.
if (renderForms && !(this instanceof SignatureWidgetAnnotation)) {
return new OperatorList();
return {
opList: new OperatorList(),
separateForm: true,
separateCanvas: false,
};
}
if (!this._hasText) {
@ -1647,12 +1655,12 @@ class WidgetAnnotation extends Annotation {
);
}
const operatorList = new OperatorList();
const opList = new OperatorList();
// Even if there is an appearance stream, ignore it. This is the
// behaviour used by Adobe Reader.
if (!this._defaultAppearance || content === null) {
return operatorList;
return { opList, separateForm: false, separateCanvas: false };
}
const matrix = [1, 0, 0, 1, 0, 0];
@ -1672,10 +1680,10 @@ class WidgetAnnotation extends Annotation {
);
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
}
operatorList.addOp(OPS.beginAnnotation, [
opList.addOp(OPS.beginAnnotation, [
this.data.id,
this.data.rect,
transform,
@ -1688,14 +1696,14 @@ class WidgetAnnotation extends Annotation {
stream,
task,
resources: this._fieldResources.mergedResources,
operatorList,
operatorList: opList,
});
operatorList.addOp(OPS.endAnnotation, []);
opList.addOp(OPS.endAnnotation, []);
if (optionalContent !== undefined) {
operatorList.addOp(OPS.endMarkedContent, []);
opList.addOp(OPS.endMarkedContent, []);
}
return operatorList;
return { opList, separateForm: false, separateCanvas: false };
}
_getMKDict(rotation) {
@ -2477,7 +2485,11 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
}
// No appearance
return new OperatorList();
return {
opList: new OperatorList(),
separateForm: false,
separateCanvas: false,
};
}
async save(evaluator, task, annotationStorage) {

View File

@ -455,7 +455,7 @@ class Page {
annotations.length === 0 ||
intent & RenderingIntentFlag.ANNOTATIONS_DISABLE
) {
pageOpList.flush(true);
pageOpList.flush(/* lastChunk = */ true);
return { length: pageOpList.totalLength };
}
const renderForms = !!(intent & RenderingIntentFlag.ANNOTATIONS_FORMS),
@ -493,10 +493,23 @@ class Page {
}
return Promise.all(opListPromises).then(function (opLists) {
for (const opList of opLists) {
let form = false,
canvas = false;
for (const { opList, separateForm, separateCanvas } of opLists) {
pageOpList.addOpList(opList);
if (separateForm) {
form = separateForm;
}
if (separateCanvas) {
canvas = separateCanvas;
}
}
pageOpList.flush(true);
pageOpList.flush(
/* lastChunk = */ true,
/* separateAnnots = */ { form, canvas }
);
return { length: pageOpList.totalLength };
});
});

View File

@ -690,7 +690,7 @@ class OperatorList {
return transfers;
}
flush(lastChunk = false) {
flush(lastChunk = false, separateAnnots = null) {
this.optimizer.flush();
const length = this.length;
this._totalLength += length;
@ -700,6 +700,7 @@ class OperatorList {
fnArray: this.fnArray,
argsArray: this.argsArray,
lastChunk,
separateAnnots,
length,
},
1,

View File

@ -1477,6 +1477,7 @@ class PDFPageProxy {
fnArray: [],
argsArray: [],
lastChunk: false,
separateAnnots: null,
};
if (this._stats) {
@ -1599,6 +1600,7 @@ class PDFPageProxy {
fnArray: [],
argsArray: [],
lastChunk: false,
separateAnnots: null,
};
if (this._stats) {
@ -1795,6 +1797,7 @@ class PDFPageProxy {
intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
}
intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
intentState.operatorList.separateAnnots = operatorListChunk.separateAnnots;
// Notify all the rendering tasks there are more operators to be consumed.
for (const internalRenderTask of intentState.renderTasks) {
@ -3194,8 +3197,10 @@ class PDFObjects {
* Allows controlling of the rendering tasks.
*/
class RenderTask {
#internalRenderTask = null;
constructor(internalRenderTask) {
this._internalRenderTask = internalRenderTask;
this.#internalRenderTask = internalRenderTask;
/**
* Callback for incremental rendering -- a function that will be called
@ -3211,7 +3216,7 @@ class RenderTask {
* @type {Promise<void>}
*/
get promise() {
return this._internalRenderTask.capability.promise;
return this.#internalRenderTask.capability.promise;
}
/**
@ -3220,7 +3225,23 @@ class RenderTask {
* this object extends will be rejected when cancelled.
*/
cancel() {
this._internalRenderTask.cancel();
this.#internalRenderTask.cancel();
}
/**
* Whether form fields are rendered separately from the main operatorList.
* @type {boolean}
*/
get separateAnnots() {
const { separateAnnots } = this.#internalRenderTask.operatorList;
if (!separateAnnots) {
return false;
}
const { annotationCanvasMap } = this.#internalRenderTask;
return (
separateAnnots.form ||
(separateAnnots.canvas && annotationCanvasMap?.size > 0)
);
}
}

View File

@ -1682,29 +1682,27 @@ describe("annotation", function () {
);
const annotationStorage = new Map();
const operatorList = await annotation.getOperatorList(
const { opList } = await annotation.getOperatorList(
partialEvaluator,
task,
RenderingIntentFlag.PRINT,
false,
annotationStorage
);
expect(operatorList.argsArray.length).toEqual(3);
expect(operatorList.fnArray).toEqual([
expect(opList.argsArray.length).toEqual(3);
expect(opList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setFillRGBColor,
OPS.endAnnotation,
]);
expect(operatorList.argsArray[0]).toEqual([
expect(opList.argsArray[0]).toEqual([
"271R",
[0, 0, 32, 10],
[32, 0, 0, 10, 0, 0],
[1, 0, 0, 1, 0, 0],
false,
]);
expect(operatorList.argsArray[1]).toEqual(
new Uint8ClampedArray([26, 51, 76])
);
expect(opList.argsArray[1]).toEqual(new Uint8ClampedArray([26, 51, 76]));
});
it("should render auto-sized text for printing", async function () {
@ -2369,29 +2367,29 @@ describe("annotation", function () {
const annotationStorage = new Map();
annotationStorage.set(annotation.data.id, { value: true });
const operatorList = await annotation.getOperatorList(
const { opList } = await annotation.getOperatorList(
checkboxEvaluator,
task,
RenderingIntentFlag.PRINT,
false,
annotationStorage
);
expect(operatorList.argsArray.length).toEqual(5);
expect(operatorList.fnArray).toEqual([
expect(opList.argsArray.length).toEqual(5);
expect(opList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.dependency,
OPS.setFont,
OPS.showText,
OPS.endAnnotation,
]);
expect(operatorList.argsArray[0]).toEqual([
expect(opList.argsArray[0]).toEqual([
"124R",
[0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 0],
false,
]);
expect(operatorList.argsArray[3][0][0].unicode).toEqual("4");
expect(opList.argsArray[3][0][0].unicode).toEqual("4");
});
it("should render checkboxes for printing", async function () {
@ -2430,55 +2428,51 @@ describe("annotation", function () {
const annotationStorage = new Map();
annotationStorage.set(annotation.data.id, { value: true });
let operatorList = await annotation.getOperatorList(
const { opList: opList1 } = await annotation.getOperatorList(
partialEvaluator,
task,
RenderingIntentFlag.PRINT,
false,
annotationStorage
);
expect(operatorList.argsArray.length).toEqual(3);
expect(operatorList.fnArray).toEqual([
expect(opList1.argsArray.length).toEqual(3);
expect(opList1.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setFillRGBColor,
OPS.endAnnotation,
]);
expect(operatorList.argsArray[0]).toEqual([
expect(opList1.argsArray[0]).toEqual([
"124R",
[0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 0],
false,
]);
expect(operatorList.argsArray[1]).toEqual(
new Uint8ClampedArray([26, 51, 76])
);
expect(opList1.argsArray[1]).toEqual(new Uint8ClampedArray([26, 51, 76]));
annotationStorage.set(annotation.data.id, { value: false });
operatorList = await annotation.getOperatorList(
const { opList: opList2 } = await annotation.getOperatorList(
partialEvaluator,
task,
RenderingIntentFlag.PRINT,
false,
annotationStorage
);
expect(operatorList.argsArray.length).toEqual(3);
expect(operatorList.fnArray).toEqual([
expect(opList2.argsArray.length).toEqual(3);
expect(opList2.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setFillRGBColor,
OPS.endAnnotation,
]);
expect(operatorList.argsArray[0]).toEqual([
expect(opList2.argsArray[0]).toEqual([
"124R",
[0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 0],
false,
]);
expect(operatorList.argsArray[1]).toEqual(
new Uint8ClampedArray([76, 51, 26])
);
expect(opList2.argsArray[1]).toEqual(new Uint8ClampedArray([76, 51, 26]));
});
it("should render checkboxes for printing twice", async function () {
@ -2520,27 +2514,27 @@ describe("annotation", function () {
for (let i = 0; i < 2; i++) {
annotationStorage.set(annotation.data.id, { value: true });
const operatorList = await annotation.getOperatorList(
const { opList } = await annotation.getOperatorList(
partialEvaluator,
task,
RenderingIntentFlag.PRINT,
false,
annotationStorage
);
expect(operatorList.argsArray.length).toEqual(3);
expect(operatorList.fnArray).toEqual([
expect(opList.argsArray.length).toEqual(3);
expect(opList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setFillRGBColor,
OPS.endAnnotation,
]);
expect(operatorList.argsArray[0]).toEqual([
expect(opList.argsArray[0]).toEqual([
"1249R",
[0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 0],
false,
]);
expect(operatorList.argsArray[1]).toEqual(
expect(opList.argsArray[1]).toEqual(
new Uint8ClampedArray([26, 51, 76])
);
}
@ -2582,29 +2576,27 @@ describe("annotation", function () {
);
const annotationStorage = new Map();
const operatorList = await annotation.getOperatorList(
const { opList } = await annotation.getOperatorList(
partialEvaluator,
task,
RenderingIntentFlag.PRINT,
false,
annotationStorage
);
expect(operatorList.argsArray.length).toEqual(3);
expect(operatorList.fnArray).toEqual([
expect(opList.argsArray.length).toEqual(3);
expect(opList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setFillRGBColor,
OPS.endAnnotation,
]);
expect(operatorList.argsArray[0]).toEqual([
expect(opList.argsArray[0]).toEqual([
"124R",
[0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 0],
false,
]);
expect(operatorList.argsArray[1]).toEqual(
new Uint8ClampedArray([26, 51, 76])
);
expect(opList.argsArray[1]).toEqual(new Uint8ClampedArray([26, 51, 76]));
});
it("should save checkboxes", async function () {
@ -2838,55 +2830,51 @@ describe("annotation", function () {
const annotationStorage = new Map();
annotationStorage.set(annotation.data.id, { value: true });
let operatorList = await annotation.getOperatorList(
const { opList: opList1 } = await annotation.getOperatorList(
partialEvaluator,
task,
RenderingIntentFlag.PRINT,
false,
annotationStorage
);
expect(operatorList.argsArray.length).toEqual(3);
expect(operatorList.fnArray).toEqual([
expect(opList1.argsArray.length).toEqual(3);
expect(opList1.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setFillRGBColor,
OPS.endAnnotation,
]);
expect(operatorList.argsArray[0]).toEqual([
expect(opList1.argsArray[0]).toEqual([
"124R",
[0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 0],
false,
]);
expect(operatorList.argsArray[1]).toEqual(
new Uint8ClampedArray([26, 51, 76])
);
expect(opList1.argsArray[1]).toEqual(new Uint8ClampedArray([26, 51, 76]));
annotationStorage.set(annotation.data.id, { value: false });
operatorList = await annotation.getOperatorList(
const { opList: opList2 } = await annotation.getOperatorList(
partialEvaluator,
task,
RenderingIntentFlag.PRINT,
false,
annotationStorage
);
expect(operatorList.argsArray.length).toEqual(3);
expect(operatorList.fnArray).toEqual([
expect(opList2.argsArray.length).toEqual(3);
expect(opList2.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setFillRGBColor,
OPS.endAnnotation,
]);
expect(operatorList.argsArray[0]).toEqual([
expect(opList2.argsArray[0]).toEqual([
"124R",
[0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 0],
false,
]);
expect(operatorList.argsArray[1]).toEqual(
new Uint8ClampedArray([76, 51, 26])
);
expect(opList2.argsArray[1]).toEqual(new Uint8ClampedArray([76, 51, 26]));
});
it("should render radio buttons for printing using normal appearance", async function () {
@ -2926,29 +2914,27 @@ describe("annotation", function () {
);
const annotationStorage = new Map();
const operatorList = await annotation.getOperatorList(
const { opList } = await annotation.getOperatorList(
partialEvaluator,
task,
RenderingIntentFlag.PRINT,
false,
annotationStorage
);
expect(operatorList.argsArray.length).toEqual(3);
expect(operatorList.fnArray).toEqual([
expect(opList.argsArray.length).toEqual(3);
expect(opList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setFillRGBColor,
OPS.endAnnotation,
]);
expect(operatorList.argsArray[0]).toEqual([
expect(opList.argsArray[0]).toEqual([
"124R",
[0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 0],
false,
]);
expect(operatorList.argsArray[1]).toEqual(
new Uint8ClampedArray([76, 51, 26])
);
expect(opList.argsArray[1]).toEqual(new Uint8ClampedArray([76, 51, 26]));
});
it("should save radio buttons", async function () {
@ -4087,7 +4073,7 @@ describe("annotation", function () {
])
)[0];
const operatorList = await freetextAnnotation.getOperatorList(
const { opList } = await freetextAnnotation.getOperatorList(
partialEvaluator,
task,
RenderingIntentFlag.PRINT,
@ -4095,8 +4081,8 @@ describe("annotation", function () {
null
);
expect(operatorList.fnArray.length).toEqual(16);
expect(operatorList.fnArray).toEqual([
expect(opList.fnArray.length).toEqual(16);
expect(opList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.save,
OPS.constructPath,
@ -4322,7 +4308,7 @@ describe("annotation", function () {
])
)[0];
const operatorList = await inkAnnotation.getOperatorList(
const { opList } = await inkAnnotation.getOperatorList(
partialEvaluator,
task,
RenderingIntentFlag.PRINT,
@ -4330,8 +4316,8 @@ describe("annotation", function () {
null
);
expect(operatorList.argsArray.length).toEqual(8);
expect(operatorList.fnArray).toEqual([
expect(opList.argsArray.length).toEqual(8);
expect(opList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setLineWidth,
OPS.setLineCap,
@ -4343,20 +4329,18 @@ describe("annotation", function () {
]);
// Linewidth.
expect(operatorList.argsArray[1]).toEqual([3]);
expect(opList.argsArray[1]).toEqual([3]);
// LineCap.
expect(operatorList.argsArray[2]).toEqual([1]);
expect(opList.argsArray[2]).toEqual([1]);
// LineJoin.
expect(operatorList.argsArray[3]).toEqual([1]);
expect(opList.argsArray[3]).toEqual([1]);
// Color.
expect(operatorList.argsArray[4]).toEqual(
new Uint8ClampedArray([0, 255, 0])
);
expect(opList.argsArray[4]).toEqual(new Uint8ClampedArray([0, 255, 0]));
// Path.
expect(operatorList.argsArray[5][0]).toEqual([OPS.moveTo, OPS.curveTo]);
expect(operatorList.argsArray[5][1]).toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
expect(opList.argsArray[5][0]).toEqual([OPS.moveTo, OPS.curveTo]);
expect(opList.argsArray[5][1]).toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
// Min-max.
expect(operatorList.argsArray[5][2]).toEqual([1, 1, 2, 2]);
expect(opList.argsArray[5][2]).toEqual([1, 1, 2, 2]);
});
});

View File

@ -501,6 +501,7 @@ describe("api", function () {
expect(opList.fnArray.length).toEqual(0);
expect(opList.argsArray.length).toEqual(0);
expect(opList.lastChunk).toEqual(true);
expect(opList.separateAnnots).toEqual(null);
await loadingTask.destroy();
});
@ -521,6 +522,7 @@ describe("api", function () {
expect(opList.fnArray.length).toEqual(0);
expect(opList.argsArray.length).toEqual(0);
expect(opList.lastChunk).toEqual(true);
expect(opList.separateAnnots).toEqual(null);
await loadingTask.destroy();
});
@ -588,6 +590,7 @@ describe("api", function () {
expect(opList.fnArray.length).toBeGreaterThan(5);
expect(opList.argsArray.length).toBeGreaterThan(5);
expect(opList.lastChunk).toEqual(true);
expect(opList.separateAnnots).toEqual(null);
try {
await pdfDocument2.getPage(1);
@ -631,6 +634,7 @@ describe("api", function () {
expect(opList.fnArray.length).toBeGreaterThan(5);
expect(opList.argsArray.length).toBeGreaterThan(5);
expect(opList.lastChunk).toEqual(true);
expect(opList.separateAnnots).toEqual(null);
}
await Promise.all([loadingTask1.destroy(), loadingTask2.destroy()]);
@ -2402,6 +2406,10 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
expect(operatorList.fnArray.length).toBeGreaterThan(100);
expect(operatorList.argsArray.length).toBeGreaterThan(100);
expect(operatorList.lastChunk).toEqual(true);
expect(operatorList.separateAnnots).toEqual({
form: false,
canvas: false,
});
});
it("gets operatorList with JPEG image (issue 4888)", async function () {
@ -2442,6 +2450,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
expect(opList.fnArray.length).toBeGreaterThan(100);
expect(opList.argsArray.length).toBeGreaterThan(100);
expect(opList.lastChunk).toEqual(true);
expect(opList.separateAnnots).toEqual(null);
return loadingTask1.destroy();
});
@ -2454,6 +2463,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
expect(opList.fnArray.length).toEqual(0);
expect(opList.argsArray.length).toEqual(0);
expect(opList.lastChunk).toEqual(true);
expect(opList.separateAnnots).toEqual(null);
return loadingTask2.destroy();
});
@ -2475,6 +2485,10 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
expect(operatorList.fnArray.length).toBeGreaterThan(20);
expect(operatorList.argsArray.length).toBeGreaterThan(20);
expect(operatorList.lastChunk).toEqual(true);
expect(operatorList.separateAnnots).toEqual({
form: false,
canvas: false,
});
// The `getOperatorList` method, similar to the `render` method,
// is supposed to include any existing Annotation-operatorLists.
@ -2498,6 +2512,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
expect(opListAnnotDisable.fnArray.length).toEqual(0);
expect(opListAnnotDisable.argsArray.length).toEqual(0);
expect(opListAnnotDisable.lastChunk).toEqual(true);
expect(opListAnnotDisable.separateAnnots).toEqual(null);
const opListAnnotEnable = await pdfPage.getOperatorList({
annotationMode: AnnotationMode.ENABLE,
@ -2505,6 +2520,10 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
expect(opListAnnotEnable.fnArray.length).toBeGreaterThan(140);
expect(opListAnnotEnable.argsArray.length).toBeGreaterThan(140);
expect(opListAnnotEnable.lastChunk).toEqual(true);
expect(opListAnnotEnable.separateAnnots).toEqual({
form: false,
canvas: true,
});
let firstAnnotIndex = opListAnnotEnable.fnArray.indexOf(
OPS.beginAnnotation
@ -2518,6 +2537,10 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
expect(opListAnnotEnableForms.fnArray.length).toBeGreaterThan(30);
expect(opListAnnotEnableForms.argsArray.length).toBeGreaterThan(30);
expect(opListAnnotEnableForms.lastChunk).toEqual(true);
expect(opListAnnotEnableForms.separateAnnots).toEqual({
form: true,
canvas: true,
});
firstAnnotIndex = opListAnnotEnableForms.fnArray.indexOf(
OPS.beginAnnotation
@ -2531,6 +2554,10 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
expect(opListAnnotEnableStorage.fnArray.length).toBeGreaterThan(170);
expect(opListAnnotEnableStorage.argsArray.length).toBeGreaterThan(170);
expect(opListAnnotEnableStorage.lastChunk).toEqual(true);
expect(opListAnnotEnableStorage.separateAnnots).toEqual({
form: false,
canvas: true,
});
firstAnnotIndex = opListAnnotEnableStorage.fnArray.indexOf(
OPS.beginAnnotation
@ -2635,8 +2662,9 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
expect(renderTask instanceof RenderTask).toEqual(true);
await renderTask.promise;
const stats = pdfPage.stats;
expect(renderTask.separateAnnots).toEqual(false);
const { stats } = pdfPage;
expect(stats instanceof StatTimer).toEqual(true);
expect(stats.times.length).toEqual(3);
@ -2719,6 +2747,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
expect(reRenderTask instanceof RenderTask).toEqual(true);
await reRenderTask.promise;
expect(reRenderTask.separateAnnots).toEqual(false);
CanvasFactory.destroy(canvasAndCtx);
});
@ -2785,8 +2814,9 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
expect(renderTask instanceof RenderTask).toEqual(true);
await renderTask.promise;
await pdfDoc.cleanup();
expect(renderTask.separateAnnots).toEqual(false);
await pdfDoc.cleanup();
expect(true).toEqual(true);
CanvasFactory.destroy(canvasAndCtx);
@ -2831,6 +2861,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
);
}
await renderTask.promise;
expect(renderTask.separateAnnots).toEqual(false);
CanvasFactory.destroy(canvasAndCtx);
await loadingTask.destroy();
@ -2918,6 +2949,8 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
});
await renderTask.promise;
expect(renderTask.separateAnnots).toEqual(false);
const printData = canvasAndCtx.canvas.toDataURL();
CanvasFactory.destroy(canvasAndCtx);
@ -3002,6 +3035,8 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
viewport,
});
await renderTask.promise;
expect(renderTask.separateAnnots).toEqual(false);
const data = canvasAndCtx.canvas.toDataURL();
CanvasFactory.destroy(canvasAndCtx);
return data;

View File

@ -99,7 +99,10 @@ const MAX_CANVAS_PIXELS = compatibilityParams.maxCanvasPixels || 16777216;
class PDFPageView {
#annotationMode = AnnotationMode.ENABLE_FORMS;
#useThumbnailCanvas = true;
#useThumbnailCanvas = {
initialOptionalContent: true,
regularAnnotations: true,
};
/**
* @param {PDFPageViewOptions} options
@ -190,14 +193,15 @@ class PDFPageView {
const { optionalContentConfigPromise } = options;
if (optionalContentConfigPromise) {
// Ensure that the thumbnails always display the *initial* document
// state.
// state, for documents with optional content.
optionalContentConfigPromise.then(optionalContentConfig => {
if (
optionalContentConfigPromise !== this._optionalContentConfigPromise
) {
return;
}
this.#useThumbnailCanvas = optionalContentConfig.hasInitialVisibility;
this.#useThumbnailCanvas.initialOptionalContent =
optionalContentConfig.hasInitialVisibility;
});
}
}
@ -408,14 +412,16 @@ class PDFPageView {
if (optionalContentConfigPromise instanceof Promise) {
this._optionalContentConfigPromise = optionalContentConfigPromise;
// Ensure that the thumbnails always display the *initial* document state.
// Ensure that the thumbnails always display the *initial* document state,
// for documents with optional content.
optionalContentConfigPromise.then(optionalContentConfig => {
if (
optionalContentConfigPromise !== this._optionalContentConfigPromise
) {
return;
}
this.#useThumbnailCanvas = optionalContentConfig.hasInitialVisibility;
this.#useThumbnailCanvas.initialOptionalContent =
optionalContentConfig.hasInitialVisibility;
});
}
@ -772,6 +778,10 @@ class PDFPageView {
}
this._resetZoomLayer(/* removeFromDOM = */ true);
// Ensure that the thumbnails won't become partially (or fully) blank,
// for documents that contain interactive form elements.
this.#useThumbnailCanvas.regularAnnotations = !paintTask.separateAnnots;
this.eventBus.dispatch("pagerendered", {
source: this,
pageNumber: this.id,
@ -888,6 +898,9 @@ class PDFPageView {
cancel() {
renderTask.cancel();
},
get separateAnnots() {
return renderTask.separateAnnots;
},
};
const viewport = this.viewport;
@ -1029,6 +1042,9 @@ class PDFPageView {
cancel() {
cancelled = true;
},
get separateAnnots() {
return false;
},
};
}
@ -1050,7 +1066,9 @@ class PDFPageView {
* @ignore
*/
get thumbnailCanvas() {
return this.#useThumbnailCanvas ? this.canvas : null;
const { initialOptionalContent, regularAnnotations } =
this.#useThumbnailCanvas;
return initialOptionalContent && regularAnnotations ? this.canvas : null;
}
}