Skip to content

Commit

Permalink
[api-minor] Add basic support for PageLayout in the API and the viewer
Browse files Browse the repository at this point in the history
Please see the specification, https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G6.2393749, and refer to the inline comments for additional details.
  • Loading branch information
Snuffleupagus committed Apr 5, 2019
1 parent 57abddc commit 7a999d1
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 2 deletions.
21 changes: 21 additions & 0 deletions src/core/obj.js
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,27 @@ class Catalog {
return pageLabels;
}

get pageLayout() {
const obj = this.catDict.get('PageLayout');
// Purposely use a non-standard default value, rather than 'SinglePage', to
// allow differentiating between `undefined` and /SinglePage since that does
// affect the Scroll mode (continuous/non-continuous) used in Adobe Reader.
let pageLayout = '';

if (isName(obj)) {
switch (obj.name) {
case 'SinglePage':
case 'OneColumn':
case 'TwoColumnLeft':
case 'TwoColumnRight':
case 'TwoPageLeft':
case 'TwoPageRight':
pageLayout = obj.name;
}
}
return shadow(this, 'pageLayout', pageLayout);
}

get pageMode() {
const obj = this.catDict.get('PageMode');
let pageMode = 'UseNone'; // Default value.
Expand Down
4 changes: 4 additions & 0 deletions src/core/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,10 @@ var WorkerMessageHandler = {
}
);

handler.on('GetPageLayout', function wphSetupGetPageLayout(data) {
return pdfManager.ensureCatalog('pageLayout');
});

handler.on('GetPageMode', function wphSetupGetPageMode(data) {
return pdfManager.ensureCatalog('pageMode');
});
Expand Down
12 changes: 12 additions & 0 deletions src/display/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,14 @@ class PDFDocumentProxy {
return this._transport.getPageLabels();
}

/**
* @return {Promise} A promise that is resolved with a {string} containing
* the page layout name.
*/
getPageLayout() {
return this._transport.getPageLayout();
}

/**
* @return {Promise} A promise that is resolved with a {string} containing
* the page mode name.
Expand Down Expand Up @@ -2214,6 +2222,10 @@ class WorkerTransport {
return this.messageHandler.sendWithPromise('GetPageLabels', null);
}

getPageLayout() {
return this.messageHandler.sendWithPromise('GetPageLayout', null);
}

getPageMode() {
return this.messageHandler.sendWithPromise('GetPageMode', null);
}
Expand Down
18 changes: 18 additions & 0 deletions test/unit/api_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,24 @@ describe('api', function() {
}).catch(done.fail);
});

it('gets default page layout', function(done) {
var loadingTask = getDocument(buildGetDocumentParams('tracemonkey.pdf'));

loadingTask.promise.then(function(pdfDocument) {
return pdfDocument.getPageLayout();
}).then(function(mode) {
expect(mode).toEqual('');

loadingTask.destroy().then(done);
}).catch(done.fail);
});
it('gets non-default page layout', function(done) {
doc.getPageLayout().then(function(mode) {
expect(mode).toEqual('SinglePage');
done();
}).catch(done.fail);
});

it('gets default page mode', function(done) {
var loadingTask = getDocument(buildGetDocumentParams('tracemonkey.pdf'));

Expand Down
32 changes: 30 additions & 2 deletions web/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,8 @@ let PDFViewerApplication = {

// Since the `setInitialView` call below depends on this being resolved,
// fetch it early to avoid delaying initial rendering of the PDF document.
const pageLayoutPromise = pdfDocument.getPageLayout().catch(
function() { /* Avoid breaking initial rendering; ignoring errors. */ });
const pageModePromise = pdfDocument.getPageMode().catch(
function() { /* Avoid breaking initial rendering; ignoring errors. */ });
const openActionDestPromise = pdfDocument.getOpenActionDestination().catch(
Expand Down Expand Up @@ -934,8 +936,8 @@ let PDFViewerApplication = {
}).catch(() => { /* Unable to read from storage; ignoring errors. */ });

Promise.all([
storePromise, pageModePromise, openActionDestPromise,
]).then(async ([values = {}, pageMode, openActionDest]) => {
storePromise, pageLayoutPromise, pageModePromise, openActionDestPromise,
]).then(async ([values = {}, pageLayout, pageMode, openActionDest]) => {
const viewOnLoad = AppOptions.get('viewOnLoad');

this._initializePdfHistory({
Expand Down Expand Up @@ -974,6 +976,9 @@ let PDFViewerApplication = {
if (pageMode && sidebarView === SidebarView.UNKNOWN) {
sidebarView = apiPageModeToSidebarView(pageMode);
}
if (pageLayout && spreadMode === SpreadMode.UNKNOWN) {
spreadMode = apiPageLayoutToSpreadMode(pageLayout);
}

this.setInitialView(hash, {
rotation, sidebarView, scrollMode, spreadMode,
Expand Down Expand Up @@ -2434,6 +2439,29 @@ function webViewerKeyDown(evt) {
}
}

/**
* Converts API PageLayout values to the format used by `PDFViewer`.
* NOTE: This is supported to the extent that the viewer implements the
* necessary Scroll/Spread modes (since SinglePage, TwoPageLeft,
* and TwoPageRight all suggests using non-continuous scrolling).
* @param {string} mode - The API PageLayout value.
* @returns {number} A value from {SpreadMode}.
*/
function apiPageLayoutToSpreadMode(layout) {
switch (layout) {
case 'SinglePage':
case 'OneColumn':
return SpreadMode.NONE;
case 'TwoColumnLeft':
case 'TwoPageLeft':
return SpreadMode.ODD;
case 'TwoColumnRight':
case 'TwoPageRight':
return SpreadMode.EVEN;
}
return SpreadMode.NONE; // Default value.
}

/**
* Converts API PageMode values to the format used by `PDFSidebar`.
* NOTE: There's also a "FullScreen" parameter which is not possible to support,
Expand Down

0 comments on commit 7a999d1

Please sign in to comment.