1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-20 15:18:08 +02:00

Merge upstream.

This commit is contained in:
Brendan Dahl 2012-02-08 16:31:30 -08:00
commit a5d9ff8568
66 changed files with 6462 additions and 1424 deletions

View file

@ -224,3 +224,10 @@
}
});
})();
// Check console compatability
(function checkConsoleCompatibility() {
if (typeof console == 'undefined') {
console = {log: function() {}};
}
})();

View file

@ -20,7 +20,8 @@
height="48.000000px"
width="48.000000px"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
version="1.1"
viewbox="0 0 48 48">
<defs
id="defs3">
<inkscape:perspective

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Before After
Before After

View file

@ -16,7 +16,8 @@
id="svg2994"
height="48px"
width="48px"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs
id="defs3">
<inkscape:perspective

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Before After
Before After

View file

@ -16,7 +16,8 @@
id="svg2913"
height="48px"
width="48px"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs
id="defs3">
<inkscape:perspective

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Before After
Before After

View file

@ -19,7 +19,8 @@
inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs
id="defs3">
<inkscape:perspective

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Before After
Before After

View file

@ -19,7 +19,8 @@
inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs
id="defs3">
<inkscape:perspective

Before

Width:  |  Height:  |  Size: 8 KiB

After

Width:  |  Height:  |  Size: 8 KiB

Before After
Before After

BIN
web/images/loading-icon.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -16,7 +16,8 @@
inkscape:version="0.46"
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
sodipodi:docname="list-add.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs
id="defs6433">
<inkscape:perspective

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -16,7 +16,8 @@
inkscape:version="0.46"
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
sodipodi:docname="list-remove.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs
id="defs6433">
<inkscape:perspective

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -0,0 +1,14 @@
<!-- This snippet is used in firefox extension, see Makefile -->
<base href="resource://pdf.js/web/" />
<script type="text/javascript" id="PDFJS_SCRIPT_TAG">
<!--
// pdf.js is inlined here because resource:// urls won't work
// for loading workers.
/* PDFJSSCRIPT_INCLUDE_BUNDLE */
-->
</script>
<script type="text/javascript">
// This specifies the location of the pdf.js file.
PDFJS.isFirefoxExtension = true;
PDFJS.workerSrc = 'none';
</script>

View file

@ -9,7 +9,7 @@ body {
}
[hidden] {
display: none;
display: none !important;
}
/* === Toolbar === */
@ -241,6 +241,16 @@ canvas {
-webkit-box-shadow: 0px 2px 10px #ff0;
}
.loadingIcon {
position: absolute;
display: block;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: url('images/loading-icon.gif') center no-repeat;
}
.textLayer {
position: absolute;
left: 0;

View file

@ -2,9 +2,11 @@
<html>
<head>
<title>Simple pdf.js page viewer</title>
<!-- PDFJSSCRIPT_INCLUDE_FIREFOX_EXTENSION -->
<link rel="stylesheet" href="viewer.css"/>
<script type="text/javascript" src="compatibility.js"></script>
<script type="text/javascript" src="compatibility.js"></script> <!-- PDFJSSCRIPT_REMOVE_FIREFOX_EXTENSION -->
<!-- PDFJSSCRIPT_INCLUDE_BUILD -->
<script type="text/javascript" src="../src/core.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
@ -26,6 +28,7 @@
<script type="text/javascript" src="../src/stream.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/worker.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../external/jpgjs/jpg.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/jpx.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript">PDFJS.workerSrc = '../src/worker_loader.js';</script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="viewer.js"></script>
@ -90,7 +93,7 @@
<input id="fileInput" type="file" oncontextmenu="return false;"/>
<div class="separator"></div>
<div id="fileInputSeperator" class="separator"></div>
<a href="#" id="viewBookmark" title="Bookmark (or copy) current location">
<img src="images/bookmark.svg" alt="Bookmark" align="top" height="16"/>

View file

@ -6,6 +6,7 @@
var kDefaultURL = 'compressed.tracemonkey-pldi-09.pdf';
var kDefaultScale = 'auto';
var kDefaultScaleDelta = 1.1;
var kUnknownScale = 0;
var kCacheSize = 20;
var kCssUnits = 96.0 / 72.0;
var kScrollbarPadding = 40;
@ -61,34 +62,54 @@ var RenderingQueue = (function RenderingQueueClosure() {
return RenderingQueue;
})();
var FirefoxCom = (function FirefoxComClosure() {
return {
/**
* Creates an event that hopefully the extension is listening for and will
* synchronously respond to.
* @param {String} action The action to trigger.
* @param {String} data Optional data to send.
* @return {*} The response.
*/
request: function(action, data) {
var request = document.createTextNode('');
request.setUserData('action', action, null);
request.setUserData('data', data, null);
document.documentElement.appendChild(request);
var sender = document.createEvent('Events');
sender.initEvent('pdf.js.message', true, false);
request.dispatchEvent(sender);
var response = request.getUserData('response');
document.documentElement.removeChild(request);
return response;
}
};
})();
// Settings Manager - This is a utility for saving settings
// First we see if localStorage is available, FF bug #495747
// First we see if localStorage is available
// If not, we use FUEL in FF
var Settings = (function SettingsClosure() {
var isLocalStorageEnabled = (function localStorageEnabledTest() {
// Feature test as per http://diveintohtml5.info/storage.html
// The additional localStorage call is to get around a FF quirk, see
// bug #495747 in bugzilla
try {
localStorage;
return 'localStorage' in window && window['localStorage'] !== null &&
localStorage;
} catch (e) {
return false;
}
return true;
})();
var extPrefix = 'extensions.uriloader@pdf.js';
var isExtension = location.protocol == 'chrome:' && !isLocalStorageEnabled;
var inPrivateBrowsing = false;
if (isExtension) {
var pbs = Components.classes['@mozilla.org/privatebrowsing;1']
.getService(Components.interfaces.nsIPrivateBrowsingService);
inPrivateBrowsing = pbs.privateBrowsingEnabled;
}
var isFirefoxExtension = PDFJS.isFirefoxExtension;
function Settings(fingerprint) {
var database = null;
var index;
if (inPrivateBrowsing)
return false;
else if (isExtension)
database = Application.prefs.getValue(extPrefix + '.database', '{}');
if (isFirefoxExtension)
database = FirefoxCom.request('getDatabase', null) || '{}';
else if (isLocalStorageEnabled)
database = localStorage.getItem('database') || '{}';
else
@ -110,31 +131,27 @@ var Settings = (function SettingsClosure() {
index = database.files.push({fingerprint: fingerprint}) - 1;
this.file = database.files[index];
this.database = database;
if (isExtension)
Application.prefs.setValue(extPrefix + '.database',
JSON.stringify(database));
else if (isLocalStorageEnabled)
localStorage.setItem('database', JSON.stringify(database));
}
Settings.prototype = {
set: function settingsSet(name, val) {
if (inPrivateBrowsing)
if (!('file' in this))
return false;
var file = this.file;
file[name] = val;
if (isExtension)
Application.prefs.setValue(extPrefix + '.database',
JSON.stringify(this.database));
var database = JSON.stringify(this.database);
if (isFirefoxExtension)
FirefoxCom.request('setDatabase', database);
else if (isLocalStorageEnabled)
localStorage.setItem('database', JSON.stringify(this.database));
localStorage.setItem('database', database);
},
get: function settingsGet(name, defaultValue) {
if (inPrivateBrowsing)
if (!('file' in this))
return defaultValue;
else
return this.file[name] || defaultValue;
return this.file[name] || defaultValue;
}
};
@ -148,7 +165,7 @@ var currentPageNumber = 1;
var PDFView = {
pages: [],
thumbnails: [],
currentScale: 0,
currentScale: kUnknownScale,
currentScaleValue: null,
initialBookmark: document.location.hash.substring(1),
@ -203,12 +220,12 @@ var PDFView = {
zoomIn: function pdfViewZoomIn() {
var newScale = Math.min(kMaxScale, this.currentScale * kDefaultScaleDelta);
this.setScale(newScale, true);
this.parseScale(newScale, true);
},
zoomOut: function pdfViewZoomOut() {
var newScale = Math.max(kMinScale, this.currentScale / kDefaultScaleDelta);
this.setScale(newScale, true);
this.parseScale(newScale, true);
},
set page(val) {
@ -258,7 +275,7 @@ var PDFView = {
},
error: function getPdfError(e) {
var loadingIndicator = document.getElementById('loading');
loadingIndicator.innerHTML = 'Error';
loadingIndicator.textContent = 'Error';
var moreInfo = {
message: 'Unexpected server response of ' + e.target.status + '.'
};
@ -273,7 +290,13 @@ var PDFView = {
},
download: function pdfViewDownload() {
window.open(this.url + '#pdfjs.action=download', '_parent');
var url = this.url.split('#')[0];
if (PDFJS.isFirefoxExtension) {
FirefoxCom.request('download', url);
} else {
url += '#pdfjs.action=download', '_parent';
window.open(url, '_parent');
}
},
navigateTo: function pdfViewNavigateTo(dest) {
@ -294,14 +317,14 @@ var PDFView = {
getDestinationHash: function pdfViewGetDestinationHash(dest) {
if (typeof dest === 'string')
return '#' + escape(dest);
return PDFView.getAnchorUrl('#' + escape(dest));
if (dest instanceof Array) {
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) {
var pdfOpenParams = '#page=' + pageNumber;
var pdfOpenParams = PDFView.getAnchorUrl('#page=' + pageNumber);
var destKind = dest[1];
if ('name' in destKind && destKind.name == 'XYZ') {
var scale = (dest[4] || this.currentScale);
@ -316,6 +339,17 @@ var PDFView = {
return '';
},
/**
* For the firefox extension we prefix the full url on anchor links so they
* don't come up as resource:// urls and so open in new tab/window works.
* @param {String} anchor The anchor hash include the #.
*/
getAnchorUrl: function getAnchorUrl(anchor) {
if (PDFJS.isFirefoxExtension)
return this.url.split('#')[0] + anchor;
return anchor;
},
/**
* Show the error box.
* @param {String} message A message that is human readable.
@ -328,7 +362,7 @@ var PDFView = {
errorWrapper.removeAttribute('hidden');
var errorMessage = document.getElementById('errorMessage');
errorMessage.innerHTML = message;
errorMessage.textContent = message;
var closeButton = document.getElementById('errorClose');
closeButton.onclick = function() {
@ -354,8 +388,14 @@ var PDFView = {
if (moreInfo) {
errorMoreInfo.value += 'Message: ' + moreInfo.message;
if (moreInfo.stack)
if (moreInfo.stack) {
errorMoreInfo.value += '\n' + 'Stack: ' + moreInfo.stack;
} else {
if (moreInfo.filename)
errorMoreInfo.value += '\n' + 'File: ' + moreInfo.filename;
if (moreInfo.lineNumber)
errorMoreInfo.value += '\n' + 'Line: ' + moreInfo.lineNumber;
}
}
errorMoreInfo.rows = errorMoreInfo.value.split('\n').length - 1;
},
@ -363,7 +403,7 @@ var PDFView = {
progress: function pdfViewProgress(level) {
var percent = Math.round(level * 100);
var loadingIndicator = document.getElementById('loading');
loadingIndicator.innerHTML = 'Loading... ' + percent + '%';
loadingIndicator.textContent = 'Loading... ' + percent + '%';
},
load: function pdfViewLoad(data, scale) {
@ -403,7 +443,7 @@ var PDFView = {
var pagesCount = pdf.numPages;
var id = pdf.fingerprint;
var storedHash = null;
document.getElementById('numPages').innerHTML = pagesCount;
document.getElementById('numPages').textContent = pagesCount;
document.getElementById('pageNumber').max = pagesCount;
PDFView.documentFingerprint = id;
var store = PDFView.store = new Settings(id);
@ -453,10 +493,16 @@ var PDFView = {
}
else if (storedHash)
this.setHash(storedHash);
else {
this.parseScale(scale || kDefaultScale, true);
else if (scale) {
this.parseScale(scale, true);
this.page = 1;
}
if (PDFView.currentScale === kUnknownScale) {
// Scale was not initialized: invalid bookmark or scale was not specified.
// Setting the default one.
this.parseScale(kDefaultScale, true);
}
},
setHash: function pdfViewSetHash(hash) {
@ -612,6 +658,10 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
div.removeAttribute('data-loaded');
delete this.canvas;
this.loadingIconDiv = document.createElement('div');
this.loadingIconDiv.className = 'loadingIcon';
div.appendChild(this.loadingIconDiv);
};
function setupAnnotations(content, scale) {
@ -649,7 +699,15 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
if (!item.content) {
content.setAttribute('hidden', true);
} else {
text.innerHTML = item.content.replace('\n', '<br />');
var e = document.createElement('span');
var lines = item.content.split('\n');
for (var i = 0, ii = lines.length; i < ii; ++i) {
var line = lines[i];
e.appendChild(document.createTextNode(line));
if (i < (ii - 1))
e.appendChild(document.createElement('br'));
}
text.appendChild(e);
image.addEventListener('mouseover', function annotationImageOver() {
this.nextSibling.removeAttribute('hidden');
}, false);
@ -743,6 +801,8 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
if (scale && scale !== PDFView.currentScale)
PDFView.parseScale(scale, true);
else if (PDFView.currentScale === kUnknownScale)
PDFView.parseScale(kDefaultScale, true);
setTimeout(function pageViewScrollIntoViewRelayout() {
// letting page to re-layout before scrolling
@ -766,7 +826,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
};
this.drawingRequired = function() {
return !div.hasChildNodes();
return !div.querySelector('canvas');
};
this.draw = function pageviewDraw(callback) {
@ -801,19 +861,23 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
ctx.restore();
ctx.translate(-this.x * scale, -this.y * scale);
this.content.startRendering(ctx,
(function pageViewDrawCallback(error) {
if (error)
PDFView.error('An error occurred while rendering the page.', error);
this.stats = content.bench;
this.updateStats();
if (this.onAfterDraw)
this.onAfterDraw();
// Rendering area
cache.push(this);
callback();
}).bind(this), textLayer
);
var self = this;
this.content.startRendering(ctx, function pageViewDrawCallback(error) {
div.removeChild(self.loadingIconDiv);
if (error)
PDFView.error('An error occurred while rendering the page.', error);
self.stats = content.bench;
self.updateStats();
if (self.onAfterDraw)
self.onAfterDraw();
cache.push(self);
callback();
}, textLayer);
setupAnnotations(this.content, this.scale);
div.setAttribute('data-loaded', true);
@ -831,7 +895,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
var anchor = document.createElement('a');
anchor.href = '#' + id;
anchor.href = PDFView.getAnchorUrl('#page=' + id);
anchor.onclick = function stopNivigation() {
PDFView.page = id;
return false;
@ -963,22 +1027,55 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
var self = this;
var textDivs = this.textDivs;
var textLayerDiv = this.textLayerDiv;
this.textLayerTimer = setInterval(function renderTextLayer() {
var renderTimer = null;
var renderingDone = false;
var renderInterval = 0;
var resumeInterval = 500; // in ms
// Render the text layer, one div at a time
function renderTextLayer() {
if (textDivs.length === 0) {
clearInterval(self.textLayerTimer);
clearInterval(renderTimer);
renderingDone = true;
return;
}
var textDiv = textDivs.shift();
if (textDiv.dataset.textLength >= 1) { // avoid div by zero
if (textDiv.dataset.textLength > 0) {
textLayerDiv.appendChild(textDiv);
// Adjust div width (via letterSpacing) to match canvas text
// Due to the .offsetWidth calls, this is slow
textDiv.style.letterSpacing =
((textDiv.dataset.canvasWidth - textDiv.offsetWidth) /
(textDiv.dataset.textLength - 1)) + 'px';
if (textDiv.dataset.textLength > 1) { // avoid div by zero
// Adjust div width (via letterSpacing) to match canvas text
// Due to the .offsetWidth calls, this is slow
// This needs to come after appending to the DOM
textDiv.style.letterSpacing =
((textDiv.dataset.canvasWidth - textDiv.offsetWidth) /
(textDiv.dataset.textLength - 1)) + 'px';
}
} // textLength > 0
}
renderTimer = setInterval(renderTextLayer, renderInterval);
// Stop rendering when user scrolls. Resume after XXX milliseconds
// of no scroll events
var scrollTimer = null;
function textLayerOnScroll() {
if (renderingDone) {
window.removeEventListener('scroll', textLayerOnScroll, false);
return;
}
}, 0);
};
// Immediately pause rendering
clearInterval(renderTimer);
clearTimeout(scrollTimer);
scrollTimer = setTimeout(function textLayerScrollTimer() {
// Resume rendering
renderTimer = setInterval(renderTextLayer, renderInterval);
}, resumeInterval);
}; // textLayerOnScroll
window.addEventListener('scroll', textLayerOnScroll, false);
}; // endLayout
this.appendText = function textLayerBuilderAppendText(text,
fontName, fontSize) {
@ -1006,12 +1103,18 @@ window.addEventListener('load', function webViewerLoad(evt) {
}
var scale = ('scale' in params) ? params.scale : 0;
PDFView.open(params.file || kDefaultURL, parseFloat(scale));
var file = PDFJS.isFirefoxExtension ?
window.location.toString() : params.file || kDefaultURL;
PDFView.open(file, parseFloat(scale));
if (!window.File || !window.FileReader || !window.FileList || !window.Blob)
if (PDFJS.isFirefoxExtension || !window.File || !window.FileReader ||
!window.FileList || !window.Blob) {
document.getElementById('fileInput').setAttribute('hidden', 'true');
else
document.getElementById('fileInputSeperator')
.setAttribute('hidden', 'true');
} else {
document.getElementById('fileInput').value = null;
}
if ('disableWorker' in params)
PDFJS.disableWorker = (params['disableWorker'] === 'true');
@ -1101,8 +1204,8 @@ function updateViewarea() {
store.set('zoom', normalizedScaleValue);
store.set('scrollLeft', Math.round(topLeft.x));
store.set('scrollTop', Math.round(topLeft.y));
document.getElementById('viewBookmark').href = pdfOpenParams;
var href = PDFView.getAnchorUrl(pdfOpenParams);
document.getElementById('viewBookmark').href = href;
}
window.addEventListener('scroll', function webViewerScroll(evt) {
@ -1242,7 +1345,7 @@ window.addEventListener('keydown', function keydown(evt) {
handled = true;
break;
case 48: // '0'
PDFView.setScale(kDefaultScale, true);
PDFView.parseScale(kDefaultScale, true);
handled = true;
break;
case 37: // left arrow