From: Artur Adib Date: Tue, 25 Oct 2011 17:16:20 +0000 (-0700) Subject: Only one worker file, bundled in pdf.js X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=21753b9e89983aa07d1647ca615fa3398c5e89fc;p=pdf.js.git Only one worker file, bundled in pdf.js --- diff --git a/Makefile b/Makefile index 46cddc1..a82d0ee 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ REPO = git@github.com:andreasgal/pdf.js.git BUILD_DIR := build +PDFJS_TARGET := $(BUILD_DIR)/pdf.js DEFAULT_BROWSERS := resources/browser_manifests/browser_manifest.json DEFAULT_TESTS := test_manifest.json @@ -10,7 +11,6 @@ EXTENSION_NAME := pdf.js.xpi -include local.mk # JS files needed for pdf.js. -# This list doesn't account for the 'worker' directory. PDF_JS_FILES = \ core.js \ util.js \ @@ -30,17 +30,9 @@ PDF_JS_FILES = \ parser.js \ pattern.js \ stream.js \ - worker/message_handler.js \ - worker/processor_handler.js \ + worker.js \ $(NULL) -PDF_WORKER_FILES = \ - worker/console.js \ - worker/message_handler.js \ - worker/pdf_worker_loader.js \ - worker/processor_handler.js \ - $(NULL) - # make server # # This target starts a local web server at localhost:8888. This can be @@ -55,10 +47,10 @@ test: pdfjs shell-test browser-test # pdfjs: @echo "Bundling source files..." - @mkdir -p build + @mkdir -p $(BUILD_DIR) @cd src; \ cat $(PDF_JS_FILES) > all_files.tmp; \ - sed -E '/INSERT_POINT/ r all_files.tmp' pdf.js > ../build/pdf.js; \ + sed -E '/INSERT_POINT/ r all_files.tmp' pdf.js > ../$(PDFJS_TARGET); \ rm -f all_files.tmp; \ cd .. @@ -121,7 +113,7 @@ browser-test: # To install gjslint, see: # # -SRC_DIRS := . utils worker web test examples/helloworld extensions/firefox \ +SRC_DIRS := . utils web test examples/helloworld extensions/firefox \ extensions/firefox/components GJSLINT_FILES = $(foreach DIR,$(SRC_DIRS),$(wildcard $(DIR)/*.js)) lint: @@ -138,7 +130,6 @@ lint: GH_PAGES = $(BUILD_DIR)/gh-pages web: | extension compiler pages-repo \ $(addprefix $(GH_PAGES)/, $(PDF_JS_FILES)) \ - $(addprefix $(GH_PAGES)/, $(PDF_WORKER_FILES)) \ $(addprefix $(GH_PAGES)/, $(wildcard web/*.*)) \ $(addprefix $(GH_PAGES)/, $(wildcard web/images/*.*)) \ $(addprefix $(GH_PAGES)/, $(wildcard $(EXTENSION_SRC)/*.xpi)) @@ -161,7 +152,6 @@ pages-repo: | $(BUILD_DIR) git clone -b gh-pages $(REPO) $(GH_PAGES); \ rm -rf $(GH_PAGES)/*; \ fi; - @mkdir -p $(GH_PAGES)/worker; @mkdir -p $(GH_PAGES)/web; @mkdir -p $(GH_PAGES)/web/images; @mkdir -p $(GH_PAGES)/$(EXTENSION_SRC); @@ -169,9 +159,6 @@ pages-repo: | $(BUILD_DIR) $(GH_PAGES)/%.js: %.js @cp $< $@ -$(GH_PAGES)/worker/%: worker/% - @cp $< $@ - $(GH_PAGES)/web/%: web/% @cp $< $@ @@ -206,14 +193,12 @@ PDF_WEB_FILES = \ web/viewer.js \ web/viewer.html \ $(NULL) -extension: +extension: | pdfjs # Copy a standalone version of pdf.js inside the content directory @rm -Rf $(EXTENSION_SRC)/$(CONTENT_DIR)/ @mkdir -p $(EXTENSION_SRC)/$(CONTENT_DIR)/web - @mkdir -p $(EXTENSION_SRC)/$(CONTENT_DIR)/worker - @cp $(PDF_JS_FILES) $(EXTENSION_SRC)/$(CONTENT_DIR)/ + @cp $(PDFJS_TARGET) $(EXTENSION_SRC)/$(CONTENT_DIR)/ @cp -r $(PDF_WEB_FILES) $(EXTENSION_SRC)/$(CONTENT_DIR)/web/ - @cp -r $(PDF_WORKER_FILES) $(EXTENSION_SRC)/$(CONTENT_DIR)/worker/ # Create the xpi @cd $(EXTENSION_SRC); zip -r $(EXTENSION_NAME) * diff --git a/src/core.js b/src/core.js index b969392..d195d4a 100644 --- a/src/core.js +++ b/src/core.js @@ -4,9 +4,6 @@ var ERRORS = 0, WARNINGS = 1, TODOS = 5; var verbosity = WARNINGS; -// Set this to true if you want to use workers. -var useWorker = false; - // // getPdf() // Convenience function to perform binary Ajax GET @@ -463,7 +460,7 @@ var PDFDoc = (function() { this.pageCache = []; if (useWorker) { - var worker = new Worker('../worker/pdf_worker_loader.js'); + var worker = new Worker('../build/pdf.js'); } else { // If we don't use a worker, just post/sendMessage to the main thread. var worker = { diff --git a/src/pdf.js b/src/pdf.js index 9970f90..cdbe64f 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -1,18 +1,32 @@ /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ -// // TODO: Global namespace -// var PDF = {}; +var PDF = {}; -(function(){ +(function(globalScope){ // Use strict in our context only - users might not want it 'use strict'; + // Set this to true if you want to use workers. + var useWorker = false; + var console; + // Files are inserted below - see Makefile /* INSERT_POINT */ - // Expose API in global object - window.PDFDoc = PDFDoc; - window.getPdf = getPdf; + // Worker-specific + if (typeof window !== 'undefined') { + console = window.console; + } else { + var consoleTimer = {}; + console = workerConsole; + + // Listen for messages from the main thread. + var handler = new MessageHandler('worker_processor', globalScope); + WorkerProcessorHandler.setup(handler); + } -})(); + // Expose API in global object + PDF.PDFDoc = PDFDoc; + PDF.getPdf = getPdf; +})(this); diff --git a/src/worker.js b/src/worker.js new file mode 100644 index 0000000..d8c8d59 --- /dev/null +++ b/src/worker.js @@ -0,0 +1,172 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ + +function MessageHandler(name, comObj) { + this.name = name; + this.comObj = comObj; + var ah = this.actionHandler = {}; + + ah['console_log'] = [function(data) { + console.log.apply(console, data); + }]; + ah['console_error'] = [function(data) { + console.error.apply(console, data); + }]; + + comObj.onmessage = function(event) { + var data = event.data; + if (data.action in ah) { + var action = ah[data.action]; + action[0].call(action[1], data.data); + } else { + throw 'Unkown action from worker: ' + data.action; + } + }; +} + +MessageHandler.prototype = { + on: function(actionName, handler, scope) { + var ah = this.actionHandler; + if (ah[actionName]) { + throw "There is already an actionName called '" + actionName + "'"; + } + ah[actionName] = [handler, scope]; + }, + + send: function(actionName, data) { + this.comObj.postMessage({ + action: actionName, + data: data + }); + } +}; + +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ + +var WorkerProcessorHandler = { + setup: function(handler) { + var pdfDoc = null; + + handler.on('doc', function(data) { + // Create only the model of the PDFDoc, which is enough for + // processing the content of the pdf. + pdfDoc = new PDFDocModel(new Stream(data)); + }); + + handler.on('page_request', function(pageNum) { + pageNum = parseInt(pageNum); + + var page = pdfDoc.getPage(pageNum); + + // The following code does quite the same as + // Page.prototype.startRendering, but stops at one point and sends the + // result back to the main thread. + var gfx = new CanvasGraphics(null); + + var start = Date.now(); + + var dependency = []; + + // Pre compile the pdf page and fetch the fonts/images. + var IRQueue = page.getIRQueue(handler, dependency); + + console.log('page=%d - getIRQueue: time=%dms, len=%d', pageNum, + Date.now() - start, IRQueue.fnArray.length); + + // Filter the dependecies for fonts. + var fonts = {}; + for (var i = 0; i < dependency.length; i++) { + var dep = dependency[i]; + if (dep.indexOf('font_') == 0) { + fonts[dep] = true; + } + } + + handler.send('page', { + pageNum: pageNum, + IRQueue: IRQueue, + 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]); + }); + } +}; + +var workerConsole = { + log: function log() { + var args = Array.prototype.slice.call(arguments); + postMessage({ + action: 'console_log', + data: args + }); + }, + + error: function error() { + var args = Array.prototype.slice.call(arguments); + postMessage({ + action: 'console_error', + data: args + }); + }, + + time: function(name) { + consoleTimer[name] = Date.now(); + }, + + timeEnd: function(name) { + var time = consoleTimer[name]; + if (time == null) { + throw 'Unkown timer name ' + name; + } + this.log('Timer:', name, Date.now() - time); + } +}; diff --git a/src/worker/console.js b/src/worker/console.js deleted file mode 100644 index 6d77e64..0000000 --- a/src/worker/console.js +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ - -var consoleTimer = {}; -var console = { - log: function log() { - var args = Array.prototype.slice.call(arguments); - postMessage({ - action: 'console_log', - data: args - }); - }, - - error: function error() { - var args = Array.prototype.slice.call(arguments); - postMessage({ - action: 'console_error', - data: args - }); - }, - - time: function(name) { - consoleTimer[name] = Date.now(); - }, - - timeEnd: function(name) { - var time = consoleTimer[name]; - if (time == null) { - throw 'Unkown timer name ' + name; - } - this.log('Timer:', name, Date.now() - time); - } -}; - diff --git a/src/worker/message_handler.js b/src/worker/message_handler.js deleted file mode 100644 index 64723f5..0000000 --- a/src/worker/message_handler.js +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / -/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ - -function MessageHandler(name, comObj) { - this.name = name; - this.comObj = comObj; - var ah = this.actionHandler = {}; - - ah['console_log'] = [function(data) { - console.log.apply(console, data); - }]; - ah['console_error'] = [function(data) { - console.error.apply(console, data); - }]; - - comObj.onmessage = function(event) { - var data = event.data; - if (data.action in ah) { - var action = ah[data.action]; - action[0].call(action[1], data.data); - } else { - throw 'Unkown action from worker: ' + data.action; - } - }; -} - -MessageHandler.prototype = { - on: function(actionName, handler, scope) { - var ah = this.actionHandler; - if (ah[actionName]) { - throw "There is already an actionName called '" + actionName + "'"; - } - ah[actionName] = [handler, scope]; - }, - - send: function(actionName, data) { - this.comObj.postMessage({ - action: actionName, - data: data - }); - } -}; - diff --git a/src/worker/pdf_worker_loader.js b/src/worker/pdf_worker_loader.js deleted file mode 100644 index c677253..0000000 --- a/src/worker/pdf_worker_loader.js +++ /dev/null @@ -1,19 +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('../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); diff --git a/src/worker/processor_handler.js b/src/worker/processor_handler.js deleted file mode 100644 index 47fb89a..0000000 --- a/src/worker/processor_handler.js +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / -/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ - -var WorkerProcessorHandler = { - setup: function(handler) { - var pdfDoc = null; - - handler.on('doc', function(data) { - // Create only the model of the PDFDoc, which is enough for - // processing the content of the pdf. - pdfDoc = new PDFDocModel(new Stream(data)); - }); - - handler.on('page_request', function(pageNum) { - pageNum = parseInt(pageNum); - - var page = pdfDoc.getPage(pageNum); - - // The following code does quite the same as - // Page.prototype.startRendering, but stops at one point and sends the - // result back to the main thread. - var gfx = new CanvasGraphics(null); - - var start = Date.now(); - - var dependency = []; - - // Pre compile the pdf page and fetch the fonts/images. - var IRQueue = page.getIRQueue(handler, dependency); - - console.log('page=%d - getIRQueue: time=%dms, len=%d', pageNum, - Date.now() - start, IRQueue.fnArray.length); - - // Filter the dependecies for fonts. - var fonts = {}; - for (var i = 0; i < dependency.length; i++) { - var dep = dependency[i]; - if (dep.indexOf('font_') == 0) { - fonts[dep] = true; - } - } - - handler.send('page', { - pageNum: pageNum, - IRQueue: IRQueue, - 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]); - }); - } -}; diff --git a/web/viewer.js b/web/viewer.js index 0b68f11..a6b0dea 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -122,7 +122,7 @@ var PDFView = { document.title = this.url = url; var self = this; - getPdf( + PDF.getPdf( { url: url, progress: function getPdfProgress(evt) { @@ -209,7 +209,7 @@ var PDFView = { while (container.hasChildNodes()) container.removeChild(container.lastChild); - var pdf = new PDFDoc(data); + var pdf = new PDF.PDFDoc(data); var pagesCount = pdf.numPages; document.getElementById('numPages').innerHTML = pagesCount; document.getElementById('pageNumber').max = pagesCount;