First pass on FontWorker
This commit is contained in:
parent
c712712e67
commit
b00df76044
8 changed files with 247 additions and 22 deletions
136
worker/client.js
136
worker/client.js
|
@ -18,12 +18,115 @@ if (typeof console.time == "undefined") {
|
|||
};
|
||||
}
|
||||
|
||||
function FontWorker() {
|
||||
this.worker = new Worker("worker/font.js");
|
||||
this.fontsWaiting = 0;
|
||||
this.fontsWaitingCallbacks = [];
|
||||
|
||||
// Listen to the WebWorker for data and call actionHandler on it.
|
||||
this.worker.onmessage = function(event) {
|
||||
var data = event.data;
|
||||
var actionHandler = this.actionHandler
|
||||
if (data.action in actionHandler) {
|
||||
actionHandler[data.action].call(this, data.data);
|
||||
} else {
|
||||
throw "Unkown action from worker: " + data.action;
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
FontWorker.prototype = {
|
||||
actionHandler: {
|
||||
"fonts": function(data) {
|
||||
// console.log("got processed fonts from worker", Object.keys(data));
|
||||
for (name in data) {
|
||||
var base64 = window.btoa(data[name]);
|
||||
|
||||
// Add the @font-face rule to the document
|
||||
var url = "url(data:font/opentype;base64," + base64 + ");";
|
||||
var rule = "@font-face { font-family:'" + name + "';src:" + url + "}";
|
||||
var styleSheet = document.styleSheets[0];
|
||||
styleSheet.insertRule(rule, styleSheet.length);
|
||||
|
||||
// Just adding the font-face to the DOM doesn't make it load. It
|
||||
// seems it's loaded once Gecko notices it's used. Therefore,
|
||||
// add a div on the page using the loaded font.
|
||||
var div = document.createElement("div");
|
||||
var style = 'font-family:"' + name +
|
||||
'";position: absolute;top:-99999;left:-99999;z-index:-99999';
|
||||
div.setAttribute("style", style);
|
||||
document.body.appendChild(div);
|
||||
this.fontsWaiting --;
|
||||
}
|
||||
|
||||
// This timeout is necessary right now to make sure the fonts are really
|
||||
// loaded at the point the callbacks are called.
|
||||
setTimeout(function() {
|
||||
// If all fonts are available now, then call all the callbacks.
|
||||
if (this.fontsWaiting == 0) {
|
||||
var callbacks = this.fontsWaitingCallbacks;
|
||||
for (var i = 0; i < callbacks.length; i++) {
|
||||
callbacks[i]();
|
||||
}
|
||||
}
|
||||
}.bind(this), 100);
|
||||
}
|
||||
},
|
||||
|
||||
ensureFonts: function(data, callback) {
|
||||
var font;
|
||||
var notLoaded = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
font = data[i];
|
||||
if (Fonts[font.name]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Store only the data on Fonts that is needed later on, such that we
|
||||
// hold track on as lease memory as possible.
|
||||
Fonts[font.name] = {
|
||||
properties: {
|
||||
charset: font.properties.charset
|
||||
},
|
||||
cache: Object.create(null)
|
||||
};
|
||||
|
||||
// Mark this font to be handled later.
|
||||
notLoaded.push(font);
|
||||
// Increate the number of fonts to wait for.
|
||||
this.fontsWaiting++;
|
||||
}
|
||||
|
||||
// If there are fonts, that need to get loaded, tell the FontWorker to get
|
||||
// started and push the callback on the waiting-callback-stack.
|
||||
if (notLoaded.length != 0) {
|
||||
// Send the worker the fonts to work on.
|
||||
this.worker.postMessage({
|
||||
action: "fonts",
|
||||
data: notLoaded
|
||||
});
|
||||
if (callback) {
|
||||
this.fontsWaitingCallbacks.push(callback);
|
||||
}
|
||||
}
|
||||
// All fonts are present? Well, then just call the callback if there is one.
|
||||
else {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
function WorkerPDFDoc(canvas) {
|
||||
var timer = null
|
||||
|
||||
this.ctx = canvas.getContext("2d");
|
||||
this.canvas = canvas;
|
||||
this.worker = new Worker('worker/pdf.js');
|
||||
this.fontWorker = new FontWorker();
|
||||
this.waitingForFonts = false;
|
||||
this.waitingForFontsCallback = [];
|
||||
|
||||
this.numPage = 1;
|
||||
this.numPages = null;
|
||||
|
@ -56,6 +159,7 @@ function WorkerPDFDoc(canvas) {
|
|||
},
|
||||
|
||||
"$showText": function(y, text) {
|
||||
text = Fonts.charsToUnicode(text);
|
||||
this.translate(currentX, -1 * y);
|
||||
this.fillText(text, 0, 0);
|
||||
currentX += this.measureText(text).width;
|
||||
|
@ -136,6 +240,10 @@ function WorkerPDFDoc(canvas) {
|
|||
throw "Pattern not found";
|
||||
}
|
||||
this.strokeStyle = pattern;
|
||||
},
|
||||
|
||||
"$setFont": function(name) {
|
||||
Fonts.active = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,6 +295,17 @@ function WorkerPDFDoc(canvas) {
|
|||
div.setAttribute("style", style);
|
||||
document.body.appendChild(div);
|
||||
},
|
||||
|
||||
"fonts": function(data) {
|
||||
this.waitingForFonts = true;
|
||||
this.fontWorker.ensureFonts(data, function() {
|
||||
this.waitingForFonts = false;
|
||||
var callbacks = this.waitingForFontsCallback;
|
||||
for (var i = 0; i < callbacks.length; i++) {
|
||||
callbacks[i]();
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
"jpeg_stream": function(data) {
|
||||
var img = new Image();
|
||||
|
@ -207,9 +326,7 @@ function WorkerPDFDoc(canvas) {
|
|||
canvasList[id] = newCanvas;
|
||||
}
|
||||
|
||||
// There might be fonts that need to get loaded. Shedule the
|
||||
// rendering at the end of the event queue ensures this.
|
||||
setTimeout(function() {
|
||||
var renderData = function() {
|
||||
if (id == 0) {
|
||||
console.time("canvas rendering");
|
||||
var ctx = this.ctx;
|
||||
|
@ -220,11 +337,18 @@ function WorkerPDFDoc(canvas) {
|
|||
}
|
||||
renderProxyCanvas(canvasList[id], cmdQueue);
|
||||
if (id == 0) console.timeEnd("canvas rendering")
|
||||
}, 0, this);
|
||||
}.bind(this);
|
||||
|
||||
if (this.waitingForFonts) {
|
||||
console.log("want to render, but not all fonts are there", id);
|
||||
this.waitingForFontsCallback.push(renderData);
|
||||
} else {
|
||||
renderData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// List to the WebWorker for data and call actionHandler on it.
|
||||
// Listen to the WebWorker for data and call actionHandler on it.
|
||||
this.worker.onmessage = function(event) {
|
||||
var data = event.data;
|
||||
if (data.action in actionHandler) {
|
||||
|
@ -232,7 +356,7 @@ function WorkerPDFDoc(canvas) {
|
|||
} else {
|
||||
throw "Unkown action from worker: " + data.action;
|
||||
}
|
||||
}
|
||||
}.bind(this)
|
||||
}
|
||||
|
||||
WorkerPDFDoc.prototype.open = function(url, callback) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue