From 952545e20fd47176aba9ef20f5d50a0c492ea28b Mon Sep 17 00:00:00 2001 From: Samuel Chantaraud Date: Fri, 23 May 2014 21:43:43 -0400 Subject: [PATCH] Limit the size of canvases to 5MP (iOS restriction) --- src/display/api.js | 8 ++++++++ web/compatibility.js | 9 +++++++++ web/page_view.js | 37 +++++++++++++++++++++++++++++++++---- web/viewer.js | 2 +- 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index a7cf6bfcb..b5e9039f2 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -140,6 +140,14 @@ PDFJS.useOnlyCssZoom = (PDFJS.useOnlyCssZoom === undefined ? PDFJS.verbosity = (PDFJS.verbosity === undefined ? PDFJS.VERBOSITY_LEVELS.warnings : PDFJS.verbosity); +/** + * The maximum supported canvas size in total pixels e.g. width * height. + * The default value is 4096 * 4096. Use -1 for no limit. + * @var {number} + */ +PDFJS.maxCanvasPixels = (PDFJS.maxCanvasPixels === undefined ? + 16777216 : PDFJS.maxCanvasPixels); + /** * Document initialization / loading parameters object. * diff --git a/web/compatibility.js b/web/compatibility.js index c39162cbf..b603971e3 100644 --- a/web/compatibility.js +++ b/web/compatibility.js @@ -507,3 +507,12 @@ if (typeof PDFJS === 'undefined') { window.setTimeout(callback, 20); }); })(); + +(function checkCanvasSizeLimitation() { + var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent); + var isAndroid = /Android/g.test(navigator.userAgent); + if (isIOS || isAndroid) { + // 5MP + PDFJS.maxCanvasPixels = 5242880; + } +})(); diff --git a/web/page_view.js b/web/page_view.js index d90419e55..461f72069 100644 --- a/web/page_view.js +++ b/web/page_view.js @@ -29,6 +29,7 @@ var PageView = function pageView(container, id, scale, this.scale = scale || 1.0; this.viewport = defaultViewport; this.pdfPageRotate = defaultViewport.rotation; + this.hasRestrictedScaling = false; this.renderingState = RenderingStates.INITIAL; this.resume = null; @@ -125,8 +126,23 @@ var PageView = function pageView(container, id, scale, rotation: totalRotation }); - if (PDFJS.useOnlyCssZoom && this.canvas) { - this.cssTransform(this.canvas); + var isScalingRestricted = false; + if (this.canvas && PDFJS.maxCanvasPixels > 0) { + var ctx = this.canvas.getContext('2d'); + var outputScale = getOutputScale(ctx); + var pixelsInViewport = this.viewport.width * this.viewport.height; + var maxScale = Math.sqrt(PDFJS.maxCanvasPixels / pixelsInViewport); + if (((Math.floor(this.viewport.width) * outputScale.sx) | 0) * + ((Math.floor(this.viewport.height) * outputScale.sy) | 0) > + PDFJS.maxCanvasPixels) { + isScalingRestricted = true; + } + } + + if (this.canvas && + (PDFJS.useOnlyCssZoom || + (this.hasRestrictedScaling && isScalingRestricted))) { + this.cssTransform(this.canvas, true); return; } else if (this.canvas && !this.zoomLayer) { this.zoomLayer = this.canvas.parentNode; @@ -138,7 +154,7 @@ var PageView = function pageView(container, id, scale, this.reset(true); }; - this.cssTransform = function pageCssTransform(canvas) { + this.cssTransform = function pageCssTransform(canvas, redrawAnnotations) { // Scale canvas, canvas wrapper, and page container. var width = this.viewport.width; var height = this.viewport.height; @@ -201,7 +217,7 @@ var PageView = function pageView(container, id, scale, CustomStyle.setProp('transformOrigin', textLayerDiv, '0% 0%'); } - if (PDFJS.useOnlyCssZoom && this.annotationLayer) { + if (redrawAnnotations && this.annotationLayer) { setupAnnotations(div, this.pdfPage, this.viewport); } }; @@ -507,6 +523,19 @@ var PageView = function pageView(container, id, scale, outputScale.scaled = true; } + if (PDFJS.maxCanvasPixels > 0) { + var pixelsInViewport = viewport.width * viewport.height; + var maxScale = Math.sqrt(PDFJS.maxCanvasPixels / pixelsInViewport); + if (outputScale.sx > maxScale || outputScale.sy > maxScale) { + outputScale.sx = maxScale; + outputScale.sy = maxScale; + outputScale.scaled = true; + this.hasRestrictedScaling = true; + } else { + this.hasRestrictedScaling = false; + } + } + canvas.width = (Math.floor(viewport.width) * outputScale.sx) | 0; canvas.height = (Math.floor(viewport.height) * outputScale.sy) | 0; canvas.style.width = Math.floor(viewport.width) + 'px'; diff --git a/web/viewer.js b/web/viewer.js index f4c24e2d8..5862efc5e 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -34,7 +34,7 @@ var SCROLLBAR_PADDING = 40; var VERTICAL_PADDING = 5; var MAX_AUTO_SCALE = 1.25; var MIN_SCALE = 0.25; -var MAX_SCALE = 4.0; +var MAX_SCALE = 10.0; var VIEW_HISTORY_MEMORY = 20; var SCALE_SELECT_CONTAINER_PADDING = 8; var SCALE_SELECT_PADDING = 22;