diff --git a/.gitignore b/.gitignore index b779eac0b..debce4dd2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ local.mk build/ tags .DS_Store +Makefile diff --git a/l10n/en-US/viewer.properties b/l10n/en-US/viewer.properties index 6bc477309..2e16898c0 100644 --- a/l10n/en-US/viewer.properties +++ b/l10n/en-US/viewer.properties @@ -50,6 +50,10 @@ thumb_page_title=Page {{page}} # number. thumb_page_canvas=Thumbnail of Page {{page}} +# Context menu +page_rotate_cw=Rotate Clockwise +page_rotate_ccw=Rotate Counter-Clockwise + # Search panel button title and messages search=Find search_terms_not_found=(Not found) diff --git a/make.js b/make.js index 807b3dd7c..e33a597e0 100755 --- a/make.js +++ b/make.js @@ -812,3 +812,13 @@ target.clean = function() { rm('-rf', BUILD_DIR); }; +// +// make makefile +// +target.makefile = function() { + var makefileContent = 'help:\n\tnode make\n\n'; + for (var i in target) { + makefileContent += i + ':\n\tnode make ' + i + '\n\n'; + } + makefileContent.to('Makefile'); +}; diff --git a/src/fonts.js b/src/fonts.js index f42f79a5a..15af2fa39 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -577,6 +577,8 @@ var FontLoader = { src += '<script type="application/javascript">'; src += ' window.onload = function fontLoaderOnload() {\n'; src += ' parent.postMessage("' + requestId + '", "*");\n'; + // Chrome stuck on loading (see chrome issue 145227) - resetting url + src += ' window.location = "about:blank";\n'; src += ' }'; // Hack so the end script tag isn't counted if this is inline JS. src += '</scr' + 'ipt></head><body>'; diff --git a/src/pattern.js b/src/pattern.js index 1799732c2..4fd2b73c5 100644 --- a/src/pattern.js +++ b/src/pattern.js @@ -219,8 +219,9 @@ var TilingPattern = (function TilingPatternClosure() { var xstep = IR[5]; var ystep = IR[6]; var paintType = IR[7]; + var tilingType = IR[8]; - TODO('TilingType'); + TODO('TilingType: ' + tilingType); this.curMatrix = ctx.mozCurrentTransform; this.invMatrix = ctx.mozCurrentTransformInverse; @@ -293,9 +294,11 @@ var TilingPattern = (function TilingPatternClosure() { var xstep = dict.get('XStep'); var ystep = dict.get('YStep'); var paintType = dict.get('PaintType'); + var tilingType = dict.get('TilingType'); return [ - 'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, paintType + 'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, + paintType, tilingType ]; }; diff --git a/web/viewer.css b/web/viewer.css index 5acca38f9..c1e7aaf3d 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -778,8 +778,6 @@ html[dir='rtl'] .toolbarButton.pageDown::before { .thumbnail { margin-bottom: 15px; float: left; - width: 114px; - height: 142px; } .thumbnail:not([data-loaded]) { diff --git a/web/viewer.html b/web/viewer.html index 2b705b72f..5a2f4f28c 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -185,8 +185,15 @@ limitations under the License. </div> </div> + <menu type="context" id="viewerContextMenu"> + <menuitem label="Rotate Counter-Clockwise" id="page_rotate_ccw" + data-l10n-id="page_rotate_ccw" ></menuitem> + <menuitem label="Rotate Clockwise" id="page_rotate_cw" + data-l10n-id="page_rotate_cw" ></menuitem> + </menu> + <div id="viewerContainer"> - <div id="viewer"></div> + <div id="viewer" contextmenu="viewerContextMenu"></div> </div> <div id="loadingBox"> diff --git a/web/viewer.js b/web/viewer.js index 27002fabf..9b7d47496 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -224,6 +224,7 @@ var PDFView = { thumbnailViewScroll: null, isFullscreen: false, previousScale: null, + pageRotation: 0, // called once when the document is loaded initialize: function pdfViewInitialize() { @@ -707,6 +708,8 @@ var PDFView = { storedHash = 'page=' + page + '&zoom=' + zoom + ',' + left + ',' + top; } + this.pageRotation = 0; + var pages = this.pages = []; this.pageText = []; this.startedTextExtraction = false; @@ -1180,6 +1183,34 @@ var PDFView = { this.isFullscreen = false; this.parseScale(this.previousScale); this.page = this.page; + }, + + rotatePages: function pdfViewPageRotation(delta) { + + this.pageRotation = (this.pageRotation + 360 + delta) % 360; + + for (var i = 0, l = this.pages.length; i < l; i++) { + var page = this.pages[i]; + page.update(page.scale, this.pageRotation); + } + + for (var i = 0, l = this.thumbnails.length; i < l; i++) { + var thumb = this.thumbnails[i]; + thumb.updateRotation(this.pageRotation); + } + + var currentPage = this.pages[this.page - 1]; + + if (this.isFullscreen) { + this.parseScale('page-fit', true); + } + + this.renderHighestPriority(); + + // Wait for fullscreen to take effect + setTimeout(function() { + currentPage.scrollIntoView(); + }, 0); } }; @@ -1188,8 +1219,9 @@ var PageView = function pageView(container, pdfPage, id, scale, this.id = id; this.pdfPage = pdfPage; + this.rotation = 0; this.scale = scale || 1.0; - this.viewport = this.pdfPage.getViewport(this.scale); + this.viewport = this.pdfPage.getViewport(this.scale, this.pdfPage.rotate); this.renderingState = RenderingStates.INITIAL; this.resume = null; @@ -1200,6 +1232,8 @@ var PageView = function pageView(container, pdfPage, id, scale, var div = this.el = document.createElement('div'); div.id = 'pageContainer' + this.id; div.className = 'page'; + div.style.width = this.viewport.width + 'px'; + div.style.height = this.viewport.height + 'px'; container.appendChild(anchor); container.appendChild(div); @@ -1209,12 +1243,18 @@ var PageView = function pageView(container, pdfPage, id, scale, this.pdfPage.destroy(); }; - this.update = function pageViewUpdate(scale) { + this.update = function pageViewUpdate(scale, rotation) { this.renderingState = RenderingStates.INITIAL; this.resume = null; + if (typeof rotation !== 'undefined') { + this.rotation = rotation; + } + this.scale = scale || this.scale; - var viewport = this.pdfPage.getViewport(this.scale); + + var totalRotation = (this.rotation + this.pdfPage.rotate) % 360; + var viewport = this.pdfPage.getViewport(this.scale, totalRotation); this.viewport = viewport; div.style.width = viewport.width + 'px'; @@ -1545,7 +1585,9 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) { return false; }; - var viewport = pdfPage.getViewport(1); + var rotation = 0; + var totalRotation = (rotation + pdfPage.rotate) % 360; + var viewport = pdfPage.getViewport(1, totalRotation); var pageWidth = this.width = viewport.width; var pageHeight = this.height = viewport.height; var pageRatio = pageWidth / pageHeight; @@ -1560,12 +1602,41 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) { div.id = 'thumbnailContainer' + id; div.className = 'thumbnail'; + var ring = document.createElement('div'); + ring.className = 'thumbnailSelectionRing'; + ring.style.width = canvasWidth + 'px'; + ring.style.height = canvasHeight + 'px'; + + div.appendChild(ring); anchor.appendChild(div); container.appendChild(anchor); this.hasImage = false; this.renderingState = RenderingStates.INITIAL; + this.updateRotation = function(rot) { + + rotation = rot; + totalRotation = (rotation + pdfPage.rotate) % 360; + viewport = pdfPage.getViewport(1, totalRotation); + pageWidth = this.width = viewport.width; + pageHeight = this.height = viewport.height; + pageRatio = pageWidth / pageHeight; + + canvasHeight = canvasWidth / this.width * this.height; + scaleX = this.scaleX = (canvasWidth / pageWidth); + scaleY = this.scaleY = (canvasHeight / pageHeight); + + div.removeAttribute('data-loaded'); + ring.textContent = ''; + ring.style.width = canvasWidth + 'px'; + ring.style.height = canvasHeight + 'px'; + + this.hasImage = false; + this.renderingState = RenderingStates.INITIAL; + this.resume = null; + } + function getPageDrawContext() { var canvas = document.createElement('canvas'); canvas.id = 'thumbnail' + id; @@ -1579,10 +1650,7 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) { div.setAttribute('data-loaded', true); - var ring = document.createElement('div'); - ring.className = 'thumbnailSelectionRing'; ring.appendChild(canvas); - div.appendChild(ring); var ctx = canvas.getContext('2d'); ctx.save(); @@ -1608,7 +1676,7 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) { var self = this; var ctx = getPageDrawContext(); - var drawViewport = pdfPage.getViewport(scaleX); + var drawViewport = pdfPage.getViewport(scaleX, totalRotation); var renderContext = { canvasContext: ctx, viewport: drawViewport, @@ -2016,6 +2084,15 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) { PDFView.parseScale(this.value); }); + document.getElementById('page_rotate_ccw').addEventListener('click', + function() { + PDFView.rotatePages(-90); + }); + + document.getElementById('page_rotate_cw').addEventListener('click', + function() { + PDFView.rotatePages(90); + }); //#if (FIREFOX || MOZCENTRAL) //if (FirefoxCom.requestSync('getLoadingType') == 'passive') { @@ -2268,6 +2345,18 @@ window.addEventListener('keydown', function keydown(evt) { handled = true; } break; + + case 82: // 'r' + PDFView.rotatePages(90); + break; + } + } + + if (cmd == 4) { // shift-key + switch (evt.keyCode) { + case 82: // 'r' + PDFView.rotatePages(-90); + break; } }