This commit is contained in:
Julian Viereck 2011-09-05 17:42:58 -07:00
parent 0134143c67
commit 71ff8ee586
7 changed files with 154 additions and 122 deletions

60
pdf.js
View File

@ -3358,18 +3358,48 @@ var Page = (function() {
},
startRendering: function(canvasCtx, continuation) {
var gfx = new CanvasGraphics(canvasCtx);
// If there is already some code to render, then use it directly.
if (this.code) {
this.display(gfx);
return;
}
var self = this;
var stats = self.stats;
stats.compile = stats.fonts = stats.render = 0;
var gfx = new CanvasGraphics(canvasCtx);
var fonts = [];
var images = new ImagesLoader();
this.compile(gfx, fonts, images);
var preCompilation = this.preCompile(gfx, fonts, images);
stats.compile = Date.now();
// Make a copy of the necessary datat to build a font later. The `font`
// object will be sent to the main thread later on.
var fontsBackup = fonts;
fonts = [];
for (var i = 0; i < fontsBackup.length; i++) {
var orgFont = fontsBackup[i];
var font = {
name: orgFont.name,
file: orgFont.file,
properties: orgFont.properties
}
fonts.push(font);
}
this.startRenderingFromPreCompilation(gfx, preCompilation, fonts, images, continuation);
},
startRenderingFromPreCompilation: function(gfx, preCompilation, fonts, images, continuation) {
var self = this;
var displayContinuation = function() {
self.code = gfx.postCompile(preCompilation);
// Always defer call to display() to work around bug in
// Firefox error reporting from XHR callbacks.
setTimeout(function() {
@ -3384,22 +3414,6 @@ var Page = (function() {
});
};
// Make a copy of the necessary datat to build a font later. The `font`
// object will be sent to the main thread later on.
var fontsBackup = fonts;
fonts = [];
for (var i = 0; i < fontsBackup.length; i++) {
var orgFont = fontsBackup[i];
var orgFontObj = orgFont.fontObj;
var font = {
name: orgFont.name,
file: orgFont.file,
properties: orgFont.properties
}
fonts.push(font);
}
this.ensureFonts(fonts, function() {
images.notifyOnLoad(function() {
stats.images = Date.now();
@ -3424,12 +3438,8 @@ var Page = (function() {
content[i] = xref.fetchIfRef(content[i]);
content = new StreamsSequenceStream(content);
}
return gfx.preCompile(content, xref, resources, fonts, images);
},
compile: function(gfx, fonts, images) {
var preCompilation = this.preCompile(gfx, fonts, images);
this.code = gfx.postCompile(preCompilation);
return gfx.preCompile(content, xref, resources, fonts, images,
this.pageNumber + "_");
},
ensureFonts: function(fonts, callback) {

View File

@ -12,6 +12,7 @@
<script type="text/javascript" src="../glyphlist.js"></script>
<script type="text/javascript" src="../metrics.js"></script>
<script type="text/javascript" src="../worker.js"></script>
<script type="text/javascript" src="../worker/message_handler.js"></script>
</head>
<body>

View File

@ -25,8 +25,21 @@ var WorkerPage = (function() {
},
startRendering: function(ctx, callback, errback) {
this.ctx = ctx;
this.callback = callback;
// TODO: Place the worker magic HERE.
this.page.startRendering(ctx, callback, errback);
// this.page.startRendering(ctx, callback, errback);
this.workerPDF.startRendering(this)
},
startRenderingFromPreCompilation: function(preCompilation, fonts, images) {
var gfx = new CanvasGraphics(this.ctx);
// TODO: Add proper handling for images loaded by the worker.
var images = new ImagesLoader();
this.page.startRenderingFromPreCompilation(gfx, preCompilation, fonts, images, this.callback);
},
getLinks: function() {
@ -46,6 +59,19 @@ var WorkerPDFDoc = (function() {
this.catalog = this.pdf.catalog;
this.pageCache = [];
this.worker = new Worker("worker/boot.js");
this.handler = new MessageHandler({
"page": function(data) {
var pageNum = data.pageNum;
var page = this.pageCache[pageNum];
page.startRenderingFromPreCompilation(data.preCompilation, data.fonts, data.images);
}
}, this.worker.postMessage, this);
this.worker.onmessage = this.handler.onMessage;
this.handler.send("doc", data);
}
constructor.prototype = {
@ -53,6 +79,10 @@ var WorkerPDFDoc = (function() {
return this.pdf.numPages;
},
startRendering: function(page) {
this.handler.send("page", page.page.pageNumber);
},
getPage: function(n) {
if (this.pageCache[n]) {
return this.pageCache[n];

63
worker/boot.js Normal file
View File

@ -0,0 +1,63 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
'use strict';
//
importScripts('console.js');
importScripts('event_handler.js');
importScripts('../pdf.js');
importScripts('../fonts.js');
importScripts('../crypto.js');
importScripts('../glyphlist.js');
// Listen for messages from the main thread.
var pdfDoc = null;
var handler = new MessageHandler({
"doc": function(data) {
pdfDocument = new PDFDoc(new Stream(data));
console.log("setup pdfDoc");
},
"page": function(pageNum) {
pageNum = parseInt(pageNum);
console.log("about to process page", pageNum);
var page = pdfDocument.getPage(pageNum);
// The following code does quite the same as Page.prototype.startRendering,
// but stops at one point and sends the result back to the main thread.
var gfx = new CanvasGraphics(canvasCtx);
var fonts = [];
// TODO: Figure out how image loading is handled inside the worker.
var images = new ImagesLoader();
// Pre compile the pdf page and fetch the fonts/images.
var preCompilation = page.preCompile(gfx, fonts, images);
// Extract the minimum of font data that is required to build all required
// font stuff on the main thread.
var fontsMin = [];
for (var i = 0; i < fonts.length; i++) {
var font = fonts[i];
fontsMin.push({
name: orgFont.name,
file: orgFont.file,
properties: orgFont.properties
});
}
// TODO: Handle images here.
handler.send("page", {
pageNum: pageNum,
fonts: fontsMin,
images: [],
preCompilation: preCompilation,
});
}
}, postMessage);
onmessage = handler.onMessage;

View File

@ -9,7 +9,7 @@ var console = {
var args = Array.prototype.slice.call(arguments);
postMessage({
action: 'log',
data: args
data: args
});
},

23
worker/message_handler.js Normal file
View File

@ -0,0 +1,23 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
'use strict';
function MessageHandler(actionHandler, postMessage, scope) {
this.onMessage = function(event) {
var data = event.data;
if (data.action in actionHandler) {
actionHandler[data.action].call(scope, data.data);
} else {
throw 'Unkown action from worker: ' + data.action;
}
};
this.send = function(actionName, data) {
postMessage({
action: actionName,
data: data
});
}
}

View File

@ -1,95 +0,0 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
'use strict';
var consoleTimer = {};
var console = {
log: function log() {
var args = Array.prototype.slice.call(arguments);
postMessage({
action: 'log',
data: args
});
},
time: function(name) {
consoleTimer[name] = Date.now();
},
timeEnd: function(name) {
var time = consoleTimer[name];
if (time == null) {
throw 'Unkown timer name ' + name;
}
this.log('Timer:', name, Date.now() - time);
}
};
//
importScripts('console.js');
importScripts('canvas.js');
importScripts('../pdf.js');
importScripts('../fonts.js');
importScripts('../crypto.js');
importScripts('../glyphlist.js');
// Use the JpegStreamProxy proxy.
JpegStream = JpegStreamProxy;
// Create the WebWorkerProxyCanvas.
var canvas = new CanvasProxy(1224, 1584);
// Listen for messages from the main thread.
var pdfDocument = null;
onmessage = function(event) {
var data = event.data;
// If there is no pdfDocument yet, then the sent data is the PDFDocument.
if (!pdfDocument) {
pdfDocument = new PDFDoc(new Stream(data));
postMessage({
action: 'pdf_num_pages',
data: pdfDocument.numPages
});
return;
}
// User requested to render a certain page.
else {
console.time('compile');
// Let's try to render the first page...
var page = pdfDocument.getPage(parseInt(data));
var pdfToCssUnitsCoef = 96.0 / 72.0;
var pageWidth = (page.mediaBox[2] - page.mediaBox[0]) * pdfToCssUnitsCoef;
var pageHeight = (page.mediaBox[3] - page.mediaBox[1]) * pdfToCssUnitsCoef;
postMessage({
action: 'setup_page',
data: pageWidth + ',' + pageHeight
});
// Set canvas size.
canvas.width = pageWidth;
canvas.height = pageHeight;
// page.compile will collect all fonts for us, once we have loaded them
// we can trigger the actual page rendering with page.display
var fonts = [];
var gfx = new CanvasGraphics(canvas.getContext('2d'), CanvasProxy);
page.compile(gfx, fonts);
console.timeEnd('compile');
// Send fonts to the main thread.
console.time('fonts');
postMessage({
action: 'fonts',
data: fonts
});
console.timeEnd('fonts');
console.time('display');
page.display(gfx);
canvas.flush();
console.timeEnd('display');
}
};