mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-20 15:18:08 +02:00
[api-minor] Introduce a PrintAnnotationStorage
with *frozen* serializable data
Given that printing is triggered *synchronously* in browsers, it's thus possible for scripting (in PDF documents) to modify the Annotation-data while printing is currently ongoing. To work-around that we add a new printing-specific `AnnotationStorage`, where the serializable data is *frozen* upon initialization, which the viewer can thus create/utilize during printing.
This commit is contained in:
parent
c5dc082da4
commit
1cc7cecc7b
6 changed files with 196 additions and 41 deletions
22
web/app.js
22
web/app.js
|
@ -254,6 +254,7 @@ const PDFViewerApplication = {
|
|||
_wheelUnusedTicks: 0,
|
||||
_idleCallbacks: new Set(),
|
||||
_PDFBug: null,
|
||||
_printAnnotationStoragePromise: null,
|
||||
|
||||
// Called once when the document is loaded.
|
||||
async initialize(appConfig) {
|
||||
|
@ -1790,9 +1791,14 @@ const PDFViewerApplication = {
|
|||
},
|
||||
|
||||
beforePrint() {
|
||||
// Given that the "beforeprint" browser event is synchronous, we
|
||||
// unfortunately cannot await the scripting event dispatching here.
|
||||
this.pdfScriptingManager.dispatchWillPrint();
|
||||
this._printAnnotationStoragePromise = this.pdfScriptingManager
|
||||
.dispatchWillPrint()
|
||||
.catch(() => {
|
||||
/* Avoid breaking printing; ignoring errors. */
|
||||
})
|
||||
.then(() => {
|
||||
return this.pdfDocument?.annotationStorage.print;
|
||||
});
|
||||
|
||||
if (this.printService) {
|
||||
// There is no way to suppress beforePrint/afterPrint events,
|
||||
|
@ -1830,6 +1836,7 @@ const PDFViewerApplication = {
|
|||
printContainer,
|
||||
printResolution,
|
||||
optionalContentConfigPromise,
|
||||
this._printAnnotationStoragePromise,
|
||||
this.l10n
|
||||
);
|
||||
this.printService = printService;
|
||||
|
@ -1843,9 +1850,12 @@ const PDFViewerApplication = {
|
|||
},
|
||||
|
||||
afterPrint() {
|
||||
// Given that the "afterprint" browser event is synchronous, we
|
||||
// unfortunately cannot await the scripting event dispatching here.
|
||||
this.pdfScriptingManager.dispatchDidPrint();
|
||||
if (this._printAnnotationStoragePromise) {
|
||||
this._printAnnotationStoragePromise.then(() => {
|
||||
this.pdfScriptingManager.dispatchDidPrint();
|
||||
});
|
||||
this._printAnnotationStoragePromise = null;
|
||||
}
|
||||
|
||||
if (this.printService) {
|
||||
this.printService.destroy();
|
||||
|
|
|
@ -29,7 +29,8 @@ function composePage(
|
|||
size,
|
||||
printContainer,
|
||||
printResolution,
|
||||
optionalContentConfigPromise
|
||||
optionalContentConfigPromise,
|
||||
printAnnotationStoragePromise
|
||||
) {
|
||||
const canvas = document.createElement("canvas");
|
||||
|
||||
|
@ -61,9 +62,12 @@ function composePage(
|
|||
ctx.restore();
|
||||
|
||||
let thisRenderTask = null;
|
||||
pdfDocument
|
||||
.getPage(pageNumber)
|
||||
.then(function (pdfPage) {
|
||||
|
||||
Promise.all([
|
||||
pdfDocument.getPage(pageNumber),
|
||||
printAnnotationStoragePromise,
|
||||
])
|
||||
.then(function ([pdfPage, printAnnotationStorage]) {
|
||||
if (currentRenderTask) {
|
||||
currentRenderTask.cancel();
|
||||
currentRenderTask = null;
|
||||
|
@ -75,6 +79,7 @@ function composePage(
|
|||
intent: "print",
|
||||
annotationMode: AnnotationMode.ENABLE_STORAGE,
|
||||
optionalContentConfigPromise,
|
||||
printAnnotationStorage,
|
||||
};
|
||||
currentRenderTask = thisRenderTask = pdfPage.render(renderContext);
|
||||
return thisRenderTask.promise;
|
||||
|
@ -114,7 +119,8 @@ function FirefoxPrintService(
|
|||
pagesOverview,
|
||||
printContainer,
|
||||
printResolution,
|
||||
optionalContentConfigPromise = null
|
||||
optionalContentConfigPromise = null,
|
||||
printAnnotationStoragePromise = null
|
||||
) {
|
||||
this.pdfDocument = pdfDocument;
|
||||
this.pagesOverview = pagesOverview;
|
||||
|
@ -122,6 +128,8 @@ function FirefoxPrintService(
|
|||
this._printResolution = printResolution || 150;
|
||||
this._optionalContentConfigPromise =
|
||||
optionalContentConfigPromise || pdfDocument.getOptionalContentConfig();
|
||||
this._optionalContentConfigPromise =
|
||||
printAnnotationStoragePromise || Promise.resolve();
|
||||
}
|
||||
|
||||
FirefoxPrintService.prototype = {
|
||||
|
@ -132,6 +140,7 @@ FirefoxPrintService.prototype = {
|
|||
printContainer,
|
||||
_printResolution,
|
||||
_optionalContentConfigPromise,
|
||||
_printAnnotationStoragePromise,
|
||||
} = this;
|
||||
|
||||
const body = document.querySelector("body");
|
||||
|
@ -149,7 +158,8 @@ FirefoxPrintService.prototype = {
|
|||
pagesOverview[i],
|
||||
printContainer,
|
||||
_printResolution,
|
||||
_optionalContentConfigPromise
|
||||
_optionalContentConfigPromise,
|
||||
_printAnnotationStoragePromise
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -175,14 +185,16 @@ PDFPrintServiceFactory.instance = {
|
|||
pagesOverview,
|
||||
printContainer,
|
||||
printResolution,
|
||||
optionalContentConfigPromise
|
||||
optionalContentConfigPromise,
|
||||
printAnnotationStoragePromise
|
||||
) {
|
||||
return new FirefoxPrintService(
|
||||
pdfDocument,
|
||||
pagesOverview,
|
||||
printContainer,
|
||||
printResolution,
|
||||
optionalContentConfigPromise
|
||||
optionalContentConfigPromise,
|
||||
printAnnotationStoragePromise
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -29,7 +29,8 @@ function renderPage(
|
|||
pageNumber,
|
||||
size,
|
||||
printResolution,
|
||||
optionalContentConfigPromise
|
||||
optionalContentConfigPromise,
|
||||
printAnnotationStoragePromise
|
||||
) {
|
||||
const scratchCanvas = activeService.scratchCanvas;
|
||||
|
||||
|
@ -44,7 +45,10 @@ function renderPage(
|
|||
ctx.fillRect(0, 0, scratchCanvas.width, scratchCanvas.height);
|
||||
ctx.restore();
|
||||
|
||||
return pdfDocument.getPage(pageNumber).then(function (pdfPage) {
|
||||
return Promise.all([
|
||||
pdfDocument.getPage(pageNumber),
|
||||
printAnnotationStoragePromise,
|
||||
]).then(function ([pdfPage, printAnnotationStorage]) {
|
||||
const renderContext = {
|
||||
canvasContext: ctx,
|
||||
transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
|
||||
|
@ -52,6 +56,7 @@ function renderPage(
|
|||
intent: "print",
|
||||
annotationMode: AnnotationMode.ENABLE_STORAGE,
|
||||
optionalContentConfigPromise,
|
||||
printAnnotationStorage,
|
||||
};
|
||||
return pdfPage.render(renderContext).promise;
|
||||
});
|
||||
|
@ -63,6 +68,7 @@ function PDFPrintService(
|
|||
printContainer,
|
||||
printResolution,
|
||||
optionalContentConfigPromise = null,
|
||||
printAnnotationStoragePromise = null,
|
||||
l10n
|
||||
) {
|
||||
this.pdfDocument = pdfDocument;
|
||||
|
@ -71,6 +77,8 @@ function PDFPrintService(
|
|||
this._printResolution = printResolution || 150;
|
||||
this._optionalContentConfigPromise =
|
||||
optionalContentConfigPromise || pdfDocument.getOptionalContentConfig();
|
||||
this._printAnnotationStoragePromise =
|
||||
printAnnotationStoragePromise || Promise.resolve();
|
||||
this.l10n = l10n;
|
||||
this.currentPage = -1;
|
||||
// The temporary canvas where renderPage paints one page at a time.
|
||||
|
@ -160,7 +168,8 @@ PDFPrintService.prototype = {
|
|||
/* pageNumber = */ index + 1,
|
||||
this.pagesOverview[index],
|
||||
this._printResolution,
|
||||
this._optionalContentConfigPromise
|
||||
this._optionalContentConfigPromise,
|
||||
this._printAnnotationStoragePromise
|
||||
)
|
||||
.then(this.useRenderedPage.bind(this))
|
||||
.then(function () {
|
||||
|
@ -359,6 +368,7 @@ PDFPrintServiceFactory.instance = {
|
|||
printContainer,
|
||||
printResolution,
|
||||
optionalContentConfigPromise,
|
||||
printAnnotationStoragePromise,
|
||||
l10n
|
||||
) {
|
||||
if (activeService) {
|
||||
|
@ -370,6 +380,7 @@ PDFPrintServiceFactory.instance = {
|
|||
printContainer,
|
||||
printResolution,
|
||||
optionalContentConfigPromise,
|
||||
printAnnotationStoragePromise,
|
||||
l10n
|
||||
);
|
||||
return activeService;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue