Merge pull request #990 from notmasteryet/concurload

Fixes concurrent pages loading (#974 and #626)
This commit is contained in:
Brendan Dahl 2011-12-30 09:40:12 -08:00
commit 9fd41e11da
3 changed files with 181 additions and 17 deletions

View File

@ -527,6 +527,13 @@ var PDFDocModel = (function PDFDocModelClosure() {
this.startXRef,
this.mainXRefEntriesOffset);
this.catalog = new Catalog(this.xref);
if (this.xref.trailer && this.xref.trailer.has('ID')) {
var fileID = '';
this.xref.trailer.get('ID')[0].split('').forEach(function(el) {
fileID += Number(el.charCodeAt(0)).toString(16);
});
this.fileID = fileID;
}
},
get numPages() {
var linearization = this.linearization;
@ -534,6 +541,22 @@ var PDFDocModel = (function PDFDocModelClosure() {
// shadow the prototype getter
return shadow(this, 'numPages', num);
},
getFingerprint: function pdfDocGetFingerprint() {
if (this.fileID) {
return this.fileID;
} else {
// If we got no fileID, then we generate one,
// from the first 100 bytes of PDF
var data = this.stream.bytes.subarray(0, 100);
var hash = calculateMD5(data, 0, data.length);
var strHash = '';
for (var i = 0, length = hash.length; i < length; i++) {
strHash += Number(hash[i]).toString(16);
}
return strHash;
}
},
getPage: function pdfDocGetPage(n) {
return this.catalog.getPage(n);
}
@ -560,7 +583,7 @@ var PDFDoc = (function PDFDocClosure() {
this.data = data;
this.stream = stream;
this.pdf = new PDFDocModel(stream);
this.fingerprint = this.pdf.getFingerprint();
this.catalog = this.pdf.catalog;
this.objs = new PDFObjects();

View File

@ -269,7 +269,7 @@ var XRef = (function XRefClosure() {
this.entries = [];
this.xrefstms = {};
var trailerDict = this.readXRef(startXRef);
this.trailer = trailerDict;
// prepare the XRef cache
this.cache = [];

View File

@ -12,6 +12,7 @@ var kScrollbarPadding = 40;
var kMinScale = 0.25;
var kMaxScale = 4.0;
var kImageDirectory = './images/';
var kSettingsMemory = 20;
var Cache = function cacheCache(size) {
var data = [];
@ -25,13 +26,126 @@ var Cache = function cacheCache(size) {
};
};
var RenderingQueue = (function RenderingQueueClosure() {
function RenderingQueue() {
this.items = [];
}
RenderingQueue.prototype = {
enqueueDraw: function RenderingQueueEnqueueDraw(item) {
if ('rendering' in item)
return; // is already in the queue
item.rendering = true;
this.items.push(item);
if (this.items.length > 1)
return; // not first item
item.draw(this.continueExecution.bind(this));
},
continueExecution: function RenderingQueueContinueExecution() {
var item = this.items.shift();
delete item.rendering;
if (this.items.length == 0)
return; // queue is empty
item = this.items[0];
item.draw(this.continueExecution.bind(this));
}
};
return RenderingQueue;
})();
// Settings Manager - This is a utility for saving settings
// First we see if localStorage is available, FF bug #495747
// If not, we use FUEL in FF
var Settings = (function SettingsClosure() {
var isLocalStorageEnabled = (function localStorageEnabledTest() {
try {
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;
}
function Settings(fingerprint) {
var database = null;
var index;
if (inPrivateBrowsing)
return false;
else if (isExtension)
database = Application.prefs.getValue(extPrefix + '.database', '{}');
else if (isLocalStorageEnabled)
database = localStorage.getItem('database') || '{}';
else
return false;
database = JSON.parse(database);
if (!('files' in database))
database.files = [];
if (database.files.length >= kSettingsMemory)
database.files.shift();
for (var i = 0, length = database.files.length; i < length; i++) {
var branch = database.files[i];
if (branch.fingerprint == fingerprint) {
index = i;
break;
}
}
if (typeof index != 'number')
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)
return false;
var file = this.file;
file[name] = val;
if (isExtension)
Application.prefs.setValue(extPrefix + '.database',
JSON.stringify(this.database));
else if (isLocalStorageEnabled)
localStorage.setItem('database', JSON.stringify(this.database));
},
get: function settingsGet(name, defaultValue) {
if (inPrivateBrowsing)
return defaultValue;
else
return this.file[name] || defaultValue;
}
};
return Settings;
})();
var cache = new Cache(kCacheSize);
var renderingQueue = new RenderingQueue();
var currentPageNumber = 1;
var PDFView = {
pages: [],
thumbnails: [],
currentScale: kDefaultScale,
currentScale: 0,
initialBookmark: document.location.hash.substring(1),
setScale: function pdfViewSetScale(val, resetAutoSettings) {
@ -272,8 +386,20 @@ var PDFView = {
this.error('An error occurred while reading the PDF.', e);
}
var pagesCount = pdf.numPages;
var id = pdf.fingerprint;
var storedHash = null;
document.getElementById('numPages').innerHTML = pagesCount;
document.getElementById('pageNumber').max = pagesCount;
PDFView.documentFingerprint = id;
var store = PDFView.store = new Settings(id);
if (store.get('exists', false)) {
var page = store.get('page', '1');
var zoom = store.get('zoom', PDFView.currentScale);
var left = store.get('scrollLeft', '0');
var top = store.get('scrollTop', '0');
storedHash = 'page=' + page + '&zoom=' + zoom + ',' + left + ',' + top;
}
var pages = this.pages = [];
var pagesRefMap = {};
@ -294,7 +420,6 @@ var PDFView = {
this.pagesRefMap = pagesRefMap;
this.destinations = pdf.catalog.destinations;
this.setScale(scale || kDefaultScale, true);
if (pdf.catalog.documentOutline) {
this.outline = new DocumentOutlineView(pdf.catalog.documentOutline);
@ -307,8 +432,12 @@ var PDFView = {
this.setHash(this.initialBookmark);
this.initialBookmark = null;
}
else
else if (storedHash)
this.setHash(storedHash);
else {
this.setScale(scale || kDefaultScale, true);
this.page = 1;
}
},
setHash: function pdfViewSetHash(hash) {
@ -334,7 +463,7 @@ var PDFView = {
if ('zoom' in params) {
var zoomArgs = params.zoom.split(','); // scale,left,top
// building destination array
var dest = [null, new Name('XYZ'), (zoomArgs[1] | 0),
var dest = [null, {name: 'XYZ'}, (zoomArgs[1] | 0),
(zoomArgs[2] | 0), (zoomArgs[0] | 0) / 100];
var currentPage = this.pages[pageNumber - 1];
currentPage.scrollIntoView(dest);
@ -609,10 +738,11 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
}, 0);
};
this.draw = function pageviewDraw() {
this.draw = function pageviewDraw(callback) {
if (div.hasChildNodes()) {
this.updateStats();
return false;
callback();
return;
}
var canvas = document.createElement('canvas');
@ -644,13 +774,14 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
this.updateStats();
if (this.onAfterDraw)
this.onAfterDraw();
cache.push(this);
callback();
}).bind(this), textLayer
);
setupAnnotations(this.content, this.scale);
div.setAttribute('data-loaded', true);
return true;
};
this.updateStats = function pageViewUpdateStats() {
@ -717,12 +848,16 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
return ctx;
}
this.draw = function thumbnailViewDraw() {
if (this.hasImage)
this.draw = function thumbnailViewDraw(callback) {
if (this.hasImage) {
callback();
return;
}
var ctx = getPageDrawContext();
page.startRendering(ctx, function thumbnailViewDrawStartRendering() {});
page.startRendering(ctx, function thumbnailViewDrawStartRendering() {
callback();
});
this.hasImage = true;
};
@ -805,8 +940,7 @@ function updateViewarea() {
var visiblePages = PDFView.getVisiblePages();
for (var i = 0; i < visiblePages.length; i++) {
var page = visiblePages[i];
if (PDFView.pages[page.id - 1].draw())
cache.push(page.view);
renderingQueue.enqueueDraw(PDFView.pages[page.id - 1]);
}
if (!visiblePages.length)
@ -826,6 +960,14 @@ function updateViewarea() {
var topLeft = currentPage.getPagePoint(window.pageXOffset,
window.pageYOffset - firstPage.y - kViewerTopMargin);
pdfOpenParams += ',' + Math.round(topLeft.x) + ',' + Math.round(topLeft.y);
var store = PDFView.store;
store.set('exists', true);
store.set('page', pageNumber);
store.set('zoom', Math.round(PDFView.currentScale * 100));
store.set('scrollLeft', Math.round(topLeft.x));
store.set('scrollTop', Math.round(topLeft.y));
document.getElementById('viewBookmark').href = pdfOpenParams;
}
@ -848,7 +990,7 @@ function updateThumbViewArea() {
var visibleThumbs = PDFView.getVisibleThumbs();
for (var i = 0; i < visibleThumbs.length; i++) {
var thumb = visibleThumbs[i];
PDFView.thumbnails[thumb.id - 1].draw();
renderingQueue.enqueueDraw(PDFView.thumbnails[thumb.id - 1]);
}
}, delay);
}
@ -888,7 +1030,6 @@ window.addEventListener('change', function webViewerChange(evt) {
// implemented in Firefox.
var file = files[0];
fileReader.readAsBinaryString(file);
document.title = file.name;
// URL does not reflect proper document location - hiding some icons.