/* Copyright 2017 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. */ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.PDFThumbnailView = undefined; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _pdf = require('../pdf'); var _ui_utils = require('./ui_utils'); var _pdf_rendering_queue = require('./pdf_rendering_queue'); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var MAX_NUM_SCALING_STEPS = 3; var THUMBNAIL_CANVAS_BORDER_WIDTH = 1; var THUMBNAIL_WIDTH = 98; var TempImageFactory = function TempImageFactoryClosure() { var tempCanvasCache = null; return { getCanvas: function getCanvas(width, height) { var tempCanvas = tempCanvasCache; if (!tempCanvas) { tempCanvas = document.createElement('canvas'); tempCanvasCache = tempCanvas; } tempCanvas.width = width; tempCanvas.height = height; tempCanvas.mozOpaque = true; var ctx = tempCanvas.getContext('2d', { alpha: false }); ctx.save(); ctx.fillStyle = 'rgb(255, 255, 255)'; ctx.fillRect(0, 0, width, height); ctx.restore(); return tempCanvas; }, destroyCanvas: function destroyCanvas() { var tempCanvas = tempCanvasCache; if (tempCanvas) { tempCanvas.width = 0; tempCanvas.height = 0; } tempCanvasCache = null; } }; }(); var PDFThumbnailView = function () { function PDFThumbnailView(_ref) { var container = _ref.container, id = _ref.id, defaultViewport = _ref.defaultViewport, linkService = _ref.linkService, renderingQueue = _ref.renderingQueue, _ref$disableCanvasToI = _ref.disableCanvasToImageConversion, disableCanvasToImageConversion = _ref$disableCanvasToI === undefined ? false : _ref$disableCanvasToI, _ref$l10n = _ref.l10n, l10n = _ref$l10n === undefined ? _ui_utils.NullL10n : _ref$l10n; _classCallCheck(this, PDFThumbnailView); this.id = id; this.renderingId = 'thumbnail' + id; this.pageLabel = null; this.pdfPage = null; this.rotation = 0; this.viewport = defaultViewport; this.pdfPageRotate = defaultViewport.rotation; this.linkService = linkService; this.renderingQueue = renderingQueue; this.renderTask = null; this.renderingState = _pdf_rendering_queue.RenderingStates.INITIAL; this.resume = null; this.disableCanvasToImageConversion = disableCanvasToImageConversion; this.pageWidth = this.viewport.width; this.pageHeight = this.viewport.height; this.pageRatio = this.pageWidth / this.pageHeight; this.canvasWidth = THUMBNAIL_WIDTH; this.canvasHeight = this.canvasWidth / this.pageRatio | 0; this.scale = this.canvasWidth / this.pageWidth; this.l10n = l10n; var anchor = document.createElement('a'); anchor.href = linkService.getAnchorUrl('#page=' + id); this.l10n.get('thumb_page_title', { page: id }, 'Page {{page}}').then(function (msg) { anchor.title = msg; }); anchor.onclick = function () { linkService.page = id; return false; }; this.anchor = anchor; var div = document.createElement('div'); div.className = 'thumbnail'; div.setAttribute('data-page-number', this.id); this.div = div; if (id === 1) { div.classList.add('selected'); } var ring = document.createElement('div'); ring.className = 'thumbnailSelectionRing'; var borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH; ring.style.width = this.canvasWidth + borderAdjustment + 'px'; ring.style.height = this.canvasHeight + borderAdjustment + 'px'; this.ring = ring; div.appendChild(ring); anchor.appendChild(div); container.appendChild(anchor); } _createClass(PDFThumbnailView, [{ key: 'setPdfPage', value: function setPdfPage(pdfPage) { this.pdfPage = pdfPage; this.pdfPageRotate = pdfPage.rotate; var totalRotation = (this.rotation + this.pdfPageRotate) % 360; this.viewport = pdfPage.getViewport(1, totalRotation); this.reset(); } }, { key: 'reset', value: function reset() { this.cancelRendering(); this.pageWidth = this.viewport.width; this.pageHeight = this.viewport.height; this.pageRatio = this.pageWidth / this.pageHeight; this.canvasHeight = this.canvasWidth / this.pageRatio | 0; this.scale = this.canvasWidth / this.pageWidth; this.div.removeAttribute('data-loaded'); var ring = this.ring; var childNodes = ring.childNodes; for (var i = childNodes.length - 1; i >= 0; i--) { ring.removeChild(childNodes[i]); } var borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH; ring.style.width = this.canvasWidth + borderAdjustment + 'px'; ring.style.height = this.canvasHeight + borderAdjustment + 'px'; if (this.canvas) { this.canvas.width = 0; this.canvas.height = 0; delete this.canvas; } if (this.image) { this.image.removeAttribute('src'); delete this.image; } } }, { key: 'update', value: function update(rotation) { if (typeof rotation !== 'undefined') { this.rotation = rotation; } var totalRotation = (this.rotation + this.pdfPageRotate) % 360; this.viewport = this.viewport.clone({ scale: 1, rotation: totalRotation }); this.reset(); } }, { key: 'cancelRendering', value: function cancelRendering() { if (this.renderTask) { this.renderTask.cancel(); this.renderTask = null; } this.renderingState = _pdf_rendering_queue.RenderingStates.INITIAL; this.resume = null; } }, { key: '_getPageDrawContext', value: function _getPageDrawContext() { var noCtxScale = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var canvas = document.createElement('canvas'); this.canvas = canvas; canvas.mozOpaque = true; var ctx = canvas.getContext('2d', { alpha: false }); var outputScale = (0, _ui_utils.getOutputScale)(ctx); canvas.width = this.canvasWidth * outputScale.sx | 0; canvas.height = this.canvasHeight * outputScale.sy | 0; canvas.style.width = this.canvasWidth + 'px'; canvas.style.height = this.canvasHeight + 'px'; if (!noCtxScale && outputScale.scaled) { ctx.scale(outputScale.sx, outputScale.sy); } return ctx; } }, { key: '_convertCanvasToImage', value: function _convertCanvasToImage() { var _this = this; if (!this.canvas) { return; } if (this.renderingState !== _pdf_rendering_queue.RenderingStates.FINISHED) { return; } var id = this.renderingId; var className = 'thumbnailImage'; if (this.disableCanvasToImageConversion) { this.canvas.id = id; this.canvas.className = className; this.l10n.get('thumb_page_canvas', { page: this.pageId }, 'Thumbnail of Page {{page}}').then(function (msg) { _this.canvas.setAttribute('aria-label', msg); }); this.div.setAttribute('data-loaded', true); this.ring.appendChild(this.canvas); return; } var image = document.createElement('img'); image.id = id; image.className = className; this.l10n.get('thumb_page_canvas', { page: this.pageId }, 'Thumbnail of Page {{page}}').then(function (msg) { image.setAttribute('aria-label', msg); }); image.style.width = this.canvasWidth + 'px'; image.style.height = this.canvasHeight + 'px'; image.src = this.canvas.toDataURL(); this.image = image; this.div.setAttribute('data-loaded', true); this.ring.appendChild(image); this.canvas.width = 0; this.canvas.height = 0; delete this.canvas; } }, { key: 'draw', value: function draw() { var _this2 = this; if (this.renderingState !== _pdf_rendering_queue.RenderingStates.INITIAL) { console.error('Must be in new state before drawing'); return Promise.resolve(undefined); } this.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING; var renderCapability = (0, _pdf.createPromiseCapability)(); var finishRenderTask = function finishRenderTask(error) { if (renderTask === _this2.renderTask) { _this2.renderTask = null; } if (error instanceof _pdf.RenderingCancelledException) { renderCapability.resolve(undefined); return; } _this2.renderingState = _pdf_rendering_queue.RenderingStates.FINISHED; _this2._convertCanvasToImage(); if (!error) { renderCapability.resolve(undefined); } else { renderCapability.reject(error); } }; var ctx = this._getPageDrawContext(); var drawViewport = this.viewport.clone({ scale: this.scale }); var renderContinueCallback = function renderContinueCallback(cont) { if (!_this2.renderingQueue.isHighestPriority(_this2)) { _this2.renderingState = _pdf_rendering_queue.RenderingStates.PAUSED; _this2.resume = function () { _this2.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING; cont(); }; return; } cont(); }; var renderContext = { canvasContext: ctx, viewport: drawViewport }; var renderTask = this.renderTask = this.pdfPage.render(renderContext); renderTask.onContinue = renderContinueCallback; renderTask.promise.then(function () { finishRenderTask(null); }, function (error) { finishRenderTask(error); }); return renderCapability.promise; } }, { key: 'setImage', value: function setImage(pageView) { if (this.renderingState !== _pdf_rendering_queue.RenderingStates.INITIAL) { return; } var img = pageView.canvas; if (!img) { return; } if (!this.pdfPage) { this.setPdfPage(pageView.pdfPage); } this.renderingState = _pdf_rendering_queue.RenderingStates.FINISHED; var ctx = this._getPageDrawContext(true); var canvas = ctx.canvas; if (img.width <= 2 * canvas.width) { ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height); this._convertCanvasToImage(); return; } var reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS; var reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS; var reducedImage = TempImageFactory.getCanvas(reducedWidth, reducedHeight); var reducedImageCtx = reducedImage.getContext('2d'); while (reducedWidth > img.width || reducedHeight > img.height) { reducedWidth >>= 1; reducedHeight >>= 1; } reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, reducedWidth, reducedHeight); while (reducedWidth > 2 * canvas.width) { reducedImageCtx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, reducedWidth >> 1, reducedHeight >> 1); reducedWidth >>= 1; reducedHeight >>= 1; } ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height); this._convertCanvasToImage(); } }, { key: 'setPageLabel', value: function setPageLabel(label) { var _this3 = this; this.pageLabel = typeof label === 'string' ? label : null; this.l10n.get('thumb_page_title', { page: this.pageId }, 'Page {{page}}').then(function (msg) { _this3.anchor.title = msg; }); if (this.renderingState !== _pdf_rendering_queue.RenderingStates.FINISHED) { return; } this.l10n.get('thumb_page_canvas', { page: this.pageId }, 'Thumbnail of Page {{page}}').then(function (ariaLabel) { if (_this3.image) { _this3.image.setAttribute('aria-label', ariaLabel); } else if (_this3.disableCanvasToImageConversion && _this3.canvas) { _this3.canvas.setAttribute('aria-label', ariaLabel); } }); } }, { key: 'pageId', get: function get() { return this.pageLabel !== null ? this.pageLabel : this.id; } }], [{ key: 'cleanup', value: function cleanup() { TempImageFactory.destroyCanvas(); } }]); return PDFThumbnailView; }(); exports.PDFThumbnailView = PDFThumbnailView;