Make the fonts decoding code works with asynchronous data url
This commit is contained in:
parent
c03dd98075
commit
b0ee046b31
104
PDFFont.js
104
PDFFont.js
@ -11,6 +11,16 @@ var kMaxFontFileSize = 40000;
|
||||
*/
|
||||
var kMaxGlyphsCount = 1024;
|
||||
|
||||
/**
|
||||
* Maximum time to wait for a font to be loaded by @font-face
|
||||
*/
|
||||
var kMaxWaitForFontFace = 2000;
|
||||
|
||||
/*
|
||||
* Useful for debugging when you want to certains operations depending on how
|
||||
* many fonts are loaded.
|
||||
*/
|
||||
var fontCount = 0;
|
||||
|
||||
/**
|
||||
* Hold a map of decoded fonts and of the standard fourteen Type1 fonts and
|
||||
@ -36,9 +46,10 @@ var Font = function(aFontName, aFontFile, aFontType) {
|
||||
|
||||
// If the font has already been decoded simply return
|
||||
if (Fonts[aFontName]) {
|
||||
this.font = Fonts[aFontName];
|
||||
this.font = Fonts[aFontName].data;
|
||||
return;
|
||||
}
|
||||
fontCount++;
|
||||
|
||||
var start = Date.now();
|
||||
switch (aFontType) {
|
||||
@ -62,10 +73,13 @@ var Font = function(aFontName, aFontFile, aFontType) {
|
||||
}
|
||||
var end = Date.now();
|
||||
|
||||
Fonts[aFontName] = {
|
||||
data: this.font,
|
||||
loading: true
|
||||
}
|
||||
|
||||
// Attach the font to the document
|
||||
this.bind();
|
||||
|
||||
Fonts[aFontName] = this.font;
|
||||
};
|
||||
|
||||
Font.prototype = {
|
||||
@ -84,10 +98,90 @@ Font.prototype = {
|
||||
: String.fromCharCode(data[i]));
|
||||
|
||||
var dataBase64 = window.btoa(str.join(""));
|
||||
var fontName = this.name;
|
||||
|
||||
/** Hack begin */
|
||||
|
||||
// Actually there is not event when a font has finished downloading so
|
||||
// the following tons of code are a dirty hack to 'guess' when a font is
|
||||
// ready
|
||||
var debug = false;
|
||||
|
||||
var canvas = document.createElement("canvas");
|
||||
var style = "position:absolute; left: " +
|
||||
(debug ? (100 * fontCount) : "-200") + "px; top: -200px;";
|
||||
canvas.setAttribute("style", style);
|
||||
canvas.setAttribute("width", 100);
|
||||
canvas.setAttribute("heigth", 100);
|
||||
document.body.appendChild(canvas);
|
||||
|
||||
// Get the first character of the font
|
||||
var page = pdfDocument.getPage(pageNum);
|
||||
var xref = page.xref;
|
||||
var resources = xref.fetchIfRef(page.resources);
|
||||
var fontResource = resources.get("Font");
|
||||
var charset = "";
|
||||
for (var id in fontResource.map) {
|
||||
var res = xref.fetch(fontResource.get(id));
|
||||
var descriptor = xref.fetch(res.get("FontDescriptor"));
|
||||
var name = descriptor.get("FontName").toString();
|
||||
var font = Fonts[name.replace("+", "_")];
|
||||
if (font && font.loading && name == fontName.replace("_", "+")) {
|
||||
charset = descriptor.get("CharSet").split("/");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Warn if the charset is not found, this is likely a bug!
|
||||
var testCharset = charset;
|
||||
if (!charset) {
|
||||
warn("No charset found for: " + fontName);
|
||||
} else {
|
||||
// if the charset is too small make it repeat a few times
|
||||
var count = 30;
|
||||
while (count-- && testCharset.length <= 30)
|
||||
testCharset = testCharset.concat(charset.slice());
|
||||
}
|
||||
|
||||
// Get the font size canvas think it will be
|
||||
var ctx = canvas.getContext("2d");
|
||||
var testString = "";
|
||||
for (var i = 0; i < testCharset.length; i++) {
|
||||
var unicode = new Number("0x" + GlyphsUnicode[testCharset[i]]);
|
||||
if (!unicode)
|
||||
error("Unicode for " + testCharset[i] + " is has not been found in the glyphs list");
|
||||
testString += String.fromCharCode(unicode);
|
||||
}
|
||||
ctx.font = "20px " + fontName + ", Symbol";
|
||||
var textWidth = ctx.mozMeasureText(testString);
|
||||
|
||||
if (debug)
|
||||
ctx.fillText(testString, 20, 20);
|
||||
|
||||
var start = Date.now();
|
||||
var interval = window.setInterval(function(self) {
|
||||
ctx.font = "20px " + fontName + ", Symbol";
|
||||
|
||||
// For some reasons the font has not loaded, so mark it loaded for the
|
||||
// page to proceed but cry
|
||||
if ((Date.now() - start) >= kMaxWaitForFontFace) {
|
||||
window.clearInterval(interval);
|
||||
Fonts[fontName].loading = false;
|
||||
warn("Is " + fontName + " for charset: " + charset + " loaded?");
|
||||
} else if (textWidth != ctx.mozMeasureText(testString)) {
|
||||
window.clearInterval(interval);
|
||||
Fonts[fontName].loading = false;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
ctx.fillText(testString, 20, 60);
|
||||
}, 150, this);
|
||||
|
||||
/** Hack end */
|
||||
|
||||
// Add the @font-face rule to the document
|
||||
var url = "url(data:" + this.mimetype + ";base64," + dataBase64 + ");";
|
||||
var rule = "@font-face { font-family:'" + this.name + "';src:" + url + "}";
|
||||
var rule = "@font-face { font-family:'" + fontName + "';src:" + url + "}";
|
||||
var styleSheet = document.styleSheets[0];
|
||||
styleSheet.insertRule(rule, styleSheet.length);
|
||||
},
|
||||
@ -473,7 +567,6 @@ var TrueType = function(aFontName, aFontFile) {
|
||||
*/
|
||||
var PSFonts = new Dict();
|
||||
|
||||
|
||||
var Stack = function(aStackSize) {
|
||||
var innerStack = new Array(aStackSize || 0);
|
||||
|
||||
@ -1136,7 +1229,6 @@ var Type1Parser = function(aAsciiStream, aBinaryStream) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var CFF = function(aFontName, aFontFile) {
|
||||
var start = Date.now();
|
||||
|
||||
|
15
pdf.js
15
pdf.js
@ -1399,6 +1399,19 @@ var Page = (function() {
|
||||
? obj
|
||||
: null));
|
||||
},
|
||||
get fonts() {
|
||||
var xref = this.xref;
|
||||
var fonts = [];
|
||||
|
||||
var resources = xref.fetchIfRef(this.resources);
|
||||
var fontResource = resources.get("Font");
|
||||
for (var id in fontResource.map) {
|
||||
var res = xref.fetch(fontResource.get(id));
|
||||
var descriptor = xref.fetch(res.get("FontDescriptor"));
|
||||
fonts.push(descriptor.get("FontName").toString());
|
||||
}
|
||||
return shadow(this, "fonts", fonts);
|
||||
},
|
||||
display: function(gfx) {
|
||||
var xref = this.xref;
|
||||
var contents = xref.fetchIfRef(this.contents);
|
||||
@ -1843,7 +1856,7 @@ var CanvasGraphics = (function() {
|
||||
var fontFile = this.xref.fetchIfRef(fontDescriptor.get("FontFile"));
|
||||
if (!fontFile)
|
||||
fontFile = this.xref.fetchIfRef(fontDescriptor.get("FontFile2"));
|
||||
fontName = fontDescriptor.get("FontName").name.replace("+", " ");
|
||||
fontName = fontDescriptor.get("FontName").name.replace("+", "_");
|
||||
new Font(fontName, fontFile, subtype);
|
||||
}
|
||||
|
||||
|
61
test.js
61
test.js
@ -21,7 +21,6 @@ function queryParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
function open(url) {
|
||||
document.title = url;
|
||||
req = new XMLHttpRequest();
|
||||
@ -54,21 +53,59 @@ function displayPage(num) {
|
||||
|
||||
var page = pdfDocument.getPage(pageNum = num);
|
||||
|
||||
var t1 = Date.now();
|
||||
function display() {
|
||||
var t1 = Date.now();
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.save();
|
||||
ctx.fillStyle = "rgb(255, 255, 255)";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.save();
|
||||
ctx.fillStyle = "rgb(255, 255, 255)";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
var gfx = new CanvasGraphics(ctx);
|
||||
page.display(gfx);
|
||||
|
||||
var gfx = new CanvasGraphics(ctx);
|
||||
page.display(gfx);
|
||||
var t2 = Date.now();
|
||||
var infoDisplay = document.getElementById("info");
|
||||
infoDisplay.innerHTML = "Time to render: "+ (t1 - t0) + "/" + (t2 - t1) + " ms";
|
||||
}
|
||||
|
||||
var t2 = Date.now();
|
||||
// Loading a font via data uri is asynchronous, so wait for all font
|
||||
// of the page to be fully loaded before loading the page
|
||||
var fontsReady = true;
|
||||
var fonts = page.fonts;
|
||||
for (var i = 0; i < fonts.length; i++) {
|
||||
var fontName = fonts[i].replace("+", "_");
|
||||
var font = Fonts[fontName];
|
||||
if (!font) {
|
||||
// load the new font
|
||||
var xref = page.xref;
|
||||
var resources = xref.fetchIfRef(page.resources);
|
||||
var fontResource = resources.get("Font");
|
||||
for (var id in fontResource.map) {
|
||||
var res = xref.fetch(fontResource.get(id));
|
||||
var descriptor = xref.fetch(res.get("FontDescriptor"));
|
||||
var name = descriptor.get("FontName").toString();
|
||||
if (name == fontName.replace("_", "+")) {
|
||||
var subtype = res.get("Subtype").name;
|
||||
var fontFile = page.xref.fetchIfRef(descriptor.get("FontFile"));
|
||||
if (!fontFile)
|
||||
fontFile = page.xref.fetchIfRef(descriptor.get("FontFile2"));
|
||||
new Font(fontName, fontFile, subtype);
|
||||
fontsReady = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (font.loading) {
|
||||
fontsReady = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var infoDisplay = document.getElementById("info");
|
||||
infoDisplay.innerHTML = "Time to render: "+ (t1 - t0) + "/" + (t2 - t1) + " ms";
|
||||
// If everything is ready do not delayed the page loading any more
|
||||
if (fontsReady)
|
||||
display();
|
||||
else
|
||||
setTimeout(displayPage, 150, num);
|
||||
}
|
||||
|
||||
function nextPage() {
|
||||
|
Loading…
Reference in New Issue
Block a user