Skip to content

Commit

Permalink
Use the Linearization dictionary, if it exists, when fetching the f…
Browse files Browse the repository at this point in the history
…irst Page

Since PDF.js already supports range requests and streaming, not to mention chunked rendering, attempting to use the `Linearization` dictionary in `PDFDocument.getPage` probably isn't going to improve performance in any noticeable way.
Nonetheless, when `Linearization` data is available, it will allow looking up the first Page *directly* without having to descend into the `Pages` tree to find the correct object.
  • Loading branch information
Snuffleupagus committed Jul 28, 2018
1 parent fbb25ff commit ec3728b
Showing 1 changed file with 43 additions and 18 deletions.
61 changes: 43 additions & 18 deletions src/core/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
* limitations under the License.
*/

import { Catalog, ObjectLoader, XRef } from './obj';
import { Dict, isDict, isName, isStream } from './primitives';
import {
getInheritableProperty, info, isArrayBuffer, isNum, isSpace, isString,
MissingDataException, OPS, shadow, stringToBytes, stringToPDFString, Util
assert, FormatError, getInheritableProperty, info, isArrayBuffer, isNum,
isSpace, isString, MissingDataException, OPS, shadow, stringToBytes,
stringToPDFString, Util
} from '../shared/util';
import { Catalog, ObjectLoader, XRef } from './obj';
import { Dict, isDict, isName, isStream, Ref } from './primitives';
import { NullStream, Stream, StreamsSequenceStream } from './stream';
import { AnnotationFactory } from './annotation';
import { calculateMD5 } from './crypto';
Expand Down Expand Up @@ -586,25 +587,49 @@ var PDFDocument = (function PDFDocumentClosure() {
return shadow(this, 'fingerprint', fileID);
},

_getLinearizationPage(pageIndex) {
const { catalog, linearization, } = this;
assert(linearization && linearization.pageFirst === pageIndex);

const ref = new Ref(linearization.objectNumberFirst, 0);
return this.xref.fetchAsync(ref).then((obj) => {
// Ensure that the object that was found is actually a Page dictionary.
if (isDict(obj, 'Page') ||
(isDict(obj) && !obj.has('Type') && obj.has('Contents'))) {
if (ref && !catalog.pageKidsCountCache.has(ref)) {
catalog.pageKidsCountCache.put(ref, 1); // Cache the Page reference.
}
return [obj, ref];
}
throw new FormatError('The Linearization dictionary doesn\'t point ' +
'to a valid Page dictionary.');
}).catch((reason) => {
info(reason);
return catalog.getPageDict(pageIndex);
});
},

getPage(pageIndex) {
if (this._pagePromises[pageIndex] !== undefined) {
return this._pagePromises[pageIndex];
}
const catalog = this.catalog;

return this._pagePromises[pageIndex] =
catalog.getPageDict(pageIndex).then(([pageDict, ref]) => {
return new Page({
pdfManager: this.pdfManager,
xref: this.xref,
pageIndex,
pageDict,
ref,
fontCache: catalog.fontCache,
builtInCMapCache: catalog.builtInCMapCache,
pdfFunctionFactory: this.pdfFunctionFactory,
});
const { catalog, linearization, } = this;

const promise = (linearization && linearization.pageFirst === pageIndex) ?
this._getLinearizationPage(pageIndex) : catalog.getPageDict(pageIndex);

return this._pagePromises[pageIndex] = promise.then(([pageDict, ref]) => {
return new Page({
pdfManager: this.pdfManager,
xref: this.xref,
pageIndex,
pageDict,
ref,
fontCache: catalog.fontCache,
builtInCMapCache: catalog.builtInCMapCache,
pdfFunctionFactory: this.pdfFunctionFactory,
});
});
},

cleanup: function PDFDocument_cleanup() {
Expand Down

0 comments on commit ec3728b

Please sign in to comment.