Skip to content

Commit

Permalink
Merge pull request #9593 from Snuffleupagus/pageSize-orientation
Browse files Browse the repository at this point in the history
Improve the pageSize entry in the document properties dialog, by also displaying page names and orientation
  • Loading branch information
timvandermeij committed Mar 25, 2018
2 parents 5c1a16b + b004308 commit a8e9f6c
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 53 deletions.
22 changes: 16 additions & 6 deletions l10n/en-US/viewer.properties
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,22 @@ document_properties_producer=PDF Producer:
document_properties_version=PDF Version:
document_properties_page_count=Page Count:
document_properties_page_size=Page Size:
# LOCALIZATION NOTE (document_properties_page_size_in_2): "{{width}}" and "{{height}}"
# will be replaced by the size of the (current) page, in inches.
document_properties_page_size_in_2={{width}} × {{height}} in
# LOCALIZATION NOTE (document_properties_page_size_mm_2): "{{width}}" and "{{height}}"
# will be replaced by the size of the (current) page, in millimeters.
document_properties_page_size_mm_2={{width}} × {{height}} mm
document_properties_page_size_unit_inches=in
document_properties_page_size_unit_millimeters=mm
document_properties_page_size_orientation_portrait=portrait
document_properties_page_size_orientation_landscape=landscape
document_properties_page_size_name_a3=A3
document_properties_page_size_name_a4=A4
document_properties_page_size_name_letter=Letter
document_properties_page_size_name_legal=Legal
# LOCALIZATION NOTE (document_properties_page_size_dimension_string):
# "{{width}}", "{{height}}", {{unit}}, and {{orientation}} will be replaced by
# the size, respectively their unit of measurement and orientation, of the (current) page.
document_properties_page_size_dimension_string={{width}} × {{height}} {{unit}} ({{orientation}})
# LOCALIZATION NOTE (document_properties_page_size_dimension_name_string):
# "{{width}}", "{{height}}", {{unit}}, {{name}}, and {{orientation}} will be replaced by
# the size, respectively their unit of measurement, name, and orientation, of the (current) page.
document_properties_page_size_dimension_name_string={{width}} × {{height}} {{unit}} ({{name}}, {{orientation}})
document_properties_close=Close

print_progress_message=Preparing document for printing…
Expand Down
22 changes: 16 additions & 6 deletions l10n/sv-SE/viewer.properties
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,22 @@ document_properties_producer=PDF-producent:
document_properties_version=PDF-version:
document_properties_page_count=Sidantal:
document_properties_page_size=Sidstorlek:
# LOCALIZATION NOTE (document_properties_page_size_in_2): "{{width}}" and "{{height}}"
# will be replaced by the size of the (current) page, in inches.
document_properties_page_size_in_2={{width}} × {{height}} tum
# LOCALIZATION NOTE (document_properties_page_size_mm_2): "{{width}}" and "{{height}}"
# will be replaced by the size of the (current) page, in millimeters.
document_properties_page_size_mm_2={{width}} × {{height}} mm
document_properties_page_size_unit_inches=tum
document_properties_page_size_unit_millimeters=mm
document_properties_page_size_orientation_portrait=stående
document_properties_page_size_orientation_landscape=liggande
document_properties_page_size_name_a3=A3
document_properties_page_size_name_a4=A4
document_properties_page_size_name_letter=Letter
document_properties_page_size_name_legal=Legal
# LOCALIZATION NOTE (document_properties_page_size_dimension_string):
# "{{width}}", "{{height}}", {{unit}}, and {{orientation}} will be replaced by
# the size, respectively their unit of measurement and orientation, of the (current) page.
document_properties_page_size_dimension_string={{width}} × {{height}} {{unit}} ({{orientation}})
# LOCALIZATION NOTE (document_properties_page_size_dimension_name_string):
# "{{width}}", "{{height}}", {{unit}}, {{name}}, and {{orientation}} will be replaced by
# the size, respectively their unit of measurement, name, and orientation, of the (current) page.
document_properties_page_size_dimension_name_string={{width}} × {{height}} {{unit}} ({{name}}, {{orientation}})
document_properties_close=Stäng

print_progress_message=Förbereder sidor för utskrift…
Expand Down
23 changes: 22 additions & 1 deletion test/unit/ui_utils_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

import {
binarySearchFirstItem, EventBus, getPageSizeInches, getPDFFileNameFromURL,
isValidRotation, waitOnEventOrTimeout, WaitOnType
isPortraitOrientation, isValidRotation, waitOnEventOrTimeout, WaitOnType
} from '../../web/ui_utils';
import { createObjectURL } from '../../src/shared/util';
import isNodeJS from '../../src/shared/is_node';
Expand Down Expand Up @@ -285,6 +285,27 @@ describe('ui_utils', function() {
});
});

describe('isPortraitOrientation', function() {
it('should be portrait orientation', function() {
expect(isPortraitOrientation({
width: 200,
height: 400,
})).toEqual(true);

expect(isPortraitOrientation({
width: 500,
height: 500,
})).toEqual(true);
});

it('should be landscape orientation', function() {
expect(isPortraitOrientation({
width: 600,
height: 300,
})).toEqual(false);
});
});

describe('waitOnEventOrTimeout', function() {
let eventBus;

Expand Down
16 changes: 6 additions & 10 deletions web/base_viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
*/

import {
CSS_UNITS, DEFAULT_SCALE, DEFAULT_SCALE_VALUE, isValidRotation,
MAX_AUTO_SCALE, NullL10n, PresentationModeState, RendererType,
SCROLLBAR_PADDING, TextLayerMode, UNKNOWN_SCALE, VERTICAL_PADDING, watchScroll
CSS_UNITS, DEFAULT_SCALE, DEFAULT_SCALE_VALUE, isPortraitOrientation,
isValidRotation, MAX_AUTO_SCALE, NullL10n, PresentationModeState,
RendererType, SCROLLBAR_PADDING, TextLayerMode, UNKNOWN_SCALE,
VERTICAL_PADDING, watchScroll
} from './ui_utils';
import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue';
import { AnnotationLayerBuilder } from './annotation_layer_builder';
Expand Down Expand Up @@ -94,10 +95,6 @@ function isSameScale(oldScale, newScale) {
return false;
}

function isPortraitOrientation(size) {
return size.width <= size.height;
}

/**
* Simple viewer control to display PDF content/pages.
* @implements {IRenderableView}
Expand Down Expand Up @@ -578,11 +575,10 @@ class BaseViewer {
scale = Math.min(pageWidthScale, pageHeightScale);
break;
case 'auto':
let isLandscape = (currentPage.width > currentPage.height);
// For pages in landscape mode, fit the page height to the viewer
// *unless* the page would thus become too wide to fit horizontally.
let horizontalScale = isLandscape ?
Math.min(pageHeightScale, pageWidthScale) : pageWidthScale;
let horizontalScale = isPortraitOrientation(currentPage) ?
pageWidthScale : Math.min(pageHeightScale, pageWidthScale);
scale = Math.min(MAX_AUTO_SCALE, horizontalScale);
break;
default:
Expand Down
4 changes: 4 additions & 0 deletions web/firefoxcom.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ class MozL10n {
this.mozL10n = mozL10n;
}

getLanguage() {
return Promise.resolve(this.mozL10n.getLanguage());
}

getDirection() {
return Promise.resolve(this.mozL10n.getDirection());
}
Expand Down
6 changes: 6 additions & 0 deletions web/genericl10n.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ class GenericL10n {
});
}

getLanguage() {
return this._ready.then((l10n) => {
return l10n.getLanguage();
});
}

getDirection() {
return this._ready.then((l10n) => {
return l10n.getDirection();
Expand Down
5 changes: 5 additions & 0 deletions web/interfaces.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ class IPDFAnnotationLayerFactory {
* @interface
*/
class IL10n {
/**
* @returns {Promise<string>} - Resolves to the current locale.
*/
getLanguage() {}

/**
* @returns {Promise<string>} - Resolves to 'rtl' or 'ltr'.
*/
Expand Down
140 changes: 117 additions & 23 deletions web/pdf_document_properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,34 @@
*/

import {
cloneObj, getPageSizeInches, getPDFFileNameFromURL, NullL10n
cloneObj, getPageSizeInches, getPDFFileNameFromURL, isPortraitOrientation,
NullL10n
} from './ui_utils';
import { createPromiseCapability } from 'pdfjs-lib';

const DEFAULT_FIELD_CONTENT = '-';

// See https://en.wikibooks.org/wiki/Lentis/Conversion_to_the_Metric_Standard_in_the_United_States
const NON_METRIC_LOCALES = ['en-us', 'en-lr', 'my'];

// Should use the format: `width x height`, in portrait orientation.
// See https://en.wikipedia.org/wiki/Paper_size
const US_PAGE_NAMES = {
'8.5x11': 'Letter',
'8.5x14': 'Legal',
};
const METRIC_PAGE_NAMES = {
'297x420': 'A3',
'210x297': 'A4',
};

function getPageName(size, isPortrait, pageNames) {
const width = (isPortrait ? size.width : size.height);
const height = (isPortrait ? size.height : size.width);

return pageNames[`${width}x${height}`];
}

/**
* @typedef {Object} PDFDocumentPropertiesOptions
* @property {string} overlayName - Name/identifier for the overlay.
Expand Down Expand Up @@ -55,7 +77,15 @@ class PDFDocumentProperties {
eventBus.on('pagechanging', (evt) => {
this._currentPageNumber = evt.pageNumber;
});
eventBus.on('rotationchanging', (evt) => {
this._pagesRotation = evt.pagesRotation;
});
}

this._isNonMetricLocale = true; // The default viewer locale is 'en-us'.
l10n.getLanguage().then((locale) => {
this._isNonMetricLocale = NON_METRIC_LOCALES.includes(locale);
});
}

/**
Expand All @@ -74,11 +104,13 @@ class PDFDocumentProperties {
Promise.all([this.overlayManager.open(this.overlayName),
this._dataAvailableCapability.promise]).then(() => {
const currentPageNumber = this._currentPageNumber;
const pagesRotation = this._pagesRotation;

// If the document properties were previously fetched (for this PDF file),
// just update the dialog immediately to avoid redundant lookups.
if (this.fieldData &&
currentPageNumber === this.fieldData['_currentPageNumber']) {
currentPageNumber === this.fieldData['_currentPageNumber'] &&
pagesRotation === this.fieldData['_pagesRotation']) {
this._updateUI();
return;
}
Expand All @@ -94,11 +126,12 @@ class PDFDocumentProperties {
this._parseDate(info.CreationDate),
this._parseDate(info.ModDate),
this.pdfDocument.getPage(currentPageNumber).then((pdfPage) => {
return this._parsePageSize(getPageSizeInches(pdfPage));
return this._parsePageSize(getPageSizeInches(pdfPage),
pagesRotation);
}),
]);
}).then(([info, metadata, fileName, fileSize, creationDate, modDate,
pageSizes]) => {
pageSize]) => {
freezeFieldData({
'fileName': fileName,
'fileSize': fileSize,
Expand All @@ -112,9 +145,9 @@ class PDFDocumentProperties {
'producer': info.Producer,
'version': info.PDFFormatVersion,
'pageCount': this.pdfDocument.numPages,
'pageSizeInch': pageSizes.inch,
'pageSizeMM': pageSizes.mm,
'pageSize': pageSize,
'_currentPageNumber': currentPageNumber,
'_pagesRotation': pagesRotation,
});
this._updateUI();

Expand Down Expand Up @@ -191,6 +224,7 @@ class PDFDocumentProperties {
delete this.fieldData;
this._dataAvailableCapability = createPromiseCapability();
this._currentPageNumber = 1;
this._pagesRotation = 0;
}

/**
Expand Down Expand Up @@ -240,27 +274,87 @@ class PDFDocumentProperties {
/**
* @private
*/
_parsePageSize(pageSizeInches) {
_parsePageSize(pageSizeInches, pagesRotation) {
if (!pageSizeInches) {
return Promise.resolve({ inch: undefined, mm: undefined, });
return Promise.resolve(undefined);
}
const { width, height, } = pageSizeInches;
// Take the viewer rotation into account as well; compare with Adobe Reader.
if (pagesRotation % 180 !== 0) {
pageSizeInches = {
width: pageSizeInches.height,
height: pageSizeInches.width,
};
}
const isPortrait = isPortraitOrientation(pageSizeInches);

return Promise.all([
this.l10n.get('document_properties_page_size_in_2', {
width: (Math.round(width * 100) / 100).toLocaleString(),
height: (Math.round(height * 100) / 100).toLocaleString(),
}, '{{width}} × {{height}} in'),
// 1in = 25.4mm; no need to round to 2 decimals for millimeters.
this.l10n.get('document_properties_page_size_mm_2', {
width: (Math.round(width * 25.4 * 10) / 10).toLocaleString(),
height: (Math.round(height * 25.4 * 10) / 10).toLocaleString(),
}, '{{width}} × {{height}} mm'),
]).then((sizes) => {
return {
inch: sizes[0],
mm: sizes[1],
let sizeInches = {
width: Math.round(pageSizeInches.width * 100) / 100,
height: Math.round(pageSizeInches.height * 100) / 100,
};
// 1in == 25.4mm; no need to round to 2 decimals for millimeters.
let sizeMillimeters = {
width: Math.round(pageSizeInches.width * 25.4 * 10) / 10,
height: Math.round(pageSizeInches.height * 25.4 * 10) / 10,
};

let pageName = null;
let name = getPageName(sizeInches, isPortrait, US_PAGE_NAMES) ||
getPageName(sizeMillimeters, isPortrait, METRIC_PAGE_NAMES);

if (!name && !(Number.isInteger(sizeMillimeters.width) &&
Number.isInteger(sizeMillimeters.height))) {
// Attempt to improve the page name detection by falling back to fuzzy
// matching of the metric dimensions, to account for e.g. rounding errors
// and/or PDF files that define the page sizes in an imprecise manner.
const exactMillimeters = {
width: pageSizeInches.width * 25.4,
height: pageSizeInches.height * 25.4,
};
const intMillimeters = {
width: Math.round(sizeMillimeters.width),
height: Math.round(sizeMillimeters.height),
};

// Try to avoid false positives, by only considering "small" differences.
if (Math.abs(exactMillimeters.width - intMillimeters.width) < 0.1 &&
Math.abs(exactMillimeters.height - intMillimeters.height) < 0.1) {

name = getPageName(intMillimeters, isPortrait, METRIC_PAGE_NAMES);
if (name) {
// Update *both* sizes, computed above, to ensure that the displayed
// dimensions always correspond to the detected page name.
sizeInches = {
width: Math.round(intMillimeters.width / 25.4 * 100) / 100,
height: Math.round(intMillimeters.height / 25.4 * 100) / 100,
};
sizeMillimeters = intMillimeters;
}
}
}
if (name) {
pageName = this.l10n.get('document_properties_page_size_name_' +
name.toLowerCase(), null, name);
}

return Promise.all([
(this._isNonMetricLocale ? sizeInches : sizeMillimeters),
this.l10n.get('document_properties_page_size_unit_' +
(this._isNonMetricLocale ? 'inches' : 'millimeters'), null,
this._isNonMetricLocale ? 'in' : 'mm'),
pageName,
this.l10n.get('document_properties_page_size_orientation_' +
(isPortrait ? 'portrait' : 'landscape'), null,
isPortrait ? 'portrait' : 'landscape'),
]).then(([{ width, height, }, unit, name, orientation]) => {
return this.l10n.get('document_properties_page_size_dimension_' +
(name ? 'name_' : '') + 'string', {
width: width.toLocaleString(),
height: height.toLocaleString(),
unit,
name,
orientation,
}, '{{width}} × {{height}} {{unit}} (' +
(name ? '{{name}}, ' : '') + '{{orientation}})');
});
}

Expand Down
Loading

0 comments on commit a8e9f6c

Please sign in to comment.