},
bind: function fontLoaderBind(fonts, callback, objects) {
+ var fontsToLoad = {};
+ // check if there are twice the same font.
+ for (var i = 0; i < fonts.length; i++) {
+ var fontName = fonts[i].loadedName;
+ if (fontsToLoad[fontName]) {
+ throw "Got twice the same font!";
+ } else {
+ fontsToLoad[fontName] = true;
+ }
+ }
+
function checkFontsLoaded() {
for (var i = 0; i < objs.length; i++) {
var fontObj = objs[i];
},
ensureFonts: function(fonts, callback) {
- console.log('--ensureFonts--');
+ console.log('--ensureFonts--', '' + fonts);
// Convert the font names to the corresponding font obj.
for (var i = 0; i < fonts.length; i++) {
// HACK FOR NOW. Access the data directly. This isn't allowed as the
<script type="text/javascript" src="../worker.js"></script>
<script type="text/javascript" src="../worker/message_handler.js"></script>
<script type="text/javascript" src="../worker/processor_handler.js"></script>
- <script type="text/javascript" src="../worker/font_handler.js"></script>
</head>
<body>
this.pageCache = [];
if (useWorker) {
- var worker = this.worker = new Worker("../worker/processor_boot.js");
- var fontWorker = this.fontWorker = new Worker('../worker/font_boot.js');
+ var worker = this.worker = new Worker("../worker/pdf_worker_loader.js");
} else {
// If we don't use a worker, just post/sendMessage to the main thread.
var worker = {
worker.onmessage({data: obj});
}
}
- var fontWorker = {
- postMessage: function(obj) {
- fontWorker.onmessage({data: obj});
- }
- }
}
+
+ this.fontsLoading = {};
var processorHandler = this.processorHandler = new MessageHandler("main", worker);
processorHandler.on("page", function(data) {
// are all the fonts that are required to render the page AND that
// aren't loaded on the page yet.
var depFonts = data.depFonts;
- var fontsToLoad = [];
var objs = this.objs;
+ var fontsToLoad = [];
+ var fontsLoading = this.fontsLoading;
+ // The `i` for the checkFontData is stored here to keep the state in
+ // the closure.
+ var i = 0;
+
function checkFontData() {
// Check if all fontObjs have been processed. If not, shedule a
// callback that is called once the data arrives and that checks
// the next fonts.
- for (var i = 0; i < depFonts.length; i++) {
+ for (i; i < depFonts.length; i++) {
var fontName = depFonts[i];
if (!objs.hasData(fontName)) {
console.log('need to wait for fontData', fontName);
- objs.onData(fontObj, checkFontData);
+ objs.onData(fontName, checkFontData);
return;
} else if (!objs.isResolved(fontName)) {
fontsToLoad.push(fontName);
}
}
+
+ // There can be edge cases where two pages wait for one font and then
+ // call startRenderingFromIRQueue twice with the same font. That makes
+ // the font getting loaded twice and throw an error later as the font
+ // promise gets resolved twice.
+ // This prevents thats fonts are loaded really only once.
+ for (var j = 0; j < fontsToLoad.length; j++) {
+ var fontName = fontsToLoad[j];
+ if (fontsLoading[fontName]) {
+ fontsToLoad.splice(j, 1);
+ j--;
+ } else {
+ fontsLoading[fontName] = true;
+ }
+ }
// At this point, all font data ia loaded. Start the actuall rendering.
page.startRenderingFromIRQueue(data.IRQueue, fontsToLoad);
var file = data[3];
var properties = data[4];
- fontHandler.send("font", [objId, name, file, properties]);
+ processorHandler.send("font", [objId, name, file, properties]);
break;
default:
throw "Got unkown object type " + objType;
}
}, this);
- var fontHandler = this.fontHandler = new MessageHandler('font', fontWorker);
- fontHandler.on('font_ready', function(data) {
+ processorHandler.on('font_ready', function(data) {
var objId = data[0];
var fontObj = new FontShape(data[1]);
// If the main thread is our worker, setup the handling for the messages
// the main thread sends to it self.
WorkerProcessorHandler.setup(processorHandler);
- WorkerFontHandler.setup(fontHandler);
}
processorHandler.send("doc", data);
+++ /dev/null
-/* -*- 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('message_handler.js');
-importScripts('../pdf.js');
-importScripts('../fonts.js');
-importScripts('../crypto.js');
-importScripts('../glyphlist.js');
-importScripts('font_handler.js');
-
-
-var handler = new MessageHandler("worker_font", this);
-WorkerFontHandler.setup(handler);
+++ /dev/null
-var WorkerFontHandler = {
- setup: function(handler) {
- handler.on("font", function(data) {
- var objId = data[0];
- var name = data[1];
- var file = data[2];
- var properties = data[3];
-
- var font = {
- name: name,
- file: file,
- properties: properties
- };
-
- // Some fonts don't have a file, e.g. the build in ones like Arial.
- if (file) {
- var fontFileDict = new Dict();
- fontFileDict.map = file.dict.map;
-
- var fontFile = new Stream(file.bytes, file.start,
- file.end - file.start, fontFileDict);
-
- // Check if this is a FlateStream. Otherwise just use the created
- // Stream one. This makes complex_ttf_font.pdf work.
- var cmf = file.bytes[0];
- if ((cmf & 0x0f) == 0x08) {
- font.file = new FlateStream(fontFile);
- } else {
- font.file = fontFile;
- }
- }
-
- var obj = new Font(font.name, font.file, font.properties);
-
- var str = '';
- var data = obj.data;
- if (data) {
- var length = data.length;
- for (var j = 0; j < length; j++)
- str += String.fromCharCode(data[j]);
- }
-
- obj.str = str;
-
- // Remove the data array form the font object, as it's not needed
- // anymore as we sent over the ready str.
- delete obj.data;
-
- handler.send("font_ready", [objId, obj]);
- });
- }
-}
--- /dev/null
+/* -*- 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('message_handler.js');
+importScripts('../pdf.js');
+importScripts('../fonts.js');
+importScripts('../crypto.js');
+importScripts('../glyphlist.js');
+importScripts('../metrics.js');
+importScripts('processor_handler.js');
+
+// Listen for messages from the main thread.
+var pdfDoc = null;
+
+var handler = new MessageHandler("worker_processor", this);
+WorkerProcessorHandler.setup(handler);
+++ /dev/null
-/* -*- 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('message_handler.js');
-importScripts('../pdf.js');
-importScripts('../fonts.js');
-importScripts('../crypto.js');
-importScripts('../glyphlist.js');
-importScripts('../metrics.js');
-importScripts('processor_handler.js');
-
-// Listen for messages from the main thread.
-var pdfDoc = null;
-
-var handler = new MessageHandler("worker_processor", this);
-WorkerProcessorHandler.setup(handler);
depFonts: Object.keys(fonts)
});
}, this);
+
+ handler.on("font", function(data) {
+ var objId = data[0];
+ var name = data[1];
+ var file = data[2];
+ var properties = data[3];
+
+ var font = {
+ name: name,
+ file: file,
+ properties: properties
+ };
+
+ // Some fonts don't have a file, e.g. the build in ones like Arial.
+ if (file) {
+ var fontFileDict = new Dict();
+ fontFileDict.map = file.dict.map;
+
+ var fontFile = new Stream(file.bytes, file.start,
+ file.end - file.start, fontFileDict);
+
+ // Check if this is a FlateStream. Otherwise just use the created
+ // Stream one. This makes complex_ttf_font.pdf work.
+ var cmf = file.bytes[0];
+ if ((cmf & 0x0f) == 0x08) {
+ font.file = new FlateStream(fontFile);
+ } else {
+ font.file = fontFile;
+ }
+ }
+
+ var obj = new Font(font.name, font.file, font.properties);
+
+ var str = '';
+ var data = obj.data;
+ if (data) {
+ var length = data.length;
+ for (var j = 0; j < length; j++)
+ str += String.fromCharCode(data[j]);
+ }
+
+ obj.str = str;
+
+ // Remove the data array form the font object, as it's not needed
+ // anymore as we sent over the ready str.
+ delete obj.data;
+
+ handler.send("font_ready", [objId, obj]);
+ });
}
}