From d7521f758aadbde040c819ca62a66364a2c92726 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Wed, 5 Oct 2011 22:24:38 +0200 Subject: [PATCH] Merge font and processor working into one worker and fix some bugs in font-loading-data-ready code --- fonts.js | 11 ++++ pdf.js | 2 +- web/viewer.html | 1 - worker.js | 42 ++++++++++----- worker/font_boot.js | 16 ------ worker/font_handler.js | 52 ------------------- ...processor_boot.js => pdf_worker_loader.js} | 0 worker/processor_handler.js | 49 +++++++++++++++++ 8 files changed, 89 insertions(+), 84 deletions(-) delete mode 100644 worker/font_boot.js delete mode 100644 worker/font_handler.js rename worker/{processor_boot.js => pdf_worker_loader.js} (100%) diff --git a/fonts.js b/fonts.js index 32f879563..974c8e79a 100755 --- a/fonts.js +++ b/fonts.js @@ -211,6 +211,17 @@ var FontLoader = { }, 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]; diff --git a/pdf.js b/pdf.js index c0fa98d5f..d7088e67c 100644 --- a/pdf.js +++ b/pdf.js @@ -3387,7 +3387,7 @@ var Page = (function() { }, 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 diff --git a/web/viewer.html b/web/viewer.html index 33026a492..6168710e4 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -14,7 +14,6 @@ - diff --git a/worker.js b/worker.js index a89ffb7a7..0f686b42b 100644 --- a/worker.js +++ b/worker.js @@ -264,8 +264,7 @@ var WorkerPDFDoc = (function() { 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 = { @@ -273,12 +272,9 @@ var WorkerPDFDoc = (function() { 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) { @@ -289,23 +285,43 @@ var WorkerPDFDoc = (function() { // 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); @@ -329,15 +345,14 @@ var WorkerPDFDoc = (function() { 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]); @@ -355,7 +370,6 @@ var WorkerPDFDoc = (function() { // 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); diff --git a/worker/font_boot.js b/worker/font_boot.js deleted file mode 100644 index 9158d20a1..000000000 --- a/worker/font_boot.js +++ /dev/null @@ -1,16 +0,0 @@ -/* -*- 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); diff --git a/worker/font_handler.js b/worker/font_handler.js deleted file mode 100644 index 3479090a0..000000000 --- a/worker/font_handler.js +++ /dev/null @@ -1,52 +0,0 @@ -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]); - }); - } -} diff --git a/worker/processor_boot.js b/worker/pdf_worker_loader.js similarity index 100% rename from worker/processor_boot.js rename to worker/pdf_worker_loader.js diff --git a/worker/processor_handler.js b/worker/processor_handler.js index 28c89db10..7c218e64d 100644 --- a/worker/processor_handler.js +++ b/worker/processor_handler.js @@ -63,5 +63,54 @@ var WorkerProcessorHandler = { 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]); + }); } }