UNPKG

9.68 kBJavaScriptView Raw
1/**
2 * @licstart The following is the entire license notice for the
3 * Javascript code in this page
4 *
5 * Copyright 2019 Mozilla Foundation
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * @licend The above is the entire license notice for the
20 * Javascript code in this page
21 */
22"use strict";
23
24Object.defineProperty(exports, "__esModule", {
25 value: true
26});
27exports.PDFPrintService = PDFPrintService;
28
29var _ui_utils = require("./ui_utils");
30
31var _app = require("./app");
32
33var _app_options = require("./app_options");
34
35var _pdf = require("../pdf");
36
37var activeService = null;
38var overlayManager = null;
39
40function renderPage(activeServiceOnEntry, pdfDocument, pageNumber, size) {
41 var scratchCanvas = activeService.scratchCanvas;
42 var PRINT_RESOLUTION = _app_options.AppOptions.get('printResolution') || 150;
43 var PRINT_UNITS = PRINT_RESOLUTION / 72.0;
44 scratchCanvas.width = Math.floor(size.width * PRINT_UNITS);
45 scratchCanvas.height = Math.floor(size.height * PRINT_UNITS);
46 var width = Math.floor(size.width * _ui_utils.CSS_UNITS) + 'px';
47 var height = Math.floor(size.height * _ui_utils.CSS_UNITS) + 'px';
48 var ctx = scratchCanvas.getContext('2d');
49 ctx.save();
50 ctx.fillStyle = 'rgb(255, 255, 255)';
51 ctx.fillRect(0, 0, scratchCanvas.width, scratchCanvas.height);
52 ctx.restore();
53 return pdfDocument.getPage(pageNumber).then(function (pdfPage) {
54 var renderContext = {
55 canvasContext: ctx,
56 transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
57 viewport: pdfPage.getViewport({
58 scale: 1,
59 rotation: size.rotation
60 }),
61 intent: 'print'
62 };
63 return pdfPage.render(renderContext).promise;
64 }).then(function () {
65 return {
66 width: width,
67 height: height
68 };
69 });
70}
71
72function PDFPrintService(pdfDocument, pagesOverview, printContainer, l10n) {
73 this.pdfDocument = pdfDocument;
74 this.pagesOverview = pagesOverview;
75 this.printContainer = printContainer;
76 this.l10n = l10n || _ui_utils.NullL10n;
77 this.disableCreateObjectURL = pdfDocument.loadingParams['disableCreateObjectURL'];
78 this.currentPage = -1;
79 this.scratchCanvas = document.createElement('canvas');
80}
81
82PDFPrintService.prototype = {
83 layout: function layout() {
84 this.throwIfInactive();
85 var body = document.querySelector('body');
86 body.setAttribute('data-pdfjsprinting', true);
87 var hasEqualPageSizes = this.pagesOverview.every(function (size) {
88 return size.width === this.pagesOverview[0].width && size.height === this.pagesOverview[0].height;
89 }, this);
90
91 if (!hasEqualPageSizes) {
92 console.warn('Not all pages have the same size. The printed ' + 'result may be incorrect!');
93 }
94
95 this.pageStyleSheet = document.createElement('style');
96 var pageSize = this.pagesOverview[0];
97 this.pageStyleSheet.textContent = '@supports ((size:A4) and (size:1pt 1pt)) {' + '@page { size: ' + pageSize.width + 'pt ' + pageSize.height + 'pt;}' + '}';
98 body.appendChild(this.pageStyleSheet);
99 },
100 destroy: function destroy() {
101 if (activeService !== this) {
102 return;
103 }
104
105 this.printContainer.textContent = '';
106
107 if (this.pageStyleSheet) {
108 this.pageStyleSheet.remove();
109 this.pageStyleSheet = null;
110 }
111
112 this.scratchCanvas.width = this.scratchCanvas.height = 0;
113 this.scratchCanvas = null;
114 activeService = null;
115 ensureOverlay().then(function () {
116 if (overlayManager.active !== 'printServiceOverlay') {
117 return;
118 }
119
120 overlayManager.close('printServiceOverlay');
121 });
122 },
123 renderPages: function renderPages() {
124 var _this = this;
125
126 var pageCount = this.pagesOverview.length;
127
128 var renderNextPage = function renderNextPage(resolve, reject) {
129 _this.throwIfInactive();
130
131 if (++_this.currentPage >= pageCount) {
132 renderProgress(pageCount, pageCount, _this.l10n);
133 resolve();
134 return;
135 }
136
137 var index = _this.currentPage;
138 renderProgress(index, pageCount, _this.l10n);
139 renderPage(_this, _this.pdfDocument, index + 1, _this.pagesOverview[index]).then(_this.useRenderedPage.bind(_this)).then(function () {
140 renderNextPage(resolve, reject);
141 }, reject);
142 };
143
144 return new Promise(renderNextPage);
145 },
146 useRenderedPage: function useRenderedPage(printItem) {
147 this.throwIfInactive();
148 var img = document.createElement('img');
149 img.style.width = printItem.width;
150 img.style.height = printItem.height;
151 var scratchCanvas = this.scratchCanvas;
152
153 if ('toBlob' in scratchCanvas && !this.disableCreateObjectURL) {
154 scratchCanvas.toBlob(function (blob) {
155 img.src = _pdf.URL.createObjectURL(blob);
156 });
157 } else {
158 img.src = scratchCanvas.toDataURL();
159 }
160
161 var wrapper = document.createElement('div');
162 wrapper.appendChild(img);
163 this.printContainer.appendChild(wrapper);
164 return new Promise(function (resolve, reject) {
165 img.onload = resolve;
166 img.onerror = reject;
167 });
168 },
169 performPrint: function performPrint() {
170 var _this2 = this;
171
172 this.throwIfInactive();
173 return new Promise(function (resolve) {
174 setTimeout(function () {
175 if (!_this2.active) {
176 resolve();
177 return;
178 }
179
180 print.call(window);
181 setTimeout(resolve, 20);
182 }, 0);
183 });
184 },
185
186 get active() {
187 return this === activeService;
188 },
189
190 throwIfInactive: function throwIfInactive() {
191 if (!this.active) {
192 throw new Error('This print request was cancelled or completed.');
193 }
194 }
195};
196var print = window.print;
197
198window.print = function print() {
199 if (activeService) {
200 console.warn('Ignored window.print() because of a pending print job.');
201 return;
202 }
203
204 ensureOverlay().then(function () {
205 if (activeService) {
206 overlayManager.open('printServiceOverlay');
207 }
208 });
209
210 try {
211 dispatchEvent('beforeprint');
212 } finally {
213 if (!activeService) {
214 console.error('Expected print service to be initialized.');
215 ensureOverlay().then(function () {
216 if (overlayManager.active === 'printServiceOverlay') {
217 overlayManager.close('printServiceOverlay');
218 }
219 });
220 return;
221 }
222
223 var activeServiceOnEntry = activeService;
224 activeService.renderPages().then(function () {
225 return activeServiceOnEntry.performPrint();
226 })["catch"](function () {}).then(function () {
227 if (activeServiceOnEntry.active) {
228 abort();
229 }
230 });
231 }
232};
233
234function dispatchEvent(eventType) {
235 var event = document.createEvent('CustomEvent');
236 event.initCustomEvent(eventType, false, false, 'custom');
237 window.dispatchEvent(event);
238}
239
240function abort() {
241 if (activeService) {
242 activeService.destroy();
243 dispatchEvent('afterprint');
244 }
245}
246
247function renderProgress(index, total, l10n) {
248 var progressContainer = document.getElementById('printServiceOverlay');
249 var progress = Math.round(100 * index / total);
250 var progressBar = progressContainer.querySelector('progress');
251 var progressPerc = progressContainer.querySelector('.relative-progress');
252 progressBar.value = progress;
253 l10n.get('print_progress_percent', {
254 progress: progress
255 }, progress + '%').then(function (msg) {
256 progressPerc.textContent = msg;
257 });
258}
259
260var hasAttachEvent = !!document.attachEvent;
261window.addEventListener('keydown', function (event) {
262 if (event.keyCode === 80 && (event.ctrlKey || event.metaKey) && !event.altKey && (!event.shiftKey || window.chrome || window.opera)) {
263 window.print();
264
265 if (hasAttachEvent) {
266 return;
267 }
268
269 event.preventDefault();
270
271 if (event.stopImmediatePropagation) {
272 event.stopImmediatePropagation();
273 } else {
274 event.stopPropagation();
275 }
276
277 return;
278 }
279}, true);
280
281if (hasAttachEvent) {
282 document.attachEvent('onkeydown', function (event) {
283 event = event || window.event;
284
285 if (event.keyCode === 80 && event.ctrlKey) {
286 event.keyCode = 0;
287 return false;
288 }
289 });
290}
291
292if ('onbeforeprint' in window) {
293 var stopPropagationIfNeeded = function stopPropagationIfNeeded(event) {
294 if (event.detail !== 'custom' && event.stopImmediatePropagation) {
295 event.stopImmediatePropagation();
296 }
297 };
298
299 window.addEventListener('beforeprint', stopPropagationIfNeeded);
300 window.addEventListener('afterprint', stopPropagationIfNeeded);
301}
302
303var overlayPromise;
304
305function ensureOverlay() {
306 if (!overlayPromise) {
307 overlayManager = _app.PDFViewerApplication.overlayManager;
308
309 if (!overlayManager) {
310 throw new Error('The overlay manager has not yet been initialized.');
311 }
312
313 overlayPromise = overlayManager.register('printServiceOverlay', document.getElementById('printServiceOverlay'), abort, true);
314 document.getElementById('printCancel').onclick = abort;
315 }
316
317 return overlayPromise;
318}
319
320_app.PDFPrintServiceFactory.instance = {
321 supportsPrinting: true,
322 createPrintService: function createPrintService(pdfDocument, pagesOverview, printContainer, l10n) {
323 if (activeService) {
324 throw new Error('The print service is created and active.');
325 }
326
327 activeService = new PDFPrintService(pdfDocument, pagesOverview, printContainer, l10n);
328 return activeService;
329 }
330};
\No newline at end of file