From b54be346b59b868c473a985242271e7e1f5696d4 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Fri, 14 Oct 2011 21:05:57 -0500 Subject: [PATCH 1/9] Add "bookmark" icon; and fixing scale/ current page number issues --- pdf.js | 5 +- web/images/bookmark.svg | 661 ++++++++++++++++++++++++++++++++++++++++ web/viewer.css | 4 + web/viewer.html | 4 + web/viewer.js | 98 ++++-- 5 files changed, 748 insertions(+), 24 deletions(-) create mode 100644 web/images/bookmark.svg diff --git a/pdf.js b/pdf.js index 3ebddd119..84ddd3800 100644 --- a/pdf.js +++ b/pdf.js @@ -3634,8 +3634,8 @@ var Page = (function pagePage() { gfx.execute(this.code, xref, resources); gfx.endDrawing(); }, - rotatePoint: function pageRotatePoint(x, y) { - var rotate = this.rotate; + rotatePoint: function pageRotatePoint(x, y, reverse) { + var rotate = reverse ? (360 - this.rotate) : this.rotate; switch (rotate) { case 180: return {x: this.width - x, y: y}; @@ -3643,6 +3643,7 @@ var Page = (function pagePage() { return {x: this.width - y, y: this.height - x}; case 270: return {x: y, y: x}; + case 360: case 0: default: return {x: x, y: this.height - y}; diff --git a/web/images/bookmark.svg b/web/images/bookmark.svg new file mode 100644 index 000000000..2c1fa130d --- /dev/null +++ b/web/images/bookmark.svg @@ -0,0 +1,661 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + New Bookmark + + + bookmark + remember + favorite + + + + + + Andreas Nilsson + + + + + + Jakub Steiner + + + create bookmark action + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/viewer.css b/web/viewer.css index e72bdc286..6c7b551e8 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -34,6 +34,10 @@ body { margin: 4px; } +#controls > a > img { + margin: 2px; +} + #controls > button { line-height: 32px; } diff --git a/web/viewer.html b/web/viewer.html index 160c5ce57..1f34fe01c 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -70,6 +70,10 @@
+ + Bookmark + + -- diff --git a/web/viewer.js b/web/viewer.js index 93f6acd31..6e43d6832 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -89,16 +89,23 @@ var PDFView = { var pages = this.pages; var input = document.getElementById('pageNumber'); if (!(0 < val && val <= pages.length)) { - input.value = this.page; + var event = document.createEvent('UIEvents'); + event.initUIEvent('pagechange', false, false, window, 0); + event.pageNumber = this.page; + window.dispatchEvent(event); return; } currentPageNumber = val; - document.getElementById('previous').disabled = (val == 1); - document.getElementById('next').disabled = (val == pages.length); - if (input.value != val) { - input.value = val; - } + var event = document.createEvent('UIEvents'); + event.initUIEvent('pagechange', false, false, window, 0); + event.pageNumber = val; + window.dispatchEvent(event); + + // checking if the this.page was called from the updateViewarea function: + // avoiding the creation of two "set page" method (internal and public) + if (updateViewarea.inProgress) + return; pages[val - 1].scrollIntoView(); }, @@ -147,12 +154,20 @@ var PDFView = { if (typeof dest === 'string') return '#' + escape(dest); if (dest instanceof Array) { - var destRef = dest[0]; // see nevigateTo method for dest format + var destRef = dest[0]; // see navigateTo method for dest format var pageNumber = destRef instanceof Object ? this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : (destRef + 1); if (pageNumber) { - return '#page=' + pageNumber + '&dest=' + dest.slice(1).join(','); + var pdfOpenParams = '#page=' + pageNumber; + if (isName(dest[1], 'XYZ')) { + var scale = (dest[4] || this.currentScale); + pdfOpenParams += '&zoom=' + (scale * 100); + if (dest[2] || dest[3]) { + pdfOpenParams += ',' + (dest[2] || 0) + ',' + (dest[3] || 0); + } + } + return pdfOpenParams; } } return ''; @@ -226,10 +241,32 @@ var PDFView = { return; if (hash.indexOf('=') >= 0) { - // TODO more complex hashes, for now catching page=XX only - var m = /\bpage=(\d+)/.exec(hash); - if (m && m[1] > 0) - this.page = m[1]; + // parsing query string + var paramsPairs = hash.split('&'); + var params = {}; + for (var i = 0; i < paramsPairs.length; ++i) { + var paramPair = paramsPairs[i].split('='); + params[paramPair[0]] = paramPair[1]; + } + // borrowing syntax from "Parameters for Opening PDF Files" + if ('nameddest' in params) { + PDFView.navigateTo(params.nameddest); + return; + } + if ('page' in params) { + var pageNumber = (params.page | 0) || 1; + this.page = pageNumber; + if ('zoom' in params) { + var zoomArgs = params.zoom.split(','); // scale,left,top + // building destination array + var dest = [null, new Name('XYZ'), (zoomArgs[1] | 0), + (zoomArgs[2] | 0), (zoomArgs[0] | 0) / 100]; + var currentPage = this.pages[pageNumber - 1]; + currentPage.scrollIntoView(dest); + } else + this.page = page; // simple page + return; + } } else if (/^\d+$/.test(hash)) // page number this.page = hash; else // named destination @@ -339,6 +376,11 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, } } + this.getPagePoint = function pageViewGetPagePoint(x, y) { + var scale = PDFView.currentScale; + return this.content.rotatePoint(x / scale, y / scale); + }; + this.scrollIntoView = function pageViewScrollIntoView(dest) { if (!dest) { div.scrollIntoView(true); @@ -388,7 +430,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, this.content.rotatePoint(x + width, y + height) ]; - if (scale) + if (scale && scale !== PDFView.currentScale) PDFView.setScale(scale, true); setTimeout(function pageViewScrollIntoViewRelayout() { @@ -575,13 +617,21 @@ function updateViewarea() { if (!visiblePages.length) return; + updateViewarea.inProgress = true; // used in "set page" var currentId = PDFView.page; var firstPage = visiblePages[0]; - var lastPage = visiblePages[visiblePages.length - 1]; - if (currentId > lastPage.id && lastPage.y > window.pageYOffset) - PDFView.page = lastPage.id; - else if (currentId < firstPage.id) - PDFView.page = firstPage.id; + PDFView.page = firstPage.id; + updateViewarea.inProgress = false; + + var kViewerTopMargin = 52; + var pageNumber = firstPage.id; + var pdfOpenParams = '#page=' + pageNumber; + pdfOpenParams += '&zoom=' + Math.round(PDFView.currentScale * 100); + var currentPage = PDFView.pages[pageNumber - 1]; + var topLeft = currentPage.getPagePoint(window.pageXOffset, + window.pageYOffset - firstPage.y - kViewerTopMargin); + pdfOpenParams += ',' + Math.round(topLeft.x) + ',' + Math.round(topLeft.y); + document.getElementById('viewBookmark').href = pdfOpenParams; } window.addEventListener('scroll', function webViewerScroll(evt) { @@ -622,6 +672,9 @@ window.addEventListener('change', function webViewerChange(evt) { fileReader.readAsBinaryString(file); document.title = file.name; + + // URL does not reflect proper document location - hiding bookmark icon. + document.getElementById('viewBookmark').style.display = 'none'; }, true); window.addEventListener('transitionend', function webViewerTransitionend(evt) { @@ -672,10 +725,11 @@ window.addEventListener('scalechange', function scalechange(evt) { }, true); window.addEventListener('pagechange', function pagechange(evt) { - var page = evt.detail; - document.getElementById('pageNumber').value = page; - document.getElementById('previous').disabled = (page == 1); - document.getElementById('next').disabled = (page == PDFView.pages.length); + var page = evt.pageNumber; + if (document.getElementById('pageNumber').value != page) + document.getElementById('pageNumber').value = page; + document.getElementById('previous').disabled = (page <= 1); + document.getElementById('next').disabled = (page >= PDFView.pages.length); }, true); window.addEventListener('keydown', function keydown(evt) { From 931192fb79d03746626ef35312d5fc925c02b8d8 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 18 Oct 2011 01:28:57 +0200 Subject: [PATCH 2/9] Remove useless code since the extension is loaded into a privileged chrome:// scope --- .../firefox/components/pdfContentHandler.js | 105 +----------------- web/viewer.js | 15 --- 2 files changed, 2 insertions(+), 118 deletions(-) diff --git a/extensions/firefox/components/pdfContentHandler.js b/extensions/firefox/components/pdfContentHandler.js index 9186bfd8a..eda0ec92c 100644 --- a/extensions/firefox/components/pdfContentHandler.js +++ b/extensions/firefox/components/pdfContentHandler.js @@ -20,105 +20,6 @@ function log(aMsg) { dump(msg + '\n'); } -function fireEventTo(aName, aData, aWindow) { - let window = aWindow.wrappedJSObject; - let evt = window.document.createEvent('CustomEvent'); - evt.initCustomEvent('pdf' + aName, false, false, aData); - window.document.dispatchEvent(evt); -} - -function loadDocument(aWindow, aDocumentUrl) { - let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1'] - .createInstance(Ci.nsIXMLHttpRequest); - xhr.onprogress = function updateProgress(evt) { - if (evt.lengthComputable) - fireEventTo(evt.type, evt.loaded / evt.total, aWindow); - }; - - xhr.onerror = function error(evt) { - fireEventTo(evt.type, false, aWindow); - }; - - xhr.onload = function load(evt) { - let data = (xhr.mozResponseArrayBuffer || xhr.mozResponse || - xhr.responseArrayBuffer || xhr.response); - try { - let view = new Uint8Array(data); - - let window = aWindow.wrappedJSObject; - let arrayBuffer = new window.ArrayBuffer(data.byteLength); - let view2 = new window.Uint8Array(arrayBuffer); - view2.set(view); - - fireEventTo(evt.type, arrayBuffer, aWindow); - } catch (e) { - log('Error - ' + e); - } - }; - - xhr.open('GET', aDocumentUrl); - xhr.responseType = 'arraybuffer'; - xhr.send(null); -} - -let WebProgressListener = { - init: function WebProgressListenerInit(aWindow, aUrl) { - this._locationHasChanged = false; - this._documentUrl = aUrl; - - let flags = Ci.nsIWebProgress.NOTIFY_LOCATION | - Ci.nsIWebProgress.NOTIFY_STATE_NETWORK | - Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT; - - let docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell); - let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebProgress); - try { - webProgress.removeProgressListener(this); - } catch (e) {} - webProgress.addProgressListener(this, flags); - }, - - onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, - aStatus) { - const complete = Ci.nsIWebProgressListener.STATE_IS_WINDOW + - Ci.nsIWebProgressListener.STATE_STOP; - if ((aStateFlags & complete) == complete && this._locationHasChanged) { - aWebProgress.removeProgressListener(this); - loadDocument(aWebProgress.DOMWindow, this._documentUrl); - } - }, - - onProgressChange: function onProgressChange(aWebProgress, aRequest, aCurSelf, - aMaxSelf, aCurTotal, aMaxTotal) { - }, - - onLocationChange: function onLocationChange(aWebProgress, aRequest, - aLocationURI) { - this._locationHasChanged = true; - }, - - onStatusChange: function onStatusChange(aWebProgress, aRequest, aStatus, - aMessage) { - }, - - onSecurityChange: function onSecurityChange(aWebProgress, aRequest, aState) { - }, - - QueryInterface: function QueryInterface(aIID) { - if (aIID.equals(Ci.nsIWebProgressListener) || - aIID.equals(Ci.nsISupportsWeakReference) || - aIID.equals(Ci.nsISupports)) { - return this; - } - - throw Components.results.NS_ERROR_NO_INTERFACE; - } -}; - - function pdfContentHandler() { } @@ -139,12 +40,11 @@ pdfContentHandler.prototype = { aRequest.cancel(Cr.NS_BINDING_ABORTED); let uri = aRequest.URI; - window = callbacks.getInterface(Ci.nsIDOMWindow); - WebProgressListener.init(window, uri.spec); - try { let url = Services.prefs.getCharPref('extensions.pdf.js.url'); url = url.replace('%s', uri.spec); + + window = callbacks.getInterface(Ci.nsIDOMWindow); window.location = url; } catch (e) { log('Error retrieving the pdf.js base url - ' + e); @@ -157,4 +57,3 @@ pdfContentHandler.prototype = { var NSGetFactory = XPCOMUtils.generateNSGetFactory([pdfContentHandler]); - diff --git a/web/viewer.js b/web/viewer.js index 91562baf4..4008d58e1 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -108,9 +108,6 @@ var PDFView = { }, open: function pdfViewOpen(url, scale) { - if (url.indexOf('http') == 0) - return; - document.title = url; getPdf( @@ -555,18 +552,6 @@ window.addEventListener('load', function webViewerLoad(evt) { document.getElementById('fileInput').value = null; }, true); -window.addEventListener('pdfload', function webViewerPdfload(evt) { - PDFView.load(evt.detail); -}, true); - -window.addEventListener('pdfprogress', function webViewerPdfProgress(evt) { - PDFView.progress(evt.detail); -}, true); - -window.addEventListener('pdferror', function webViewerPdfError(evt) { - PDFView.error(); -}, true); - function updateViewarea() { var visiblePages = PDFView.getVisiblePages(); for (var i = 0; i < visiblePages.length; i++) { From e347ad03d97599588aa9be0f134f665f4b7b46de Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 18 Oct 2011 01:34:44 +0200 Subject: [PATCH 3/9] Fix a small broking mistake in fonts.js --- fonts.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fonts.js b/fonts.js index bcec5d2ac..2bcfa5e6e 100644 --- a/fonts.js +++ b/fonts.js @@ -2613,14 +2613,13 @@ var Type2CFF = (function type2CFF() { var glyph = charsets[i]; var code = glyphMap[glyph] || 0; - var mapping = glyphs[code] || glyphs[glyph] || {}; + var mapping = glyphs[code] || glyphs[glyph] || { width: defaultWidth }; var unicode = mapping.unicode; if (unicode <= 0x1f || (unicode >= 127 && unicode <= 255)) unicode += kCmapGlyphOffset; - var width = ('width' in mapping) && isNum(mapping.width) ? mapping.width - : defaultWidth; + var width = isNum(mapping.width) ? mapping.width : defaultWidth; properties.encoding[code] = { unicode: unicode, width: width From b8a5b76db5cd20dfba5891e9f70de27fe46aa46f Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 18 Oct 2011 03:45:07 +0200 Subject: [PATCH 4/9] Fix a spacing issue --- fonts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fonts.js b/fonts.js index 2bcfa5e6e..2ba6e2f7a 100644 --- a/fonts.js +++ b/fonts.js @@ -1329,7 +1329,7 @@ var Font = (function Font() { // Character to glyphs mapping 'cmap': createCMapTable(charstrings.slice(), - ('glyphIds' in font) ? font.glyphIds: null), + ('glyphIds' in font) ? font.glyphIds : null), // Font header 'head': (function fontFieldsHead() { From 20efacb3a1e2c137e7f7ef934bd8590331b21ece Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 18 Oct 2011 21:40:59 +0200 Subject: [PATCH 5/9] Use 'hidden' instead of display: none --- web/viewer.css | 4 ++++ web/viewer.html | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/web/viewer.css b/web/viewer.css index 6c7b551e8..040b87bdf 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -8,6 +8,10 @@ body { padding: 0px; } +[hidden] { + display: none; +} + /* === Toolbar === */ #controls { background-color: #eee; diff --git a/web/viewer.html b/web/viewer.html index f761c94fe..4175d29fc 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -82,7 +82,7 @@
-