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
-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 \
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
#
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 ..
# To install gjslint, see:
#
# <http://code.google.com/closure/utilities/docs/linter_howto.html>
-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:
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))
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);
$(GH_PAGES)/%.js: %.js
@cp $< $@
-$(GH_PAGES)/worker/%: worker/%
- @cp $< $@
-
$(GH_PAGES)/web/%: web/%
@cp $< $@
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) *
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
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 = {
/* -*- 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);
--- /dev/null
+/* -*- 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);
+ }
+};
+++ /dev/null
-/* -*- 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);
- }
-};
-
+++ /dev/null
-/* -*- 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
- });
- }
-};
-
+++ /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: */
-
-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]);
- });
- }
-};
document.title = this.url = url;
var self = this;
- getPdf(
+ PDF.getPdf(
{
url: url,
progress: function getPdfProgress(evt) {
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;