firefox_print_service.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* Copyright 2016 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. import {
  16. AnnotationMode,
  17. PixelsPerInch,
  18. RenderingCancelledException,
  19. shadow,
  20. } from "pdfjs-lib";
  21. import { getXfaHtmlForPrinting } from "./print_utils.js";
  22. import { PDFPrintServiceFactory } from "./app.js";
  23. // Creates a placeholder with div and canvas with right size for the page.
  24. function composePage(
  25. pdfDocument,
  26. pageNumber,
  27. size,
  28. printContainer,
  29. printResolution,
  30. optionalContentConfigPromise,
  31. printAnnotationStoragePromise
  32. ) {
  33. const canvas = document.createElement("canvas");
  34. // The size of the canvas in pixels for printing.
  35. const PRINT_UNITS = printResolution / PixelsPerInch.PDF;
  36. canvas.width = Math.floor(size.width * PRINT_UNITS);
  37. canvas.height = Math.floor(size.height * PRINT_UNITS);
  38. const canvasWrapper = document.createElement("div");
  39. canvasWrapper.className = "printedPage";
  40. canvasWrapper.append(canvas);
  41. printContainer.append(canvasWrapper);
  42. // A callback for a given page may be executed multiple times for different
  43. // print operations (think of changing the print settings in the browser).
  44. //
  45. // Since we don't support queueing multiple render tasks for the same page
  46. // (and it'd be racy anyways if painting the page is not done in one go) we
  47. // keep track of the last scheduled task in order to properly cancel it before
  48. // starting the next one.
  49. let currentRenderTask = null;
  50. canvas.mozPrintCallback = function (obj) {
  51. // Printing/rendering the page.
  52. const ctx = obj.context;
  53. ctx.save();
  54. ctx.fillStyle = "rgb(255, 255, 255)";
  55. ctx.fillRect(0, 0, canvas.width, canvas.height);
  56. ctx.restore();
  57. let thisRenderTask = null;
  58. Promise.all([
  59. pdfDocument.getPage(pageNumber),
  60. printAnnotationStoragePromise,
  61. ])
  62. .then(function ([pdfPage, printAnnotationStorage]) {
  63. if (currentRenderTask) {
  64. currentRenderTask.cancel();
  65. currentRenderTask = null;
  66. }
  67. const renderContext = {
  68. canvasContext: ctx,
  69. transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
  70. viewport: pdfPage.getViewport({ scale: 1, rotation: size.rotation }),
  71. intent: "print",
  72. annotationMode: AnnotationMode.ENABLE_STORAGE,
  73. optionalContentConfigPromise,
  74. printAnnotationStorage,
  75. };
  76. currentRenderTask = thisRenderTask = pdfPage.render(renderContext);
  77. return thisRenderTask.promise;
  78. })
  79. .then(
  80. function () {
  81. // Tell the printEngine that rendering this canvas/page has finished.
  82. if (currentRenderTask === thisRenderTask) {
  83. currentRenderTask = null;
  84. }
  85. obj.done();
  86. },
  87. function (reason) {
  88. if (!(reason instanceof RenderingCancelledException)) {
  89. console.error(reason);
  90. }
  91. if (currentRenderTask === thisRenderTask) {
  92. currentRenderTask.cancel();
  93. currentRenderTask = null;
  94. }
  95. // Tell the printEngine that rendering this canvas/page has failed.
  96. // This will make the print process stop.
  97. if ("abort" in obj) {
  98. obj.abort();
  99. } else {
  100. obj.done();
  101. }
  102. }
  103. );
  104. };
  105. }
  106. function FirefoxPrintService(
  107. pdfDocument,
  108. pagesOverview,
  109. printContainer,
  110. printResolution,
  111. optionalContentConfigPromise = null,
  112. printAnnotationStoragePromise = null
  113. ) {
  114. this.pdfDocument = pdfDocument;
  115. this.pagesOverview = pagesOverview;
  116. this.printContainer = printContainer;
  117. this._printResolution = printResolution || 150;
  118. this._optionalContentConfigPromise =
  119. optionalContentConfigPromise || pdfDocument.getOptionalContentConfig();
  120. this._printAnnotationStoragePromise =
  121. printAnnotationStoragePromise || Promise.resolve();
  122. }
  123. FirefoxPrintService.prototype = {
  124. layout() {
  125. const {
  126. pdfDocument,
  127. pagesOverview,
  128. printContainer,
  129. _printResolution,
  130. _optionalContentConfigPromise,
  131. _printAnnotationStoragePromise,
  132. } = this;
  133. const body = document.querySelector("body");
  134. body.setAttribute("data-pdfjsprinting", true);
  135. if (pdfDocument.isPureXfa) {
  136. getXfaHtmlForPrinting(printContainer, pdfDocument);
  137. return;
  138. }
  139. for (let i = 0, ii = pagesOverview.length; i < ii; ++i) {
  140. composePage(
  141. pdfDocument,
  142. /* pageNumber = */ i + 1,
  143. pagesOverview[i],
  144. printContainer,
  145. _printResolution,
  146. _optionalContentConfigPromise,
  147. _printAnnotationStoragePromise
  148. );
  149. }
  150. },
  151. destroy() {
  152. this.printContainer.textContent = "";
  153. const body = document.querySelector("body");
  154. body.removeAttribute("data-pdfjsprinting");
  155. },
  156. };
  157. PDFPrintServiceFactory.instance = {
  158. get supportsPrinting() {
  159. const canvas = document.createElement("canvas");
  160. const value = "mozPrintCallback" in canvas;
  161. return shadow(this, "supportsPrinting", value);
  162. },
  163. createPrintService(
  164. pdfDocument,
  165. pagesOverview,
  166. printContainer,
  167. printResolution,
  168. optionalContentConfigPromise,
  169. printAnnotationStoragePromise
  170. ) {
  171. return new FirefoxPrintService(
  172. pdfDocument,
  173. pagesOverview,
  174. printContainer,
  175. printResolution,
  176. optionalContentConfigPromise,
  177. printAnnotationStoragePromise
  178. );
  179. },
  180. };
  181. export { FirefoxPrintService };