diff --git a/src/display/api.js b/src/display/api.js index a27a2b500..2cf8f9ad2 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -743,8 +743,10 @@ class PDFDocumentProxy { } /** + * NOTE: This is (mostly) intended to support printing of XFA forms. + * * @type {Object | null} An object representing a HTML tree structure - * to render the XFA, or `null` when no XFA form exists. + * to render the XFA, or `null` when no XFA form exists. */ get allXfaHtml() { return this._transport._htmlForXfa; diff --git a/src/display/display_utils.js b/src/display/display_utils.js index fbf9a5e69..e4cc62085 100644 --- a/src/display/display_utils.js +++ b/src/display/display_utils.js @@ -606,6 +606,20 @@ class PDFDateString { } } +/** + * NOTE: This is (mostly) intended to support printing of XFA forms. + */ +function getXfaPageViewport(xfaPage, { scale = 1, rotation = 0 }) { + const { width, height } = xfaPage.attributes.style; + const viewBox = [0, 0, parseInt(width), parseInt(height)]; + + return new PageViewport({ + viewBox, + scale, + rotation, + }); +} + export { addLinkAttributes, DEFAULT_LINK_REL, @@ -616,6 +630,7 @@ export { DOMSVGFactory, getFilenameFromUrl, getPdfFilenameFromUrl, + getXfaPageViewport, isDataScheme, isPdfFile, isValidFetchUrl, diff --git a/src/display/xfa_layer.js b/src/display/xfa_layer.js index 5b3e16005..cd068b92d 100644 --- a/src/display/xfa_layer.js +++ b/src/display/xfa_layer.js @@ -13,8 +13,6 @@ * limitations under the License. */ -import { PageViewport } from "./display_utils.js"; - class XfaLayer { static setupStorage(html, fieldId, element, storage, intent) { const storedData = storage.getValue(fieldId, { value: null }); @@ -134,13 +132,8 @@ class XfaLayer { const rootDiv = parameters.div; rootDiv.appendChild(rootHtml); - - let { viewport } = parameters; - if (!(viewport instanceof PageViewport)) { - viewport = new PageViewport(viewport); - } - const coeffs = viewport.transform.join(","); - rootDiv.style.transform = `matrix(${coeffs})`; + const transform = `matrix(${parameters.viewport.transform.join(",")})`; + rootDiv.style.transform = transform; // Set defaults. rootDiv.setAttribute("class", "xfaLayer xfaFont"); diff --git a/src/pdf.js b/src/pdf.js index b5d4d38d1..9a1bfce30 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -18,6 +18,7 @@ import { addLinkAttributes, getFilenameFromUrl, getPdfFilenameFromUrl, + getXfaPageViewport, isPdfFile, isValidFetchUrl, LinkTarget, @@ -108,6 +109,7 @@ export { loadScript, PDFDateString, RenderingCancelledException, + getXfaPageViewport, // From "./display/api.js": build, getDocument, diff --git a/web/firefox_print_service.js b/web/firefox_print_service.js index d4b1e16cd..5fb6dba4e 100644 --- a/web/firefox_print_service.js +++ b/web/firefox_print_service.js @@ -14,7 +14,7 @@ */ import { RenderingCancelledException, shadow } from "pdfjs-lib"; -import { getXfaHtmlForPrinting } from "./ui_utils.js"; +import { getXfaHtmlForPrinting } from "./print_utils.js"; import { PDFPrintServiceFactory } from "./app.js"; // Creates a placeholder with div and canvas with right size for the page. diff --git a/web/pdf_print_service.js b/web/pdf_print_service.js index a74ca3374..592607fb3 100644 --- a/web/pdf_print_service.js +++ b/web/pdf_print_service.js @@ -14,7 +14,7 @@ */ import { PDFPrintServiceFactory, PDFViewerApplication } from "./app.js"; -import { getXfaHtmlForPrinting } from "./ui_utils.js"; +import { getXfaHtmlForPrinting } from "./print_utils.js"; import { viewerCompatibilityParams } from "./viewer_compatibility.js"; let activeService = null; diff --git a/web/print_utils.js b/web/print_utils.js new file mode 100644 index 000000000..3c1d8c85f --- /dev/null +++ b/web/print_utils.js @@ -0,0 +1,42 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CSS_UNITS } from "./ui_utils.js"; +import { DefaultXfaLayerFactory } from "./xfa_layer_builder.js"; +import { getXfaPageViewport } from "pdfjs-lib"; + +function getXfaHtmlForPrinting(printContainer, pdfDocument) { + const xfaHtml = pdfDocument.allXfaHtml; + const factory = new DefaultXfaLayerFactory(); + const scale = Math.round(CSS_UNITS * 100) / 100; + + for (const xfaPage of xfaHtml.children) { + const page = document.createElement("div"); + page.className = "xfaPrintedPage"; + printContainer.appendChild(page); + + const builder = factory.createXfaLayerBuilder( + /* pageDiv = */ page, + /* pdfPage = */ null, + /* annotationStorage = */ pdfDocument.annotationStorage, + /* xfaHtml = */ xfaPage + ); + const viewport = getXfaPageViewport(xfaPage, { scale }); + + builder.render(viewport, "print"); + } +} + +export { getXfaHtmlForPrinting }; diff --git a/web/ui_utils.js b/web/ui_utils.js index e93511211..672c56f69 100644 --- a/web/ui_utils.js +++ b/web/ui_utils.js @@ -13,8 +13,6 @@ * limitations under the License. */ -import { DefaultXfaLayerFactory } from "./xfa_layer_builder.js"; - const CSS_UNITS = 96.0 / 72.0; const DEFAULT_SCALE_VALUE = "auto"; const DEFAULT_SCALE = 1.0; @@ -995,29 +993,6 @@ function apiPageModeToSidebarView(mode) { return SidebarView.NONE; // Default value. } -function getXfaHtmlForPrinting(printContainer, pdfDocument) { - const xfaHtml = pdfDocument.allXfaHtml; - const factory = new DefaultXfaLayerFactory(); - const scale = Math.round(CSS_UNITS * 100) / 100; - for (const xfaPage of xfaHtml.children) { - const page = document.createElement("div"); - page.className = "xfaPrintedPage"; - printContainer.appendChild(page); - - const { width, height } = xfaPage.attributes.style; - const viewBox = [0, 0, parseInt(width), parseInt(height)]; - const viewport = { viewBox, scale, rotation: 0 }; - - const builder = factory.createXfaLayerBuilder( - page, - null, - pdfDocument.annotationStorage, - xfaPage - ); - builder.render(viewport, "print"); - } -} - export { animationStarted, apiPageLayoutToSpreadMode, @@ -1034,7 +1009,6 @@ export { getOutputScale, getPageSizeInches, getVisibleElements, - getXfaHtmlForPrinting, isPortraitOrientation, isValidRotation, isValidScrollMode, diff --git a/web/xfa_layer_builder.js b/web/xfa_layer_builder.js index 99c95c5de..17f891c19 100644 --- a/web/xfa_layer_builder.js +++ b/web/xfa_layer_builder.js @@ -43,56 +43,55 @@ class XfaLayerBuilder { * annotations is complete. */ render(viewport, intent = "display") { - if (intent === "display") { - return this.pdfPage - .getXfa() - .then(xfa => { - if (this._cancelled) { - return; - } - const parameters = { - viewport: viewport.clone({ dontFlip: true }), - div: this.div, - xfa, - page: this.pdfPage, - annotationStorage: this.annotationStorage, - }; + if (intent === "print") { + const parameters = { + viewport: viewport.clone({ dontFlip: true }), + div: this.div, + xfa: this.xfaHtml, + page: null, + annotationStorage: this.annotationStorage, + intent, + }; - if (this.div) { - XfaLayer.update(parameters); - } else { - // Create an xfa layer div and render the form - this.div = document.createElement("div"); - this.pageDiv.appendChild(this.div); - parameters.div = this.div; + // Create an xfa layer div and render the form + const div = document.createElement("div"); + this.pageDiv.appendChild(div); + parameters.div = div; - XfaLayer.render(parameters); - } - }) - .catch(error => { - console.error(error); - }); + XfaLayer.render(parameters); + return Promise.resolve(); } - // intent === "print". - viewport.dontFlip = true; - const parameters = { - viewport, - div: this.div, - xfa: this.xfaHtml, - page: null, - annotationStorage: this.annotationStorage, - intent, - }; + // intent === "display" + return this.pdfPage + .getXfa() + .then(xfa => { + if (this._cancelled) { + return; + } + const parameters = { + viewport: viewport.clone({ dontFlip: true }), + div: this.div, + xfa, + page: this.pdfPage, + annotationStorage: this.annotationStorage, + intent, + }; - // Create an xfa layer div and render the form - const div = document.createElement("div"); - this.pageDiv.appendChild(div); - parameters.div = div; + if (this.div) { + XfaLayer.update(parameters); + } else { + // Create an xfa layer div and render the form + this.div = document.createElement("div"); + this.pageDiv.appendChild(this.div); + parameters.div = this.div; - XfaLayer.render(parameters); - - return null; + XfaLayer.render(parameters); + } + }) + .catch(error => { + console.error(error); + }); } cancel() {