Merge pull request #7766 from Rob--W/printing-refactor-split-from-7721
Printing refactor split from 7721
This commit is contained in:
		
						commit
						a740d69457
					
				@ -35,13 +35,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  var activeService = null;
 | 
					  var activeService = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Using one canvas for all paint operations -- painting one canvas at a time.
 | 
					  // Renders the page to the canvas of the given print service, and returns
 | 
				
			||||||
  var scratchCanvas = null;
 | 
					  // the suggested dimensions of the output page.
 | 
				
			||||||
 | 
					  function renderPage(activeServiceOnEntry, pdfDocument, pageNumber, size) {
 | 
				
			||||||
  function renderPage(pdfDocument, pageNumber, size, wrapper) {
 | 
					    var scratchCanvas = activeService.scratchCanvas;
 | 
				
			||||||
    if (!scratchCanvas) {
 | 
					 | 
				
			||||||
      scratchCanvas = document.createElement('canvas');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The size of the canvas in pixels for printing.
 | 
					    // The size of the canvas in pixels for printing.
 | 
				
			||||||
    var PRINT_RESOLUTION = 150;
 | 
					    var PRINT_RESOLUTION = 150;
 | 
				
			||||||
@ -50,9 +47,8 @@
 | 
				
			|||||||
    scratchCanvas.height = Math.floor(size.height * PRINT_UNITS);
 | 
					    scratchCanvas.height = Math.floor(size.height * PRINT_UNITS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The physical size of the img as specified by the PDF document.
 | 
					    // The physical size of the img as specified by the PDF document.
 | 
				
			||||||
    var img = document.createElement('img');
 | 
					    var width = Math.floor(size.width * CSS_UNITS) + 'px';
 | 
				
			||||||
    img.style.width = Math.floor(size.width * CSS_UNITS) + 'px';
 | 
					    var height = Math.floor(size.height * CSS_UNITS) + 'px';
 | 
				
			||||||
    img.style.height = Math.floor(size.height * CSS_UNITS) + 'px';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var ctx = scratchCanvas.getContext('2d');
 | 
					    var ctx = scratchCanvas.getContext('2d');
 | 
				
			||||||
    ctx.save();
 | 
					    ctx.save();
 | 
				
			||||||
@ -68,23 +64,11 @@
 | 
				
			|||||||
        intent: 'print'
 | 
					        intent: 'print'
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      return pdfPage.render(renderContext).promise;
 | 
					      return pdfPage.render(renderContext).promise;
 | 
				
			||||||
    }).then(function() {
 | 
					    }).then(function () {
 | 
				
			||||||
      if (!activeService) {
 | 
					      return {
 | 
				
			||||||
        return Promise.reject(new Error('cancelled'));
 | 
					        width: width,
 | 
				
			||||||
      }
 | 
					        height: height,
 | 
				
			||||||
      if (('toBlob' in scratchCanvas) &&
 | 
					      };
 | 
				
			||||||
          !pdfjsLib.PDFJS.disableCreateObjectURL) {
 | 
					 | 
				
			||||||
        scratchCanvas.toBlob(function (blob) {
 | 
					 | 
				
			||||||
          img.src = URL.createObjectURL(blob);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        img.src = scratchCanvas.toDataURL();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      wrapper.appendChild(img);
 | 
					 | 
				
			||||||
      return new Promise(function(resolve, reject) {
 | 
					 | 
				
			||||||
        img.onload = resolve;
 | 
					 | 
				
			||||||
        img.onerror = reject;
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -92,14 +76,16 @@
 | 
				
			|||||||
    this.pdfDocument = pdfDocument;
 | 
					    this.pdfDocument = pdfDocument;
 | 
				
			||||||
    this.pagesOverview = pagesOverview;
 | 
					    this.pagesOverview = pagesOverview;
 | 
				
			||||||
    this.printContainer = printContainer;
 | 
					    this.printContainer = printContainer;
 | 
				
			||||||
    this.wrappers = [];
 | 
					 | 
				
			||||||
    this.currentPage = -1;
 | 
					    this.currentPage = -1;
 | 
				
			||||||
 | 
					    // The temporary canvas where renderPage paints one page at a time.
 | 
				
			||||||
 | 
					    this.scratchCanvas = document.createElement('canvas');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PDFPrintService.prototype = {
 | 
					  PDFPrintService.prototype = {
 | 
				
			||||||
    layout: function () {
 | 
					    layout: function () {
 | 
				
			||||||
 | 
					      this.throwIfInactive();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      var pdfDocument = this.pdfDocument;
 | 
					      var pdfDocument = this.pdfDocument;
 | 
				
			||||||
      var printContainer = this.printContainer;
 | 
					 | 
				
			||||||
      var body = document.querySelector('body');
 | 
					      var body = document.querySelector('body');
 | 
				
			||||||
      body.setAttribute('data-pdfjsprinting', true);
 | 
					      body.setAttribute('data-pdfjsprinting', true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -130,29 +116,23 @@
 | 
				
			|||||||
        '@page { size: ' + pageSize.width + 'pt ' + pageSize.height + 'pt;}' +
 | 
					        '@page { size: ' + pageSize.width + 'pt ' + pageSize.height + 'pt;}' +
 | 
				
			||||||
        '}';
 | 
					        '}';
 | 
				
			||||||
      body.appendChild(this.pageStyleSheet);
 | 
					      body.appendChild(this.pageStyleSheet);
 | 
				
			||||||
 | 
					 | 
				
			||||||
      for (var i = 0, ii = this.pagesOverview.length; i < ii; ++i) {
 | 
					 | 
				
			||||||
        var wrapper = document.createElement('div');
 | 
					 | 
				
			||||||
        printContainer.appendChild(wrapper);
 | 
					 | 
				
			||||||
        this.wrappers[i] = wrapper;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    destroy: function () {
 | 
					    destroy: function () {
 | 
				
			||||||
 | 
					      if (activeService !== this) {
 | 
				
			||||||
 | 
					        // |activeService| cannot be replaced without calling destroy() first,
 | 
				
			||||||
 | 
					        // so if it differs then an external consumer has a stale reference to
 | 
				
			||||||
 | 
					        // us.
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      this.printContainer.textContent = '';
 | 
					      this.printContainer.textContent = '';
 | 
				
			||||||
      this.wrappers = null;
 | 
					 | 
				
			||||||
      if (this.pageStyleSheet && this.pageStyleSheet.parentNode) {
 | 
					      if (this.pageStyleSheet && this.pageStyleSheet.parentNode) {
 | 
				
			||||||
        this.pageStyleSheet.parentNode.removeChild(this.pageStyleSheet);
 | 
					        this.pageStyleSheet.parentNode.removeChild(this.pageStyleSheet);
 | 
				
			||||||
        this.pageStyleSheet = null;
 | 
					        this.pageStyleSheet = null;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (activeService !== this) {
 | 
					      this.scratchCanvas.width = this.scratchCanvas.height = 0;
 | 
				
			||||||
        return; // no need to clean up shared resources
 | 
					      this.scratchCanvas = null;
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      activeService = null;
 | 
					      activeService = null;
 | 
				
			||||||
      if (scratchCanvas) {
 | 
					 | 
				
			||||||
        scratchCanvas.width = scratchCanvas.height = 0;
 | 
					 | 
				
			||||||
        scratchCanvas = null;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      ensureOverlay().then(function () {
 | 
					      ensureOverlay().then(function () {
 | 
				
			||||||
        if (OverlayManager.active !== 'printServiceOverlay') {
 | 
					        if (OverlayManager.active !== 'printServiceOverlay') {
 | 
				
			||||||
          return; // overlay was already closed
 | 
					          return; // overlay was already closed
 | 
				
			||||||
@ -164,10 +144,7 @@
 | 
				
			|||||||
    renderPages: function () {
 | 
					    renderPages: function () {
 | 
				
			||||||
      var pageCount = this.pagesOverview.length;
 | 
					      var pageCount = this.pagesOverview.length;
 | 
				
			||||||
      var renderNextPage = function (resolve, reject) {
 | 
					      var renderNextPage = function (resolve, reject) {
 | 
				
			||||||
        if (activeService !== this) {
 | 
					        this.throwIfInactive();
 | 
				
			||||||
          reject(new Error('cancelled'));
 | 
					 | 
				
			||||||
          return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (++this.currentPage >= pageCount) {
 | 
					        if (++this.currentPage >= pageCount) {
 | 
				
			||||||
          renderProgress(pageCount, pageCount);
 | 
					          renderProgress(pageCount, pageCount);
 | 
				
			||||||
          resolve();
 | 
					          resolve();
 | 
				
			||||||
@ -175,12 +152,68 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        var index = this.currentPage;
 | 
					        var index = this.currentPage;
 | 
				
			||||||
        renderProgress(index, pageCount);
 | 
					        renderProgress(index, pageCount);
 | 
				
			||||||
        renderPage(this.pdfDocument, index + 1,
 | 
					        renderPage(this, this.pdfDocument, index + 1, this.pagesOverview[index])
 | 
				
			||||||
                   this.pagesOverview[index], this.wrappers[index]).then(
 | 
					          .then(this.useRenderedPage.bind(this))
 | 
				
			||||||
          function () { renderNextPage(resolve, reject); }, reject);
 | 
					          .then(function () {
 | 
				
			||||||
 | 
					            renderNextPage(resolve, reject);
 | 
				
			||||||
 | 
					          }, reject);
 | 
				
			||||||
      }.bind(this);
 | 
					      }.bind(this);
 | 
				
			||||||
      return new Promise(renderNextPage);
 | 
					      return new Promise(renderNextPage);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useRenderedPage: function (printItem) {
 | 
				
			||||||
 | 
					      this.throwIfInactive();
 | 
				
			||||||
 | 
					      var img = document.createElement('img');
 | 
				
			||||||
 | 
					      img.style.width = printItem.width;
 | 
				
			||||||
 | 
					      img.style.height = printItem.height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var scratchCanvas = this.scratchCanvas;
 | 
				
			||||||
 | 
					      if (('toBlob' in scratchCanvas) &&
 | 
				
			||||||
 | 
					          !pdfjsLib.PDFJS.disableCreateObjectURL) {
 | 
				
			||||||
 | 
					        scratchCanvas.toBlob(function (blob) {
 | 
				
			||||||
 | 
					          img.src = URL.createObjectURL(blob);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        img.src = scratchCanvas.toDataURL();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var wrapper = document.createElement('div');
 | 
				
			||||||
 | 
					      wrapper.appendChild(img);
 | 
				
			||||||
 | 
					      this.printContainer.appendChild(wrapper);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return new Promise(function (resolve, reject) {
 | 
				
			||||||
 | 
					        img.onload = resolve;
 | 
				
			||||||
 | 
					        img.onerror = reject;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    performPrint: function () {
 | 
				
			||||||
 | 
					      this.throwIfInactive();
 | 
				
			||||||
 | 
					      return new Promise(function (resolve) {
 | 
				
			||||||
 | 
					        // Push window.print in the macrotask queue to avoid being affected by
 | 
				
			||||||
 | 
					        // the deprecation of running print() code in a microtask, see
 | 
				
			||||||
 | 
					        // https://github.com/mozilla/pdf.js/issues/7547.
 | 
				
			||||||
 | 
					        setTimeout(function () {
 | 
				
			||||||
 | 
					          if (!this.active) {
 | 
				
			||||||
 | 
					            resolve();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          print.call(window);
 | 
				
			||||||
 | 
					          // Delay promise resolution in case print() was not synchronous.
 | 
				
			||||||
 | 
					          setTimeout(resolve, 20);  // Tidy-up.
 | 
				
			||||||
 | 
					        }.bind(this), 0);
 | 
				
			||||||
 | 
					      }.bind(this));
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    get active() {
 | 
				
			||||||
 | 
					      return this === activeService;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    throwIfInactive: function () {
 | 
				
			||||||
 | 
					      if (!this.active) {
 | 
				
			||||||
 | 
					        throw new Error('This print request was cancelled or completed.');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -191,7 +224,9 @@
 | 
				
			|||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ensureOverlay().then(function () {
 | 
					    ensureOverlay().then(function () {
 | 
				
			||||||
      OverlayManager.open('printServiceOverlay');
 | 
					      if (activeService) {
 | 
				
			||||||
 | 
					        OverlayManager.open('printServiceOverlay');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
@ -199,8 +234,26 @@
 | 
				
			|||||||
    } finally {
 | 
					    } finally {
 | 
				
			||||||
      if (!activeService) {
 | 
					      if (!activeService) {
 | 
				
			||||||
        console.error('Expected print service to be initialized.');
 | 
					        console.error('Expected print service to be initialized.');
 | 
				
			||||||
 | 
					        if (OverlayManager.active === 'printServiceOverlay') {
 | 
				
			||||||
 | 
					          OverlayManager.close('printServiceOverlay');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      activeService.renderPages().then(startPrint, abort);
 | 
					      var activeServiceOnEntry = activeService;
 | 
				
			||||||
 | 
					      activeService.renderPages().then(function () {
 | 
				
			||||||
 | 
					        return activeServiceOnEntry.performPrint();
 | 
				
			||||||
 | 
					      }).catch(function () {
 | 
				
			||||||
 | 
					        // Ignore any error messages.
 | 
				
			||||||
 | 
					      }).then(function () {
 | 
				
			||||||
 | 
					        // aborts acts on the "active" print request, so we need to check
 | 
				
			||||||
 | 
					        // whether the print request (activeServiceOnEntry) is still active.
 | 
				
			||||||
 | 
					        // Without the check, an unrelated print request (created after aborting
 | 
				
			||||||
 | 
					        // this print request while the pages were being generated) would be
 | 
				
			||||||
 | 
					        // aborted.
 | 
				
			||||||
 | 
					        if (activeServiceOnEntry.active) {
 | 
				
			||||||
 | 
					          abort();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -210,19 +263,6 @@
 | 
				
			|||||||
    window.dispatchEvent(event);
 | 
					    window.dispatchEvent(event);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function startPrint() {
 | 
					 | 
				
			||||||
    // Push window.print in the macrotask queue to avoid being affected by
 | 
					 | 
				
			||||||
    // the deprecation of running print() code in a microtask, see
 | 
					 | 
				
			||||||
    // https://github.com/mozilla/pdf.js/issues/7547.
 | 
					 | 
				
			||||||
    setTimeout(function() {
 | 
					 | 
				
			||||||
      if (!activeService) {
 | 
					 | 
				
			||||||
        return; // Print task cancelled by user.
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      print.call(window);
 | 
					 | 
				
			||||||
      setTimeout(abort, 20); // Tidy-up
 | 
					 | 
				
			||||||
    }, 0);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  function abort() {
 | 
					  function abort() {
 | 
				
			||||||
    if (activeService) {
 | 
					    if (activeService) {
 | 
				
			||||||
      activeService.destroy();
 | 
					      activeService.destroy();
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user