From 7e3bbccaaec6dd9114eecb9b43098c2ba9942a2c Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Wed, 7 Sep 2011 19:50:05 -0700 Subject: [PATCH] Add dependency management for loading images that causes the execution to halt if the dependency isn't satisfied during executing time --- pdf.js | 57 +++++++++++++++++++++++++++++++++++++++++++++---------- worker.js | 54 ++++++++++++++++++++++++++++------------------------ 2 files changed, 76 insertions(+), 35 deletions(-) diff --git a/pdf.js b/pdf.js index 40b38d9f0..ad7747946 100644 --- a/pdf.js +++ b/pdf.js @@ -861,13 +861,15 @@ var PredictorStream = (function() { var JpegStreamIR = (function() { function JpegStreamIR(objId, IR) { - var src = IR; + var src = 'data:image/jpeg;base64,' + window.btoa(IR); // create DOM image var img = new Image(); img.onload = (function() { this.loaded = true; - Objects[objId] = this; + + Objects.resolve(objId, this); + if (this.onLoad) this.onLoad(); }).bind(this); @@ -925,7 +927,7 @@ var JpegStream = (function() { if (isYcckImage(bytes)) bytes = fixYcckImage(bytes); - this.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes)); + this.src = bytesToString(bytes); } constructor.prototype = { @@ -3453,8 +3455,16 @@ var Page = (function() { width: this.width, height: this.height, rotate: this.rotate }); - gfx.executeIRQueue(this.IRQueue); - gfx.endDrawing(); + + var startIdx = 0; + var length = this.IRQueue.fnArray.length; + var IRQueue = this.IRQueue; + + function next() { + console.log("next executeIRQueue", startIdx, length); + startIdx = gfx.executeIRQueue(IRQueue, startIdx, next); + } + next(); }, rotatePoint: function(x, y) { var rotate = this.rotate; @@ -4285,7 +4295,11 @@ var PartialEvaluator = (function() { IR: image.getIR() }); - // TODO: Place dependency note in IR queue. + // Add the dependency on the image object. + fnArray.push("dependency"); + argsArray.push([ objId ]); + + // The normal fn. fn = 'paintJpegXObject'; args = [ objId, w, h ]; } else { @@ -4864,12 +4878,35 @@ var CanvasGraphics = (function() { this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height); }, - executeIRQueue: function(codeIR) { + executeIRQueue: function(codeIR, startIdx, continueCallback) { var argsArray = codeIR.argsArray; var fnArray = codeIR.fnArray; - for (var i = 0, length = argsArray.length; i < length; i++) { - this[fnArray[i]].apply(this, argsArray[i]); + var i = startIdx || 0; + var length = argsArray.length; + for (i; i < length; i++) { + if (fnArray[i] !== "dependency") { + this[fnArray[i]].apply(this, argsArray[i]); + } else { + var deps = argsArray[i]; + for (var n = 0; n < deps.length; n++) { + var depObjId = deps[n]; + var promise; + if (!Objects[depObjId]) { + promise = Objects[depObjId] = new Promise(); + } else { + promise = Objects[depObjId]; + } + // If the promise isn't resolved yet, add the continueCallback + // to the promise and bail out. + if (!promise.isResolved) { + console.log("Unresolved object: " + depObjId); + promise.then(continueCallback); + return i; + } + } + } } + return i; }, endDrawing: function() { @@ -5367,7 +5404,7 @@ var CanvasGraphics = (function() { }, paintJpegXObject: function(objId, w, h) { - var image = Objects[objId]; + var image = Objects[objId].data; if (!image) { error("Dependent image isn't ready yet"); } diff --git a/worker.js b/worker.js index 9db894d32..5d0769d29 100644 --- a/worker.js +++ b/worker.js @@ -51,12 +51,27 @@ var WorkerPage = (function() { })(); // This holds a list of objects the IR queue depends on. -var Objects = {}; +var Objects = { + resolve: function(objId, data) { + // In case there is a promise already on this object, just resolve it. + if (Objects[objId] instanceof Promise) { + Objects[objId].resolve(data); + } else { + Objects[objId] = new Promise(data); + } + } +}; var Promise = (function() { - function Promise(name) { - this.name = name; - this.isResolved = false; + function Promise(data) { + // If you build a promise and pass in some data it's already resolved. + if (data != null) { + this.isResolved = true; + this.data = data; + } else { + this.isResolved = false; + } + this.callbacks = []; }; Promise.prototype = { @@ -83,6 +98,7 @@ var Promise = (function() { } } } + return Promise; })(); var WorkerPDFDoc = (function() { @@ -95,7 +111,7 @@ var WorkerPDFDoc = (function() { this.pageCache = []; - var useWorker = true; + var useWorker = false; if (useWorker) { var worker = new Worker("../worker/boot.js"); @@ -125,29 +141,17 @@ var WorkerPDFDoc = (function() { font.file.end - font.file.start, fontFileDict); font.file = new FlateStream(fontFile); } - - var imageLoadingDone = function() { - var timeStart = new Date(); - console.log("startRenderingFromPreCompilation:", "numberOfFonts", fonts.length); - page.startRenderingFromIRQueue(data.IRQueue, data.fonts, data.images); - console.log("RenderingTime", (new Date()) - timeStart); - } var images = data.images; - if (images.length != 0) { - // Generate JpegStreams based on IR information and start rendering - // once the compilation is done. - var loader = new ImagesLoader(); - loader.onLoad = imageLoadingDone; - - for (var i = 0; i < images.length; i++) { - var image = images[i]; - var stream = new JpegStreamIR(image.id, image.IR); - loader.bind(stream); - } - } else { - imageLoadingDone(); + for (var i = 0; i < images.length; i++) { + var image = images[i]; + var stream = new JpegStreamIR(image.id, image.IR); } + + var timeStart = new Date(); + console.log("startRenderingFromPreCompilation:", "numberOfFonts", fonts.length); + page.startRenderingFromIRQueue(data.IRQueue, data.fonts, data.images); + console.log("RenderingTime", (new Date()) - timeStart); }, this); if (!useWorker) {