Browse Source

Send JpegStreams to the main thread ASAP. No need for ImagesLoader anymore

Julian Viereck 14 years ago
parent
commit
ac11f30ae9
  1. 61
      pdf.js
  2. 40
      worker.js
  3. 6
      worker/handler.js

61
pdf.js

@ -943,44 +943,6 @@ var JpegStream = (function() {
return constructor; return constructor;
})(); })();
// Simple object to track the loading images
// Initialy for every that is in loading call imageLoading()
// and, when images onload is fired, call imageLoaded()
// When all images are loaded, the onLoad event is fired.
var ImagesLoader = (function() {
function constructor() {
this.loading = 0;
}
constructor.prototype = {
imageLoading: function() {
++this.loading;
},
imageLoaded: function() {
if (--this.loading == 0 && this.onLoad) {
this.onLoad();
delete this.onLoad;
}
},
bind: function(jpegStream) {
if (jpegStream.loaded)
return;
this.imageLoading();
jpegStream.onLoad = this.imageLoaded.bind(this);
},
notifyOnLoad: function(callback) {
if (this.loading == 0)
callback();
this.onLoad = callback;
}
};
return constructor;
})();
var DecryptStream = (function() { var DecryptStream = (function() {
function constructor(str, decrypt) { function constructor(str, decrypt) {
this.str = str; this.str = str;
@ -3377,7 +3339,7 @@ var Page = (function() {
return shadow(this, 'rotate', rotate); return shadow(this, 'rotate', rotate);
}, },
startRenderingFromIRQueue: function(gfx, IRQueue, fonts, images, continuation) { startRenderingFromIRQueue: function(gfx, IRQueue, fonts, continuation) {
var self = this; var self = this;
this.IRQueue = IRQueue; this.IRQueue = IRQueue;
@ -3396,14 +3358,11 @@ var Page = (function() {
}; };
this.ensureFonts(fonts, function() { this.ensureFonts(fonts, function() {
images.notifyOnLoad(function() {
self.stats.images = Date.now();
displayContinuation(); displayContinuation();
}); });
})
}, },
getIRQueue: function(fonts, images) { getIRQueue: function(handler, fonts) {
if (this.IRQueue) { if (this.IRQueue) {
// content was compiled // content was compiled
return this.IRQueue; return this.IRQueue;
@ -3422,7 +3381,7 @@ var Page = (function() {
var pe = this.pe = new PartialEvaluator(); var pe = this.pe = new PartialEvaluator();
var IRQueue = {}; var IRQueue = {};
return this.IRQueue = pe.getIRQueue(content, xref, resources, IRQueue, fonts, images, "p" + this.pageNumber + "_"); return this.IRQueue = pe.getIRQueue(content, xref, resources, IRQueue, handler, fonts, "p" + this.pageNumber + "_");
}, },
ensureFonts: function(fonts, callback) { ensureFonts: function(fonts, callback) {
@ -3460,10 +3419,13 @@ var Page = (function() {
var IRQueue = this.IRQueue; var IRQueue = this.IRQueue;
var self = this; var self = this;
var startTime = Date.now();
function next() { function next() {
startIdx = gfx.executeIRQueue(IRQueue, startIdx, next); startIdx = gfx.executeIRQueue(IRQueue, startIdx, next);
if (startIdx == length) { if (startIdx == length) {
self.stats.render = Date.now(); self.stats.render = Date.now();
console.log("page=%d - executeIRQueue: time=%dms",
self.pageNumber + 1, self.stats.render - startTime);
callback(); callback();
} }
} }
@ -4199,7 +4161,7 @@ var PartialEvaluator = (function() {
}; };
constructor.prototype = { constructor.prototype = {
getIRQueue: function(stream, xref, resources, queue, fonts, images, uniquePrefix) { getIRQueue: function(stream, xref, resources, queue, handler, fonts, uniquePrefix) {
function buildPaintImageXObject(image, inline) { function buildPaintImageXObject(image, inline) {
var dict = image.dict; var dict = image.dict;
var w = dict.get('Width', 'W'); var w = dict.get('Width', 'W');
@ -4207,10 +4169,7 @@ var PartialEvaluator = (function() {
if (image instanceof JpegStream) { if (image instanceof JpegStream) {
var objId = ++objIdCounter; var objId = ++objIdCounter;
images.push({ handler.send("obj", [objId, "JpegStream", image.getIR()]);
id: objId,
IR: image.getIR()
});
// Add the dependency on the image object. // Add the dependency on the image object.
fnArray.push("dependency"); fnArray.push("dependency");
@ -4306,7 +4265,7 @@ var PartialEvaluator = (function() {
// TODO: Add dependency here. // TODO: Add dependency here.
// Create an IR of the pattern code. // Create an IR of the pattern code.
var codeIR = this.getIRQueue(pattern, xref, var codeIR = this.getIRQueue(pattern, xref,
dict.get('Resources'), {}, fonts, images, uniquePrefix); dict.get('Resources'), {}, handler, fonts, uniquePrefix);
args = TilingPattern.getIR(codeIR, dict, args); args = TilingPattern.getIR(codeIR, dict, args);
} }
@ -4344,7 +4303,7 @@ var PartialEvaluator = (function() {
// This adds the IRQueue of the xObj to the current queue. // This adds the IRQueue of the xObj to the current queue.
this.getIRQueue(xobj, xref, xobj.dict.get('Resources'), queue, this.getIRQueue(xobj, xref, xobj.dict.get('Resources'), queue,
fonts, images, uniquePrefix); handler, fonts, uniquePrefix);
fn = "paintFormXObjectEnd"; fn = "paintFormXObjectEnd";

40
worker.js

@ -30,16 +30,24 @@ var WorkerPage = (function() {
// TODO: Place the worker magic HERE. // TODO: Place the worker magic HERE.
// this.page.startRendering(ctx, callback, errback); // this.page.startRendering(ctx, callback, errback);
this.startRenderingTime = Date.now();
this.workerPDF.startRendering(this) this.workerPDF.startRendering(this)
}, },
startRenderingFromIRQueue: function(IRQueue, fonts, images) { startRenderingFromIRQueue: function(IRQueue, fonts) {
var gfx = new CanvasGraphics(this.ctx); var gfx = new CanvasGraphics(this.ctx);
// TODO: Add proper handling for images loaded by the worker. var startTime = Date.now();
var images = new ImagesLoader(); var callback = function(err) {
var pageNum = this.page.pageNumber + 1;
this.page.startRenderingFromIRQueue(gfx, IRQueue, fonts, images, this.callback); console.log("page=%d - rendering time: time=%dms",
pageNum, Date.now() - startTime);
console.log("page=%d - total time: time=%dms",
pageNum, Date.now() - this.startRenderingTime);
this.callback(err);
}.bind(this);
this.page.startRenderingFromIRQueue(gfx, IRQueue, fonts, callback);
}, },
getLinks: function() { getLinks: function() {
@ -153,15 +161,21 @@ var WorkerPDFDoc = (function() {
} }
} }
var images = data.images; page.startRenderingFromIRQueue(data.IRQueue, data.fonts);
for (var i = 0; i < images.length; i++) { }, this);
var image = images[i];
var stream = new JpegStreamIR(image.id, image.IR);
}
var timeStart = new Date(); handler.on("obj", function(data) {
page.startRenderingFromIRQueue(data.IRQueue, data.fonts, data.images); var objId = data[0];
console.log("RenderingTime", (new Date()) - timeStart); var objType = data[1];
switch (objType) {
case "JpegStream":
var IR = data[2];
new JpegStreamIR(objId, IR);
break;
default:
throw "Got unkown object type " + objType;
}
}, this); }, this);
if (!useWorker) { if (!useWorker) {

6
worker/handler.js

@ -20,11 +20,12 @@ var WorkerHandler = {
// but stops at one point and sends the result back to the main thread. // but stops at one point and sends the result back to the main thread.
var gfx = new CanvasGraphics(null); var gfx = new CanvasGraphics(null);
var fonts = []; var fonts = [];
var images = [];
var start = Date.now();
// Pre compile the pdf page and fetch the fonts/images. // Pre compile the pdf page and fetch the fonts/images.
var IRQueue = page.getIRQueue(fonts, images); var IRQueue = page.getIRQueue(handler, fonts);
console.log("page=%d - getIRQueue: time=%dms, len=%d", pageNum, Date.now() - start, IRQueue.fnArray.length);
// Extract the minimum of font data that is required to build all required // Extract the minimum of font data that is required to build all required
// font stuff on the main thread. // font stuff on the main thread.
var fontsMin = []; var fontsMin = [];
@ -59,7 +60,6 @@ var WorkerHandler = {
handler.send("page", { handler.send("page", {
pageNum: pageNum, pageNum: pageNum,
fonts: fontsMin, fonts: fontsMin,
images: images,
IRQueue: IRQueue, IRQueue: IRQueue,
}); });
}, this); }, this);

Loading…
Cancel
Save