Merge pull request #3911 from yurydelendik/mem-redux2

Cleaning up fonts when viewer is idle for some time
This commit is contained in:
Brendan Dahl 2013-11-18 13:01:23 -08:00
commit 3132c9e7e9
9 changed files with 93 additions and 9 deletions

View File

@ -25,12 +25,13 @@
var Page = (function PageClosure() { var Page = (function PageClosure() {
function Page(pdfManager, xref, pageIndex, pageDict, ref) { function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache) {
this.pdfManager = pdfManager; this.pdfManager = pdfManager;
this.pageIndex = pageIndex; this.pageIndex = pageIndex;
this.pageDict = pageDict; this.pageDict = pageDict;
this.xref = xref; this.xref = xref;
this.ref = ref; this.ref = ref;
this.fontCache = fontCache;
this.idCounters = { this.idCounters = {
obj: 0 obj: 0
}; };
@ -160,7 +161,7 @@ var Page = (function PageClosure() {
var partialEvaluator = new PartialEvaluator( var partialEvaluator = new PartialEvaluator(
pdfManager, this.xref, handler, pdfManager, this.xref, handler,
this.pageIndex, 'p' + this.pageIndex + '_', this.pageIndex, 'p' + this.pageIndex + '_',
this.idCounters); this.idCounters, this.fontCache);
var dataPromises = Promise.all( var dataPromises = Promise.all(
[contentStreamPromise, resourcesPromise], reject); [contentStreamPromise, resourcesPromise], reject);
@ -226,7 +227,7 @@ var Page = (function PageClosure() {
var partialEvaluator = new PartialEvaluator( var partialEvaluator = new PartialEvaluator(
pdfManager, self.xref, handler, pdfManager, self.xref, handler,
self.pageIndex, 'p' + self.pageIndex + '_', self.pageIndex, 'p' + self.pageIndex + '_',
self.idCounters); self.idCounters, self.fontCache);
var bidiTexts = partialEvaluator.getTextContent(contentStream, var bidiTexts = partialEvaluator.getTextContent(contentStream,
self.resources); self.resources);
@ -496,6 +497,10 @@ var PDFDocument = (function PDFDocumentClosure() {
getPage: function PDFDocument_getPage(pageIndex) { getPage: function PDFDocument_getPage(pageIndex) {
return this.catalog.getPage(pageIndex); return this.catalog.getPage(pageIndex);
},
cleanup: function PDFDocument_cleanup() {
return this.catalog.cleanup();
} }
}; };

View File

@ -26,7 +26,7 @@
var PartialEvaluator = (function PartialEvaluatorClosure() { var PartialEvaluator = (function PartialEvaluatorClosure() {
function PartialEvaluator(pdfManager, xref, handler, pageIndex, function PartialEvaluator(pdfManager, xref, handler, pageIndex,
uniquePrefix, idCounters) { uniquePrefix, idCounters, fontCache) {
this.state = new EvalState(); this.state = new EvalState();
this.stateStack = []; this.stateStack = [];
@ -36,7 +36,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
this.pageIndex = pageIndex; this.pageIndex = pageIndex;
this.uniquePrefix = uniquePrefix; this.uniquePrefix = uniquePrefix;
this.idCounters = idCounters; this.idCounters = idCounters;
this.fontCache = new RefSetCache(); this.fontCache = fontCache;
} }
// Specifies properties for each command // Specifies properties for each command

View File

@ -189,7 +189,7 @@ var RefSet = (function RefSetClosure() {
var RefSetCache = (function RefSetCacheClosure() { var RefSetCache = (function RefSetCacheClosure() {
function RefSetCache() { function RefSetCache() {
this.dict = {}; this.dict = Object.create(null);
} }
RefSetCache.prototype = { RefSetCache.prototype = {
@ -203,6 +203,16 @@ var RefSetCache = (function RefSetCacheClosure() {
put: function RefSetCache_put(ref, obj) { put: function RefSetCache_put(ref, obj) {
this.dict['R' + ref.num + '.' + ref.gen] = obj; this.dict['R' + ref.num + '.' + ref.gen] = obj;
},
forEach: function RefSetCache_forEach(fn, thisArg) {
for (var i in this.dict) {
fn.call(thisArg, this.dict[i]);
}
},
clear: function RefSetCache_clear() {
this.dict = Object.create(null);
} }
}; };
@ -214,6 +224,7 @@ var Catalog = (function CatalogClosure() {
this.pdfManager = pdfManager; this.pdfManager = pdfManager;
this.xref = xref; this.xref = xref;
this.catDict = xref.getCatalogObj(); this.catDict = xref.getCatalogObj();
this.fontCache = new RefSetCache();
assertWellFormed(isDict(this.catDict), assertWellFormed(isDict(this.catDict),
'catalog object is not a dictionary'); 'catalog object is not a dictionary');
@ -400,13 +411,22 @@ var Catalog = (function CatalogClosure() {
return shadow(this, 'javaScript', javaScript); return shadow(this, 'javaScript', javaScript);
}, },
cleanup: function Catalog_cleanup() {
this.fontCache.forEach(function (font) {
delete font.sent;
delete font.translated;
});
this.fontCache.clear();
},
getPage: function Catalog_getPage(pageIndex) { getPage: function Catalog_getPage(pageIndex) {
if (!(pageIndex in this.pagePromises)) { if (!(pageIndex in this.pagePromises)) {
this.pagePromises[pageIndex] = this.getPageDict(pageIndex).then( this.pagePromises[pageIndex] = this.getPageDict(pageIndex).then(
function (a) { function (a) {
var dict = a[0]; var dict = a[0];
var ref = a[1]; var ref = a[1];
return new Page(this.pdfManager, this.xref, pageIndex, dict, ref); return new Page(this.pdfManager, this.xref, pageIndex, dict, ref,
this.fontCache);
}.bind(this) }.bind(this)
); );
} }

View File

@ -46,6 +46,10 @@ var BasePdfManager = (function BasePdfManagerClosure() {
return this.pdfModel.getPage(pageIndex); return this.pdfModel.getPage(pageIndex);
}, },
cleanup: function BasePdfManager_cleanup() {
return this.pdfModel.cleanup();
},
ensure: function BasePdfManager_ensure(obj, prop, args) { ensure: function BasePdfManager_ensure(obj, prop, args) {
return new NotImplementedException(); return new NotImplementedException();
}, },

View File

@ -379,6 +379,11 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
}); });
}); });
handler.on('Cleanup', function wphCleanup(data, promise) {
pdfManager.cleanup();
promise.resolve(true);
});
handler.on('Terminate', function wphTerminate(data, promise) { handler.on('Terminate', function wphTerminate(data, promise) {
pdfManager.terminate(); pdfManager.terminate();
promise.resolve(); promise.resolve();

View File

@ -276,6 +276,9 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
dataLoaded: function PDFDocumentProxy_dataLoaded() { dataLoaded: function PDFDocumentProxy_dataLoaded() {
return this.transport.dataLoaded(); return this.transport.dataLoaded();
}, },
cleanup: function PDFDocumentProxy_cleanup() {
this.transport.startCleanup();
},
destroy: function PDFDocumentProxy_destroy() { destroy: function PDFDocumentProxy_destroy() {
this.transport.destroy(); this.transport.destroy();
} }
@ -907,6 +910,21 @@ var WorkerTransport = (function WorkerTransportClosure() {
} }
); );
return promise; return promise;
},
startCleanup: function WorkerTransport_startCleanup() {
this.messageHandler.send('Cleanup', null,
function endCleanup() {
for (var i = 0, ii = this.pageCache.length; i < ii; i++) {
var page = this.pageCache[i];
if (page) {
page.destroy();
}
}
this.commonObjs.clear();
FontLoader.clear();
}.bind(this)
);
} }
}; };
return WorkerTransport; return WorkerTransport;

View File

@ -33,6 +33,12 @@ var FontLoader = {
var styleSheet = styleElement.sheet; var styleSheet = styleElement.sheet;
styleSheet.insertRule(rule, styleSheet.cssRules.length); styleSheet.insertRule(rule, styleSheet.cssRules.length);
}, },
clear: function fontLoaderClear() {
var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
if (styleElement) {
styleElement.parentNode.removeChild(styleElement);
}
},
//#if !(MOZCENTRAL) //#if !(MOZCENTRAL)
get loadTestFont() { get loadTestFont() {
// This is a CFF font with 1 glyph for '.' that fills its entire width and // This is a CFF font with 1 glyph for '.' that fills its entire width and

View File

@ -67,12 +67,16 @@ var PageView = function pageView(container, id, scale,
} }
}; };
this.reset = function pageViewReset() { this.resetRenderingState = function pageViewResetRenderingState() {
if (this.renderTask) { if (this.renderTask) {
this.renderTask.cancel(); this.renderTask.cancel();
} }
this.resume = null; this.resume = null;
this.renderingState = RenderingStates.INITIAL; this.renderingState = RenderingStates.INITIAL;
};
this.reset = function pageViewReset() {
this.resetRenderingState();
div.style.width = Math.floor(this.viewport.width) + 'px'; div.style.width = Math.floor(this.viewport.width) + 'px';
div.style.height = Math.floor(this.viewport.height) + 'px'; div.style.height = Math.floor(this.viewport.height) + 'px';

View File

@ -38,6 +38,7 @@ var SCALE_SELECT_CONTAINER_PADDING = 8;
var SCALE_SELECT_PADDING = 22; var SCALE_SELECT_PADDING = 22;
var THUMBNAIL_SCROLL_MARGIN = -19; var THUMBNAIL_SCROLL_MARGIN = -19;
var USE_ONLY_CSS_ZOOM = false; var USE_ONLY_CSS_ZOOM = false;
var CLEANUP_TIMEOUT = 30000;
//#if B2G //#if B2G
//USE_ONLY_CSS_ZOOM = true; //USE_ONLY_CSS_ZOOM = true;
//#endif //#endif
@ -106,6 +107,7 @@ var PDFView = {
lastScroll: 0, lastScroll: 0,
previousPageNumber: 1, previousPageNumber: 1,
isViewerEmbedded: (window.parent !== window), isViewerEmbedded: (window.parent !== window),
idleTimeout: null,
// called once when the document is loaded // called once when the document is loaded
initialize: function pdfViewInitialize() { initialize: function pdfViewInitialize() {
@ -1011,6 +1013,11 @@ var PDFView = {
}, },
renderHighestPriority: function pdfViewRenderHighestPriority() { renderHighestPriority: function pdfViewRenderHighestPriority() {
if (PDFView.idleTimeout) {
clearTimeout(PDFView.idleTimeout);
PDFView.idleTimeout = null;
}
// Pages have a higher priority than thumbnails, so check them first. // Pages have a higher priority than thumbnails, so check them first.
var visiblePages = this.getVisiblePages(); var visiblePages = this.getVisiblePages();
var pageView = this.getHighestPriority(visiblePages, this.pages, var pageView = this.getHighestPriority(visiblePages, this.pages,
@ -1025,9 +1032,24 @@ var PDFView = {
var thumbView = this.getHighestPriority(visibleThumbs, var thumbView = this.getHighestPriority(visibleThumbs,
this.thumbnails, this.thumbnails,
this.thumbnailViewScroll.down); this.thumbnailViewScroll.down);
if (thumbView) if (thumbView) {
this.renderView(thumbView, 'thumbnail'); this.renderView(thumbView, 'thumbnail');
return;
}
} }
PDFView.idleTimeout = setTimeout(function () {
PDFView.cleanup();
}, CLEANUP_TIMEOUT);
},
cleanup: function pdfViewCleanup() {
for (var i = 0, ii = this.pages.length; i < ii; i++) {
if (this.pages[i]) {
this.pages[i].resetRenderingState();
}
}
this.pdfDocument.cleanup();
}, },
getHighestPriority: function pdfViewGetHighestPriority(visible, views, getHighestPriority: function pdfViewGetHighestPriority(visible, views,