Most working, but once you add the font-css file to the web page, there is no font drawn at all

This commit is contained in:
Julian Viereck 2011-06-22 01:28:17 +02:00
parent f346014c12
commit a8dcb0dcd6
5 changed files with 235 additions and 108 deletions

View File

@ -42,11 +42,17 @@ function CanvasProxy(width, height) {
"stroke",
"clip",
"measureText",
"isPointInPath"
"isPointInPath",
"$setCurrentX",
"$addCurrentX",
"$saveCurrentX",
"$restoreCurrentX",
"$showText"
];
function buildFuncCall(name) {
return function() {
console.log("funcCall", name)
// console.log("funcCall", name)
stack.push([name, Array.prototype.slice.call(arguments)]);
}
}
@ -103,6 +109,8 @@ function CanvasProxy(width, height) {
}
CanvasProxy.prototype.flush = function() {
// postMessage("log");
// postMessage(JSON.stringify([this.$stack.length]));
postMessage("canvas_proxy_stack");
postMessage(JSON.stringify(this.$stack));
this.$stack.length = 0;

146
fonts.js
View File

@ -759,91 +759,109 @@ var Font = (function () {
var data = this.font;
var fontName = this.name;
var isWorker = (typeof window == "undefined");
/** Hack begin */
if (!isWorker) {
// Actually there is not event when a font has finished downloading so
// the following code are a dirty hack to 'guess' when a font is ready
var canvas = document.createElement("canvas");
var style = "border: 1px solid black; position:absolute; top: " +
(debug ? (100 * fontCount) : "-200") + "px; left: 2px; width: 340px; height: 100px";
canvas.setAttribute("style", style);
canvas.setAttribute("width", 340);
canvas.setAttribute("heigth", 100);
document.body.appendChild(canvas);
// Actually there is not event when a font has finished downloading so
// the following code are a dirty hack to 'guess' when a font is ready
var canvas = document.createElement("canvas");
var style = "border: 1px solid black; position:absolute; top: " +
(debug ? (100 * fontCount) : "-200") + "px; left: 2px; width: 340px; height: 100px";
canvas.setAttribute("style", style);
canvas.setAttribute("width", 340);
canvas.setAttribute("heigth", 100);
document.body.appendChild(canvas);
// Get the font size canvas think it will be for 'spaces'
var ctx = canvas.getContext("2d");
ctx.font = "bold italic 20px " + fontName + ", Symbol, Arial";
var testString = " ";
// Get the font size canvas think it will be for 'spaces'
var ctx = canvas.getContext("2d");
ctx.font = "bold italic 20px " + fontName + ", Symbol, Arial";
var testString = " ";
// When debugging use the characters provided by the charsets to visually
// see what's happening instead of 'spaces'
var debug = false;
if (debug) {
var name = document.createElement("font");
name.setAttribute("style", "position: absolute; left: 20px; top: " +
(100 * fontCount + 60) + "px");
name.innerHTML = fontName;
document.body.appendChild(name);
// When debugging use the characters provided by the charsets to visually
// see what's happening instead of 'spaces'
var debug = false;
if (debug) {
var name = document.createElement("font");
name.setAttribute("style", "position: absolute; left: 20px; top: " +
(100 * fontCount + 60) + "px");
name.innerHTML = fontName;
document.body.appendChild(name);
// Retrieve font charset
var charset = Fonts[fontName].properties.charset || [];
// Retrieve font charset
var charset = Fonts[fontName].properties.charset || [];
// if the charset is too small make it repeat a few times
var count = 30;
while (count-- && charset.length <= 30)
charset = charset.concat(charset.slice());
// if the charset is too small make it repeat a few times
var count = 30;
while (count-- && charset.length <= 30)
charset = charset.concat(charset.slice());
for (var i = 0; i < charset.length; i++) {
var unicode = GlyphsUnicode[charset[i]];
if (!unicode)
continue;
testString += String.fromCharCode(unicode);
}
for (var i = 0; i < charset.length; i++) {
var unicode = GlyphsUnicode[charset[i]];
if (!unicode)
continue;
testString += String.fromCharCode(unicode);
}
ctx.fillText(testString, 20, 20);
}
ctx.fillText(testString, 20, 20);
}
// Periodicaly check for the width of the testString, it will be
// different once the real font has loaded
var textWidth = ctx.measureText(testString).width;
// Periodicaly check for the width of the testString, it will be
// different once the real font has loaded
var textWidth = ctx.measureText(testString).width;
var interval = window.setInterval(function canvasInterval(self) {
this.start = this.start || Date.now();
ctx.font = "bold italic 20px " + fontName + ", Symbol, Arial";
var interval = window.setInterval(function canvasInterval(self) {
this.start = this.start || Date.now();
ctx.font = "bold italic 20px " + fontName + ", Symbol, Arial";
// For some reasons the font has not loaded, so mark it loaded for the
// page to proceed but cry
if ((Date.now() - this.start) >= kMaxWaitForFontFace) {
window.clearInterval(interval);
Fonts[fontName].loading = false;
warn("Is " + fontName + " for charset: " + charset + " loaded?");
this.start = 0;
} else if (textWidth != ctx.measureText(testString).width) {
window.clearInterval(interval);
Fonts[fontName].loading = false;
this.start = 0;
}
// For some reasons the font has not loaded, so mark it loaded for the
// page to proceed but cry
if ((Date.now() - this.start) >= kMaxWaitForFontFace) {
window.clearInterval(interval);
Fonts[fontName].loading = false;
warn("Is " + fontName + " for charset: " + charset + " loaded?");
this.start = 0;
} else if (textWidth != ctx.measureText(testString).width) {
window.clearInterval(interval);
Fonts[fontName].loading = false;
this.start = 0;
}
if (debug)
ctx.fillText(testString, 20, 50);
}, 30, this);
if (debug)
ctx.fillText(testString, 20, 50);
}, 30, this);
}
/** Hack end */
//
// Get the base64 encoding of the binary font data
var str = "";
var length = data.length;
for (var i = 0; i < length; ++i)
str += String.fromCharCode(data[i]);
var base64 = window.btoa(str);
if (isWorker) {
postMessage("font");
postMessage(JSON.stringify({
str: str,
mimetype: this.mimetype,
fontName: fontName,
}));
// Add the @font-face rule to the document
var url = "url(data:" + this.mimetype + ";base64," + base64 + ");";
var rule = "@font-face { font-family:'" + fontName + "';src:" + url + "}";
var styleSheet = document.styleSheets[0];
styleSheet.insertRule(rule, styleSheet.length);
setTimeout(function() {
Fonts[fontName].loading = false;
}, kMaxWaitForFontFace);
} else {
var base64 = window.btoa(str);
// Add the @font-face rule to the document
var url = "url(data:" + this.mimetype + ";base64," + base64 + ");";
var rule = "@font-face { font-family:'" + fontName + "';src:" + url + "}";
var styleSheet = document.styleSheets[0];
styleSheet.insertRule(rule, styleSheet.length);
console.log("added font", fontName);
console.log(rule);
}
}
};

34
pdf.js
View File

@ -2674,12 +2674,18 @@ var CanvasGraphics = (function() {
},
save: function() {
this.ctx.save();
if (this.ctx.$saveCurrentX) {
this.ctx.$saveCurrentX();
}
this.stateStack.push(this.current);
this.current = new CanvasExtraState();
},
restore: function() {
var prev = this.stateStack.pop();
if (prev) {
if (this.ctx.$restoreCurrentX) {
this.ctx.$restoreCurrentX();
}
this.current = prev;
this.ctx.restore();
}
@ -2760,6 +2766,9 @@ var CanvasGraphics = (function() {
// Text
beginText: function() {
this.current.textMatrix = IDENTITY_MATRIX;
if (this.ctx.$setCurrentX) {
this.ctx.$setCurrentX(0)
}
this.current.x = this.current.lineX = 0;
this.current.y = this.current.lineY = 0;
},
@ -2814,6 +2823,9 @@ var CanvasGraphics = (function() {
moveText: function (x, y) {
this.current.x = this.current.lineX += x;
this.current.y = this.current.lineY += y;
if (this.ctx.$setCurrentX) {
this.ctx.$setCurrentX(this.current.x)
}
},
setLeadingMoveText: function(x, y) {
this.setLeading(-y);
@ -2821,6 +2833,10 @@ var CanvasGraphics = (function() {
},
setTextMatrix: function(a, b, c, d, e, f) {
this.current.textMatrix = [ a, b, c, d, e, f ];
if (this.ctx.$setCurrentX) {
this.$setCurrentX(0)
}
this.current.x = this.current.lineX = 0;
this.current.y = this.current.lineY = 0;
},
@ -2831,11 +2847,15 @@ var CanvasGraphics = (function() {
this.ctx.save();
this.ctx.transform.apply(this.ctx, this.current.textMatrix);
this.ctx.scale(1, -1);
this.ctx.translate(0, -2 * this.current.y);
text = Fonts.charsToUnicode(text);
this.ctx.fillText(text, this.current.x, this.current.y);
this.current.x += this.ctx.measureText(text).width;
if (this.ctx.$showText) {
this.ctx.$showText(this.current.y, Fonts.charsToUnicode(text));
} else {
console.log(text, this.current.x);
text = Fonts.charsToUnicode(text);
this.ctx.fillText(text, 0, 0);
this.current.x += this.ctx.measureText(text).width;
}
this.ctx.restore();
},
@ -2843,7 +2863,11 @@ var CanvasGraphics = (function() {
for (var i = 0; i < arr.length; ++i) {
var e = arr[i];
if (IsNum(e)) {
this.current.x -= e * 0.001 * this.current.fontSize;
if (this.ctx.$addCurrentX) {
this.ctx.$addCurrentX(-e * 0.001 * this.current.fontSize)
} else {
this.current.x -= e * 0.001 * this.current.fontSize;
}
} else if (IsString(e)) {
this.showText(e);
} else {

View File

@ -11,11 +11,63 @@ var myWorker = new Worker('worker.js');
const WAIT = 0;
const CANVAS_PROXY_STACK = 1;
const LOG = 2;
const FONT = 3;
var currentX = 0;
var currentXStack = [];
var special = {
"$setCurrentX": function(value) {
currentX = value;
},
"$addCurrentX": function(value) {
currentX += value;
},
"$saveCurrentX": function() {
currentXStack.push(currentX);
},
"$restoreCurrentX": function() {
currentX = currentXStack.pop();
},
"$showText": function(y, text) {
console.log(text, currentX, y, this.measureText(text).width);
this.translate(currentX, -1 * y);
this.fillText(text, 0, 0);
currentX += this.measureText(text).width;
}
}
function renderProxyCanvas(stack) {
// for (var i = 0; i < stack.length; i++) {
for (var i = 0; i < 1000; i++) {
var opp = stack[i];
if (opp[0] == "$") {
// console.log("set property", opp[1], opp[2]);
if (opp[1] == "font") {
ctx[opp[1]] = opp[2];
// console.log("font", opp[2]);
} else {
ctx[opp[1]] = opp[2];
}
} else if (opp[0] in special) {
// console.log("sepcial", opp[0], opp[1])
special[opp[0]].apply(ctx, opp[1]);
} else {
// console.log("execute", opp[0], opp[1]);
ctx[opp[0]].apply(ctx, opp[1]);
}
}
}
var onMessageState = WAIT;
myWorker.onmessage = function(event) {
var data = event.data;
console.log("onMessageRaw", data);
// console.log("onMessageRaw", data);
switch (onMessageState) {
case WAIT:
if (typeof data != "string") {
@ -28,11 +80,31 @@ myWorker.onmessage = function(event) {
case "canvas_proxy_stack":
onMessageState = CANVAS_PROXY_STACK;
return;
case "font":
onMessageState = FONT;
return;
default:
throw "unkown state: " + data
}
break;
case FONT:
data = JSON.parse(data);
var base64 = window.btoa(data.str);
// Add the @font-face rule to the document
var url = "url(data:" + data.mimetype + ";base64," + base64 + ");";
var rule = "@font-face { font-family:'" + data.fontName + "';src:" + url + "}";
var styleSheet = document.styleSheets[0];
// ONCE you uncomment this, there is no font painted at all :(
// styleSheet.insertRule(rule, styleSheet.length);
console.log("added font", data.fontName);
// console.log(rule);
onMessageState = WAIT;
break;
case LOG:
console.log.apply(console, JSON.parse(data));
onMessageState = WAIT;
@ -40,17 +112,14 @@ myWorker.onmessage = function(event) {
case CANVAS_PROXY_STACK:
var stack = JSON.parse(data);
for (var i = 0; i < stack.length; i++) {
var opp = stack[i];
if (opp[0] == "$") {
console.log("set property", opp[1], opp[2]);
ctx[opp[1]] = opp[2];
} else {
console.log("execute", opp[0], opp[1]);
ctx[opp[0]].apply(ctx, opp[1]);
}
}
console.log("canvas stack", stack.length)
// console.log(stack.length);
onMessageState = WAIT;
// return;
setTimeout(function() {
renderProxyCanvas(stack);
}, 2000);
break;
}
}
@ -75,6 +144,10 @@ function open(url) {
window.onload = function() {
var ctx = window.ctx = document.getElementById("canvas").getContext("2d");
ctx.save();
ctx.fillStyle = "rgb(255, 255, 255)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();
// for (var name in ctx) {
// if (!(ctx[name] instanceof Function)) {
// console.log('"' + name + '": "' + ctx[name] + '",');

View File

@ -40,6 +40,7 @@ var canvas = new CanvasProxy(1224, 1584);
// canvas.flush();
log("test");
var pageInterval;
onmessage = function(event) {
var data = event.data;
var pdfDocument = new PDFDoc(new Stream(data));
@ -59,36 +60,39 @@ onmessage = function(event) {
//
var fontsReady = true;
// Inspect fonts and translate the missing one
var count = fonts.length;
for (var i = 0; i < count; i++) {
var font = fonts[i];
if (Fonts[font.name]) {
fontsReady = fontsReady && !Fonts[font.name].loading;
continue;
}
// Inspect fonts and translate the missing one
var count = fonts.length;
for (var i = 0; i < count; i++) {
var font = fonts[i];
if (Fonts[font.name]) {
fontsReady = fontsReady && !Fonts[font.name].loading;
continue;
}
new Font(font.name, font.file, font.properties);
fontsReady = false;
}
new Font(font.name, font.file, font.properties);
fontsReady = false;
}
function delayLoadFont() {
for (var i = 0; i < count; i++) {
if (Fonts[font.name].loading)
return;
}
clearInterval(pageInterval);
page.display(gfx);
// function delayLoadFont() {
// for (var i = 0; i < count; i++) {
// if (Fonts[font.name].loading)
// return;
// }
// clearInterval(pageInterval);
// page.display(gfx);
//
// log("flush");
// canvas.flush();
// };
canvas.flush();
};
// if (fontsReady) {
// delayLoadFont();
// } else {
// pageInterval = setInterval(delayLoadFont, 10);
// }
if (fontsReady) {
delayLoadFont();
} else {
pageInterval = setInterval(delayLoadFont, 10);
}
postMessage(page.code.src);
page.display(gfx);
canvas.flush();
}
// function open(url) {