Merge branch 'api' of https://github.com/mozilla/pdf.js into api
This commit is contained in:
commit
459e08d1b4
137
src/api.js
137
src/api.js
@ -1,6 +1,16 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
/**
|
||||
* This is the main entry point for loading a PDF and interacting with it.
|
||||
* NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR)
|
||||
* is used, which means it must follow the same origin rules that any XHR does
|
||||
* e.g. No cross domain requests without CORS.
|
||||
*
|
||||
* @param {string|TypedAray} source Either a url to a PDF is located or a
|
||||
* typed array already populated with data.
|
||||
* @return {Promise} A promise that is resolved with {PDFDocumentProxy} object.
|
||||
*/
|
||||
PDFJS.getDocument = function getDocument(source) {
|
||||
var promise = new PDFJS.Promise();
|
||||
var transport = new WorkerTransport(promise);
|
||||
@ -31,33 +41,74 @@ PDFJS.getDocument = function getDocument(source) {
|
||||
return promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Proxy to a PDFDocument in the worker thread. Also, contains commonly used
|
||||
* properties that can be read synchronously.
|
||||
*/
|
||||
var PDFDocumentProxy = (function() {
|
||||
function PDFDocumentProxy(pdfInfo, transport) {
|
||||
this.pdfInfo = pdfInfo;
|
||||
this.transport = transport;
|
||||
}
|
||||
PDFDocumentProxy.prototype = {
|
||||
/**
|
||||
* @return {number} Total number of pages the PDF contains.
|
||||
*/
|
||||
get numPages() {
|
||||
return this.pdfInfo.numPages;
|
||||
},
|
||||
/**
|
||||
* @return {string} A unique ID to identify a PDF. Not guaranteed to be
|
||||
* unique.
|
||||
*/
|
||||
get fingerprint() {
|
||||
return this.pdfInfo.fingerprint;
|
||||
},
|
||||
/**
|
||||
* @param {number} The page number to get. The first page is 1.
|
||||
* @return {Promise} A promise that is resolved with a {PDFPageProxy}
|
||||
* object.
|
||||
*/
|
||||
getPage: function(number) {
|
||||
return this.transport.getPage(number);
|
||||
},
|
||||
/**
|
||||
* @return {Promise} A promise that is resolved with a lookup table for
|
||||
* mapping named destinations to reference numbers.
|
||||
*/
|
||||
getDestinations: function() {
|
||||
var promise = new PDFJS.Promise();
|
||||
var destinations = this.pdfInfo.destinations;
|
||||
promise.resolve(destinations);
|
||||
return promise;
|
||||
},
|
||||
/**
|
||||
* @return {Promise} A promise that is resolved with an {array} that is a
|
||||
* tree outline (if it has one) of the PDF. The tree is in the format of:
|
||||
* [
|
||||
* {
|
||||
* title: string,
|
||||
* bold: boolean,
|
||||
* italic: boolean,
|
||||
* color: rgb array,
|
||||
* dest: dest obj,
|
||||
* items: array of more items like this
|
||||
* },
|
||||
* ...
|
||||
* ].
|
||||
*/
|
||||
getOutline: function() {
|
||||
var promise = new PDFJS.Promise();
|
||||
var outline = this.pdfInfo.outline;
|
||||
promise.resolve(outline);
|
||||
return promise;
|
||||
},
|
||||
/**
|
||||
* @return {Promise} A promise that is resolved with an {object} that has
|
||||
* info and metadata properties. Info is an {object} filled with anything
|
||||
* available in the information dictionary and similarly metadata is a
|
||||
* {Metadata} object with information from the metadata section of the PDF.
|
||||
*/
|
||||
getMetadata: function() {
|
||||
var promise = new PDFJS.Promise();
|
||||
var info = this.pdfInfo.info;
|
||||
@ -84,30 +135,69 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
this.objs = transport.objs;
|
||||
}
|
||||
PDFPageProxy.prototype = {
|
||||
/**
|
||||
* @return {number} Page number of the page. First page is 1.
|
||||
*/
|
||||
get pageNumber() {
|
||||
return this.pageInfo.pageIndex + 1;
|
||||
},
|
||||
/**
|
||||
* @return {number} The number of degrees the page is rotated clockwise.
|
||||
*/
|
||||
get rotate() {
|
||||
return this.pageInfo.rotate;
|
||||
},
|
||||
/**
|
||||
* @return {object} The reference that points to this page. It has 'num' and
|
||||
* 'gen' properties.
|
||||
*/
|
||||
get ref() {
|
||||
return this.pageInfo.ref;
|
||||
},
|
||||
/**
|
||||
* @return {array} An array of the visible portion of the PDF page in the
|
||||
* user space units - [x1, y1, x2, y2].
|
||||
*/
|
||||
get view() {
|
||||
return this.pageInfo.view;
|
||||
},
|
||||
/**
|
||||
* @param {number} scale The desired scale of the viewport.
|
||||
* @param {number} rotate Degrees to rotate the viewport. If omitted this
|
||||
* defaults to the page rotation.
|
||||
* @return {PageViewport} Contains 'width' and 'height' properties along
|
||||
* with transforms required for rendering.
|
||||
*/
|
||||
getViewport: function(scale, rotate) {
|
||||
if (arguments.length < 2)
|
||||
rotate = this.rotate;
|
||||
return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
|
||||
},
|
||||
/**
|
||||
* @return {Promise} A promise that is resolved with an {array} of the
|
||||
* annotation objects.
|
||||
*/
|
||||
getAnnotations: function() {
|
||||
if (this.annotationsPromise)
|
||||
return this.annotationsPromise;
|
||||
|
||||
var promise = new PDFJS.Promise();
|
||||
var annotations = this.pageInfo.annotations;
|
||||
promise.resolve(annotations);
|
||||
this.annotationsPromise = promise;
|
||||
this.transport.getAnnotations(this.pageInfo.pageIndex);
|
||||
return promise;
|
||||
},
|
||||
render: function(renderContext) {
|
||||
/**
|
||||
* Begins the process of rendering a page to the desired context.
|
||||
* @param {object} params A parameter object that supports:
|
||||
* {
|
||||
* canvasContext(required): A 2D context of a DOM Canvas object.,
|
||||
* textLayer(optional): An object that has beginLayout, endLayout, and
|
||||
* appendText functions.
|
||||
* }.
|
||||
* @return {Promise} A promise that is resolved when the page finishes
|
||||
* rendering.
|
||||
*/
|
||||
render: function(params) {
|
||||
var promise = new Promise();
|
||||
var stats = this.stats;
|
||||
stats.time('Overall');
|
||||
@ -132,10 +222,10 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
// Once the operatorList and fonts are loaded, do the actual rendering.
|
||||
this.displayReadyPromise.then(
|
||||
function pageDisplayReadyPromise() {
|
||||
var gfx = new CanvasGraphics(renderContext.canvasContext,
|
||||
this.objs, renderContext.textLayer);
|
||||
var gfx = new CanvasGraphics(params.canvasContext,
|
||||
this.objs, params.textLayer);
|
||||
try {
|
||||
this.display(gfx, renderContext.viewport, complete);
|
||||
this.display(gfx, params.viewport, complete);
|
||||
} catch (e) {
|
||||
complete(e);
|
||||
}
|
||||
@ -147,7 +237,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
|
||||
return promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* For internal use only.
|
||||
*/
|
||||
startRenderingFromOperatorList:
|
||||
function PDFPageWrapper_startRenderingFromOperatorList(operatorList,
|
||||
fonts) {
|
||||
@ -168,7 +260,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* For internal use only.
|
||||
*/
|
||||
ensureFonts: function PDFPageWrapper_ensureFonts(fonts, callback) {
|
||||
this.stats.time('Font Loading');
|
||||
// Convert the font names to the corresponding font obj.
|
||||
@ -186,7 +280,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
}.bind(this)
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* For internal use only.
|
||||
*/
|
||||
display: function PDFPageWrapper_display(gfx, viewport, callback) {
|
||||
var stats = this.stats;
|
||||
stats.time('Rendering');
|
||||
@ -209,6 +305,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
gfx.executeOperatorList(operatorList, startIdx, next, stepper);
|
||||
if (startIdx == length) {
|
||||
gfx.endDrawing();
|
||||
delete this.operatorList;
|
||||
stats.timeEnd('Rendering');
|
||||
stats.timeEnd('Overall');
|
||||
if (callback) callback();
|
||||
@ -216,13 +313,18 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
}
|
||||
next();
|
||||
},
|
||||
|
||||
/**
|
||||
* Stub for future feature.
|
||||
*/
|
||||
getTextContent: function() {
|
||||
var promise = new PDFJS.Promise();
|
||||
var textContent = 'page text'; // not implemented
|
||||
promise.resolve(textContent);
|
||||
return promise;
|
||||
},
|
||||
/**
|
||||
* Stub for future feature.
|
||||
*/
|
||||
getOperationList: function() {
|
||||
var promise = new PDFJS.Promise();
|
||||
var operationList = { // not implemented
|
||||
@ -235,7 +337,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
};
|
||||
return PDFPageProxy;
|
||||
})();
|
||||
|
||||
/**
|
||||
* For internal use only.
|
||||
*/
|
||||
var WorkerTransport = (function WorkerTransportClosure() {
|
||||
function WorkerTransport(promise) {
|
||||
this.workerReadyPromise = promise;
|
||||
@ -342,6 +446,12 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
promise.resolve(page);
|
||||
}, this);
|
||||
|
||||
messageHandler.on('GetAnnotations', function transportAnnotations(data) {
|
||||
var annotations = data.annotations;
|
||||
var promise = this.pageCache[data.pageIndex].annotationsPromise;
|
||||
promise.resolve(annotations);
|
||||
}, this);
|
||||
|
||||
messageHandler.on('RenderPage', function transportRender(data) {
|
||||
var page = this.pageCache[data.pageIndex];
|
||||
var depFonts = data.depFonts;
|
||||
@ -440,6 +550,11 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
this.pagePromises[pageIndex] = promise;
|
||||
this.messageHandler.send('GetPageRequest', { pageIndex: pageIndex });
|
||||
return promise;
|
||||
},
|
||||
|
||||
getAnnotations: function WorkerTransport_getAnnotations(pageIndex) {
|
||||
this.messageHandler.send('GetAnnotationsRequest',
|
||||
{ pageIndex: pageIndex });
|
||||
}
|
||||
};
|
||||
return WorkerTransport;
|
||||
|
@ -466,7 +466,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
args = [];
|
||||
} else if (obj != null) {
|
||||
assertWellFormed(args.length <= 33, 'Too many arguments');
|
||||
args.push(obj);
|
||||
args.push(obj instanceof Dict ? obj.getAll() : obj);
|
||||
}
|
||||
}
|
||||
|
||||
@ -862,7 +862,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
properties.coded = true;
|
||||
var charProcs = dict.get('CharProcs').getAll();
|
||||
var fontResources = dict.get('Resources') || resources;
|
||||
properties.resources = fontResources;
|
||||
properties.charProcOperatorList = {};
|
||||
for (var key in charProcs) {
|
||||
var glyphStream = charProcs[key];
|
||||
|
@ -766,7 +766,6 @@ var Font = (function FontClosure() {
|
||||
this.name = name;
|
||||
this.coded = properties.coded;
|
||||
this.charProcOperatorList = properties.charProcOperatorList;
|
||||
this.resources = properties.resources;
|
||||
this.sizes = [];
|
||||
|
||||
var names = name.split('+');
|
||||
|
64
src/obj.js
64
src/obj.js
@ -37,51 +37,55 @@ var Dict = (function DictClosure() {
|
||||
// xref is optional
|
||||
function Dict(xref) {
|
||||
// Map should only be used internally, use functions below to access.
|
||||
this.map = Object.create(null);
|
||||
this.xref = xref;
|
||||
}
|
||||
var map = Object.create(null);
|
||||
|
||||
this.assignXref = function Dict_assingXref(newXref) {
|
||||
xref = newXref;
|
||||
};
|
||||
|
||||
Dict.prototype = {
|
||||
// automatically dereferences Ref objects
|
||||
get: function Dict_get(key1, key2, key3) {
|
||||
this.get = function Dict_get(key1, key2, key3) {
|
||||
var value;
|
||||
var xref = this.xref;
|
||||
if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map ||
|
||||
if (typeof (value = map[key1]) != 'undefined' || key1 in map ||
|
||||
typeof key2 == 'undefined') {
|
||||
return xref ? this.xref.fetchIfRef(value) : value;
|
||||
return xref ? xref.fetchIfRef(value) : value;
|
||||
}
|
||||
if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map ||
|
||||
if (typeof (value = map[key2]) != 'undefined' || key2 in map ||
|
||||
typeof key3 == 'undefined') {
|
||||
return xref ? this.xref.fetchIfRef(value) : value;
|
||||
return xref ? xref.fetchIfRef(value) : value;
|
||||
}
|
||||
value = this.map[key3] || null;
|
||||
return xref ? this.xref.fetchIfRef(value) : value;
|
||||
},
|
||||
value = map[key3] || null;
|
||||
return xref ? xref.fetchIfRef(value) : value;
|
||||
};
|
||||
|
||||
// no dereferencing
|
||||
getRaw: function Dict_getRaw(key) {
|
||||
return this.map[key];
|
||||
},
|
||||
this.getRaw = function Dict_getRaw(key) {
|
||||
return map[key];
|
||||
};
|
||||
|
||||
// creates new map and dereferences all Refs
|
||||
getAll: function Dict_getAll() {
|
||||
this.getAll = function Dict_getAll() {
|
||||
var all = {};
|
||||
for (var key in this.map)
|
||||
all[key] = this.get(key);
|
||||
for (var key in map) {
|
||||
var obj = this.get(key);
|
||||
all[key] = obj instanceof Dict ? obj.getAll() : obj;
|
||||
}
|
||||
return all;
|
||||
},
|
||||
};
|
||||
|
||||
set: function Dict_set(key, value) {
|
||||
this.map[key] = value;
|
||||
},
|
||||
this.set = function Dict_set(key, value) {
|
||||
map[key] = value;
|
||||
};
|
||||
|
||||
has: function Dict_has(key) {
|
||||
return key in this.map;
|
||||
},
|
||||
this.has = function Dict_has(key) {
|
||||
return key in map;
|
||||
};
|
||||
|
||||
forEach: function Dict_forEach(callback) {
|
||||
for (var key in this.map) {
|
||||
this.forEach = function Dict_forEach(callback) {
|
||||
for (var key in map) {
|
||||
callback(key, this.get(key));
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
return Dict;
|
||||
@ -299,7 +303,7 @@ var XRef = (function XRefClosure() {
|
||||
this.entries = [];
|
||||
this.xrefstms = {};
|
||||
var trailerDict = this.readXRef(startXRef);
|
||||
trailerDict.xref = this;
|
||||
trailerDict.assignXref(this);
|
||||
this.trailer = trailerDict;
|
||||
// prepare the XRef cache
|
||||
this.cache = [];
|
||||
|
@ -100,20 +100,27 @@ var WorkerMessageHandler = {
|
||||
handler.send('GetDoc', {pdfInfo: doc});
|
||||
});
|
||||
|
||||
handler.on('GetPageRequest', function wphSetupTest(data) {
|
||||
handler.on('GetPageRequest', function wphSetupGetPage(data) {
|
||||
var pageNumber = data.pageIndex + 1;
|
||||
var pdfPage = pdfModel.getPage(pageNumber);
|
||||
var page = {
|
||||
pageIndex: data.pageIndex,
|
||||
rotate: pdfPage.rotate,
|
||||
ref: pdfPage.ref,
|
||||
view: pdfPage.view,
|
||||
annotations: pdfPage.getAnnotations()
|
||||
view: pdfPage.view
|
||||
};
|
||||
handler.send('GetPage', {pageInfo: page});
|
||||
});
|
||||
|
||||
handler.on('RenderPageRequest', function wphSetupPageRequest(data) {
|
||||
handler.on('GetAnnotationsRequest', function wphSetupGetAnnotations(data) {
|
||||
var pdfPage = pdfModel.getPage(data.pageIndex + 1);
|
||||
handler.send('GetAnnotations', {
|
||||
pageIndex: data.pageIndex,
|
||||
annotations: pdfPage.getAnnotations()
|
||||
});
|
||||
});
|
||||
|
||||
handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
|
||||
var pageNum = data.pageIndex + 1;
|
||||
|
||||
|
||||
@ -170,7 +177,6 @@ var WorkerMessageHandler = {
|
||||
fonts[dep] = true;
|
||||
}
|
||||
}
|
||||
|
||||
handler.send('RenderPage', {
|
||||
pageIndex: data.pageIndex,
|
||||
operatorList: operatorList,
|
||||
|
@ -29,6 +29,7 @@
|
||||
"file": "pdfs/pdf.pdf",
|
||||
"md5": "dbdb23c939d2be09b43126c3c56060c7",
|
||||
"link": true,
|
||||
"pageLimit": 500,
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
},
|
||||
|
@ -1284,7 +1284,6 @@ window.addEventListener('load', function webViewerLoad(evt) {
|
||||
|
||||
var file = PDFJS.isFirefoxExtension ?
|
||||
window.location.toString() : params.file || kDefaultURL;
|
||||
PDFView.open(file, 0);
|
||||
|
||||
if (PDFJS.isFirefoxExtension || !window.File || !window.FileReader ||
|
||||
!window.FileList || !window.Blob) {
|
||||
@ -1316,6 +1315,7 @@ window.addEventListener('load', function webViewerLoad(evt) {
|
||||
|
||||
var sidebarScrollView = document.getElementById('sidebarScrollView');
|
||||
sidebarScrollView.addEventListener('scroll', updateThumbViewArea, true);
|
||||
PDFView.open(file, 0);
|
||||
}, true);
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user