"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)]);
}
}
}
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;
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);
+
+ // 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);
+
+ // 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());
+
+ for (var i = 0; i < charset.length; i++) {
+ var unicode = GlyphsUnicode[charset[i]];
+ if (!unicode)
+ continue;
+ testString += String.fromCharCode(unicode);
+ }
- // 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 = " ";
-
- // 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 || [];
-
- // 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);
- }
-
- 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;
-
- 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;
- }
+ // 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";
+
+ // 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);
-
- // 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);
+ if (isWorker) {
+ postMessage("font");
+ postMessage(JSON.stringify({
+ str: str,
+ mimetype: this.mimetype,
+ fontName: fontName,
+ }));
+
+ 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);
+ }
}
};
},
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();
}
// 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;
},
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);
},
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;
},
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();
},
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 {
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") {
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;
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;
}
}
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] + '",');
// canvas.flush();
log("test");
+var pageInterval;
onmessage = function(event) {
var data = event.data;
var pdfDocument = new PDFDoc(new Stream(data));
//
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;
- }
-
- 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);
-
- canvas.flush();
- };
-
- if (fontsReady) {
- delayLoadFont();
- } else {
- pageInterval = setInterval(delayLoadFont, 10);
- }
- postMessage(page.code.src);
+ // 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;
+ }
+
+ // function delayLoadFont() {
+ // for (var i = 0; i < count; i++) {
+ // if (Fonts[font.name].loading)
+ // return;
+ // }
+ // clearInterval(pageInterval);
+ // page.display(gfx);
+ //
+ // log("flush");
+ // canvas.flush();
+ // };
+
+ // if (fontsReady) {
+ // delayLoadFont();
+ // } else {
+ // pageInterval = setInterval(delayLoadFont, 10);
+ // }
+
+ page.display(gfx);
+ canvas.flush();
}
// function open(url) {