Bug 1182228 - Update pdf.js to version 1.1.270. r=

This commit is contained in:
Ryan VanderMeulen 2015-07-09 15:00:32 -04:00
parent 4678f16203
commit d01015c944
9 changed files with 431 additions and 183 deletions

View File

@ -1,3 +1,3 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 1.1.215
Current extension version is: 1.1.270

View File

@ -438,9 +438,23 @@ ChromeActions.prototype = {
message = getLocalizedString(strings, 'unsupported_feature');
}
PdfJsTelemetry.onFallback();
PdfjsContentUtils.displayWarning(domWindow, message, sendResponse,
PdfjsContentUtils.displayWarning(domWindow, message,
getLocalizedString(strings, 'open_with_different_viewer'),
getLocalizedString(strings, 'open_with_different_viewer', 'accessKey'));
let winmm = domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
winmm.addMessageListener('PDFJS:Child:fallbackDownload',
function fallbackDownload(msg) {
let data = msg.data;
sendResponse(data.download);
winmm.removeMessageListener('PDFJS:Child:fallbackDownload',
fallbackDownload);
});
},
updateFindControlState: function(data) {
if (!this.supportsIntegratedFind()) {

View File

@ -311,24 +311,30 @@ let PdfjsChromeUtils = {
* a pdf displayed correctly.
*/
_displayWarning: function (aMsg) {
let json = aMsg.data;
let data = aMsg.data;
let browser = aMsg.target;
let cpowCallback = aMsg.objects.callback;
let tabbrowser = browser.getTabBrowser();
let notificationBox = tabbrowser.getNotificationBox(browser);
// Flag so we don't call the response callback twice, since if the user
// clicks open with different viewer both the button callback and
// Flag so we don't send the message twice, since if the user clicks
// "open with different viewer" both the button callback and
// eventCallback will be called.
let responseSent = false;
let messageSent = false;
function sendMessage(download) {
let mm = browser.messageManager;
mm.sendAsyncMessage('PDFJS:Child:fallbackDownload',
{ download: download });
}
let buttons = [{
label: json.label,
accessKey: json.accessKey,
label: data.label,
accessKey: data.accessKey,
callback: function() {
responseSent = true;
cpowCallback(true);
messageSent = true;
sendMessage(true);
}
}];
notificationBox.appendNotification(json.message, 'pdfjs-fallback', null,
notificationBox.appendNotification(data.message, 'pdfjs-fallback', null,
notificationBox.PRIORITY_INFO_LOW,
buttons,
function eventsCallback(eventType) {
@ -339,10 +345,10 @@ let PdfjsChromeUtils = {
}
// Don't send a response again if we already responded when the button was
// clicked.
if (responseSent) {
if (messageSent) {
return;
}
cpowCallback(false);
sendMessage(false);
});
}
};

View File

@ -112,7 +112,7 @@ let PdfjsContentUtils = {
* Request the display of a notification warning in the associated window
* when the renderer isn't sure a pdf displayed correctly.
*/
displayWarning: function (aWindow, aMessage, aCallback, aLabel, accessKey) {
displayWarning: function (aWindow, aMessage, aLabel, accessKey) {
// the child's dom frame mm associated with the window.
let winmm = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
@ -122,8 +122,6 @@ let PdfjsContentUtils = {
message: aMessage,
label: aLabel,
accessKey: accessKey
}, {
callback: aCallback
});
},

View File

@ -22,8 +22,8 @@ if (typeof PDFJS === 'undefined') {
(typeof window !== 'undefined' ? window : this).PDFJS = {};
}
PDFJS.version = '1.1.215';
PDFJS.build = 'c9a7498';
PDFJS.version = '1.1.270';
PDFJS.build = 'ccfafea';
(function pdfjsWrapper() {
// Use strict in our context only - users might not want it
@ -81,6 +81,14 @@ var AnnotationType = {
LINK: 3
};
var AnnotationBorderStyleType = {
SOLID: 1,
DASHED: 2,
BEVELED: 3,
INSET: 4,
UNDERLINE: 5
};
var StreamType = {
UNKNOWN: 0,
FLATE: 1,
@ -6083,19 +6091,64 @@ var AnnotationUtils = (function AnnotationUtilsClosure() {
var width = item.rect[2] - item.rect[0];
var height = item.rect[3] - item.rect[1];
var bWidth = item.borderWidth || 0;
if (bWidth) {
width = width - 2 * bWidth;
height = height - 2 * bWidth;
cstyle.borderWidth = bWidth + 'px';
var color = item.color;
if (drawBorder && color) {
cstyle.borderStyle = 'solid';
cstyle.borderColor = Util.makeCssRgb(Math.round(color[0] * 255),
Math.round(color[1] * 255),
Math.round(color[2] * 255));
// Border
if (item.borderStyle.width > 0) {
// Border width
container.style.borderWidth = item.borderStyle.width + 'px';
if (item.borderStyle.style !== AnnotationBorderStyleType.UNDERLINE) {
// Underline styles only have a bottom border, so we do not need
// to adjust for all borders. This yields a similar result as
// Adobe Acrobat/Reader.
width = width - 2 * item.borderStyle.width;
height = height - 2 * item.borderStyle.width;
}
// Horizontal and vertical border radius
var horizontalRadius = item.borderStyle.horizontalCornerRadius;
var verticalRadius = item.borderStyle.verticalCornerRadius;
if (horizontalRadius > 0 || verticalRadius > 0) {
var radius = horizontalRadius + 'px / ' + verticalRadius + 'px';
CustomStyle.setProp('borderRadius', container, radius);
}
// Border style
switch (item.borderStyle.style) {
case AnnotationBorderStyleType.SOLID:
container.style.borderStyle = 'solid';
break;
case AnnotationBorderStyleType.DASHED:
container.style.borderStyle = 'dashed';
break;
case AnnotationBorderStyleType.BEVELED:
warn('Unimplemented border style: beveled');
break;
case AnnotationBorderStyleType.INSET:
warn('Unimplemented border style: inset');
break;
case AnnotationBorderStyleType.UNDERLINE:
container.style.borderBottomStyle = 'solid';
break;
default:
break;
}
// Border color
if (item.color) {
container.style.borderColor =
Util.makeCssRgb(Math.round(item.color[0] * 255),
Math.round(item.color[1] * 255),
Math.round(item.color[2] * 255));
} else {
// Default color is black, but that's not obvious from the spec.
container.style.borderColor = 'rgb(0,0,0)';
}
}
cstyle.width = width + 'px';
cstyle.height = height + 'px';
return container;

View File

@ -22,8 +22,8 @@ if (typeof PDFJS === 'undefined') {
(typeof window !== 'undefined' ? window : this).PDFJS = {};
}
PDFJS.version = '1.1.215';
PDFJS.build = 'c9a7498';
PDFJS.version = '1.1.270';
PDFJS.build = 'ccfafea';
(function pdfjsWrapper() {
// Use strict in our context only - users might not want it
@ -81,6 +81,14 @@ var AnnotationType = {
LINK: 3
};
var AnnotationBorderStyleType = {
SOLID: 1,
DASHED: 2,
BEVELED: 3,
INSET: 4,
UNDERLINE: 5
};
var StreamType = {
UNKNOWN: 0,
FLATE: 1,
@ -4453,45 +4461,8 @@ var Annotation = (function AnnotationClosure() {
}
}
// Some types of annotations have border style dict which has more
// info than the border array
if (dict.has('BS')) {
var borderStyle = dict.get('BS');
data.borderWidth = borderStyle.has('W') ? borderStyle.get('W') : 1;
} else {
var borderArray = dict.get('Border') || [0, 0, 1];
data.borderWidth = borderArray[2] || 0;
// TODO: implement proper support for annotations with line dash patterns.
var dashArray = borderArray[3];
if (data.borderWidth > 0 && dashArray) {
if (!isArray(dashArray)) {
// Ignore the border if dashArray is not actually an array,
// this is consistent with the behaviour in Adobe Reader.
data.borderWidth = 0;
} else {
var dashArrayLength = dashArray.length;
if (dashArrayLength > 0) {
// According to the PDF specification: the elements in a dashArray
// shall be numbers that are nonnegative and not all equal to zero.
var isInvalid = false;
var numPositive = 0;
for (var i = 0; i < dashArrayLength; i++) {
var validNumber = (+dashArray[i] >= 0);
if (!validNumber) {
isInvalid = true;
break;
} else if (dashArray[i] > 0) {
numPositive++;
}
}
if (isInvalid || numPositive === 0) {
data.borderWidth = 0;
}
}
}
}
}
this.borderStyle = data.borderStyle = new AnnotationBorderStyle();
this.setBorderStyle(dict);
this.appearance = getDefaultAppearance(dict);
data.hasAppearance = !!this.appearance;
@ -4499,6 +4470,48 @@ var Annotation = (function AnnotationClosure() {
}
Annotation.prototype = {
/**
* Set the border style (as AnnotationBorderStyle object).
*
* @public
* @memberof Annotation
* @param {Dict} borderStyle - The border style dictionary
*/
setBorderStyle: function Annotation_setBorderStyle(borderStyle) {
if (!isDict(borderStyle)) {
return;
}
if (borderStyle.has('BS')) {
var dict = borderStyle.get('BS');
var dictType;
if (!dict.has('Type') || (isName(dictType = dict.get('Type')) &&
dictType.name === 'Border')) {
this.borderStyle.setWidth(dict.get('W'));
this.borderStyle.setStyle(dict.get('S'));
this.borderStyle.setDashArray(dict.get('D'));
}
} else if (borderStyle.has('Border')) {
var array = borderStyle.get('Border');
if (isArray(array) && array.length >= 3) {
this.borderStyle.setHorizontalCornerRadius(array[0]);
this.borderStyle.setVerticalCornerRadius(array[1]);
this.borderStyle.setWidth(array[2]);
this.borderStyle.setStyle('S');
if (array.length === 4) { // Dash array available
this.borderStyle.setDashArray(array[3]);
}
}
} else {
// There are no border entries in the dictionary. According to the
// specification, we should draw a solid border of width 1 in that
// case, but Adobe Reader did not implement that part of the
// specification and instead draws no border at all, so we do the same.
// See also https://github.com/mozilla/pdf.js/issues/6179.
this.borderStyle.setWidth(0);
}
},
getData: function Annotation_getData() {
return this.data;
@ -4685,6 +4698,144 @@ var Annotation = (function AnnotationClosure() {
return Annotation;
})();
/**
* Contains all data regarding an annotation's border style.
*
* @class
*/
var AnnotationBorderStyle = (function AnnotationBorderStyleClosure() {
/**
* @constructor
* @private
*/
function AnnotationBorderStyle() {
this.width = 1;
this.style = AnnotationBorderStyleType.SOLID;
this.dashArray = [3];
this.horizontalCornerRadius = 0;
this.verticalCornerRadius = 0;
}
AnnotationBorderStyle.prototype = {
/**
* Set the width.
*
* @public
* @memberof AnnotationBorderStyle
* @param {integer} width - The width
*/
setWidth: function AnnotationBorderStyle_setWidth(width) {
if (width === (width | 0)) {
this.width = width;
}
},
/**
* Set the style.
*
* @public
* @memberof AnnotationBorderStyle
* @param {Object} style - The style object
* @see {@link shared/util.js}
*/
setStyle: function AnnotationBorderStyle_setStyle(style) {
if (!style) {
return;
}
switch (style.name) {
case 'S':
this.style = AnnotationBorderStyleType.SOLID;
break;
case 'D':
this.style = AnnotationBorderStyleType.DASHED;
break;
case 'B':
this.style = AnnotationBorderStyleType.BEVELED;
break;
case 'I':
this.style = AnnotationBorderStyleType.INSET;
break;
case 'U':
this.style = AnnotationBorderStyleType.UNDERLINE;
break;
default:
break;
}
},
/**
* Set the dash array.
*
* @public
* @memberof AnnotationBorderStyle
* @param {Array} dashArray - The dash array with at least one element
*/
setDashArray: function AnnotationBorderStyle_setDashArray(dashArray) {
// We validate the dash array, but we do not use it because CSS does not
// allow us to change spacing of dashes. For more information, visit
// http://www.w3.org/TR/css3-background/#the-border-style.
if (isArray(dashArray) && dashArray.length > 0) {
// According to the PDF specification: the elements in a dashArray
// shall be numbers that are nonnegative and not all equal to zero.
var isValid = true;
var allZeros = true;
for (var i = 0, len = dashArray.length; i < len; i++) {
var element = dashArray[i];
var validNumber = (+element >= 0);
if (!validNumber) {
isValid = false;
break;
} else if (element > 0) {
allZeros = false;
}
}
if (isValid && !allZeros) {
this.dashArray = dashArray;
} else {
this.width = 0; // Adobe behavior when the array is invalid.
}
} else if (dashArray) {
this.width = 0; // Adobe behavior when the array is invalid.
}
},
/**
* Set the horizontal corner radius (from a Border dictionary).
*
* @public
* @memberof AnnotationBorderStyle
* @param {integer} radius - The horizontal corner radius
*/
setHorizontalCornerRadius:
function AnnotationBorderStyle_setHorizontalCornerRadius(radius) {
if (radius === (radius | 0)) {
this.horizontalCornerRadius = radius;
}
},
/**
* Set the vertical corner radius (from a Border dictionary).
*
* @public
* @memberof AnnotationBorderStyle
* @param {integer} radius - The vertical corner radius
*/
setVerticalCornerRadius:
function AnnotationBorderStyle_setVerticalCornerRadius(radius) {
if (radius === (radius | 0)) {
this.verticalCornerRadius = radius;
}
}
};
return AnnotationBorderStyle;
})();
var WidgetAnnotation = (function WidgetAnnotationClosure() {
function WidgetAnnotation(params) {
@ -4785,21 +4936,9 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
return TextWidgetAnnotation;
})();
var InteractiveAnnotation = (function InteractiveAnnotationClosure() {
function InteractiveAnnotation(params) {
Annotation.call(this, params);
this.data.hasHtml = true;
}
Util.inherit(InteractiveAnnotation, Annotation, { });
return InteractiveAnnotation;
})();
var TextAnnotation = (function TextAnnotationClosure() {
function TextAnnotation(params) {
InteractiveAnnotation.call(this, params);
Annotation.call(this, params);
var dict = params.dict;
var data = this.data;
@ -4809,6 +4948,7 @@ var TextAnnotation = (function TextAnnotationClosure() {
data.annotationType = AnnotationType.TEXT;
data.content = stringToPDFString(content || '');
data.title = stringToPDFString(title || '');
data.hasHtml = true;
if (data.hasAppearance) {
data.name = 'NoIcon';
@ -4823,18 +4963,19 @@ var TextAnnotation = (function TextAnnotationClosure() {
}
}
Util.inherit(TextAnnotation, InteractiveAnnotation, { });
Util.inherit(TextAnnotation, Annotation, { });
return TextAnnotation;
})();
var LinkAnnotation = (function LinkAnnotationClosure() {
function LinkAnnotation(params) {
InteractiveAnnotation.call(this, params);
Annotation.call(this, params);
var dict = params.dict;
var data = this.data;
data.annotationType = AnnotationType.LINK;
data.hasHtml = true;
var action = dict.get('A');
if (action && isDict(action)) {
@ -4898,7 +5039,7 @@ var LinkAnnotation = (function LinkAnnotationClosure() {
return url;
}
Util.inherit(LinkAnnotation, InteractiveAnnotation, { });
Util.inherit(LinkAnnotation, Annotation, { });
return LinkAnnotation;
})();
@ -6305,7 +6446,7 @@ var ColorSpace = (function ColorSpaceClosure() {
}
break;
case 'Pattern':
var basePatternCS = xref.fetchIfRef(cs[1]) || null;
var basePatternCS = cs[1] || null;
if (basePatternCS) {
basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
}
@ -6313,7 +6454,7 @@ var ColorSpace = (function ColorSpaceClosure() {
case 'Indexed':
case 'I':
var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
var hiVal = cs[2] + 1;
var hiVal = xref.fetchIfRef(cs[2]) + 1;
var lookup = xref.fetchIfRef(cs[3]);
if (isStream(lookup)) {
lookup = lookup.getBytes();
@ -6321,7 +6462,7 @@ var ColorSpace = (function ColorSpaceClosure() {
return ['IndexedCS', baseIndexedCS, hiVal, lookup];
case 'Separation':
case 'DeviceN':
var name = cs[1];
var name = xref.fetchIfRef(cs[1]);
numComps = 1;
if (isName(name)) {
numComps = 1;
@ -10705,6 +10846,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}
// eagerly compile XForm objects
var name = args[0].name;
if (!name) {
warn('XObject must be referred to by name.');
continue;
}
if (imageCache[name] !== undefined) {
operatorList.addOp(imageCache[name].fn, imageCache[name].args);
args = null;
@ -16082,6 +16227,32 @@ var OpenTypeFileBuilder = (function OpenTypeFileBuilderClosure() {
return OpenTypeFileBuilder;
})();
// Problematic Unicode characters in the fonts that needs to be moved to avoid
// issues when they are painted on the canvas, e.g. complex-script shaping or
// control/whitespace characters. The ranges are listed in pairs: the first item
// is a code of the first problematic code, the second one is the next
// non-problematic code. The ranges must be in sorted order.
var ProblematicCharRanges = new Int32Array([
// Control characters.
0x0000, 0x0020,
0x007F, 0x00A1,
0x00AD, 0x00AE,
// Chars that is used in complex-script shaping.
0x0600, 0x0780,
0x08A0, 0x10A0,
0x1780, 0x1800,
// General punctuation chars.
0x2000, 0x2010,
0x2011, 0x2012,
0x2028, 0x2030,
0x205F, 0x2070,
0x25CC, 0x25CD,
// Chars that is used in complex-script shaping.
0xAA60, 0xAA80,
// Specials Unicode block.
0xFFF0, 0x10000
]);
/**
* 'Font' is the class the outside world should use, it encapsulate all the font
* decoding logics whatever type it is (assuming the font type is supported).
@ -16365,33 +16536,18 @@ var Font = (function FontClosure() {
* @return {boolean}
*/
function isProblematicUnicodeLocation(code) {
if (code <= 0x1F) { // Control chars
return true;
// Using binary search to find a range start.
var i = 0, j = ProblematicCharRanges.length - 1;
while (i < j) {
var c = (i + j + 1) >> 1;
if (code < ProblematicCharRanges[c]) {
j = c - 1;
} else {
i = c;
}
}
if (code >= 0x80 && code <= 0x9F) { // Control chars
return true;
}
if ((code >= 0x2000 && code <= 0x200F) || // General punctuation chars
(code >= 0x2028 && code <= 0x202F) ||
(code >= 0x2060 && code <= 0x206F)) {
return true;
}
if (code >= 0xFFF0 && code <= 0xFFFF) { // Specials Unicode block
return true;
}
switch (code) {
case 0x7F: // Control char
case 0xA0: // Non breaking space
case 0xAD: // Soft hyphen
case 0x2011: // Non breaking hyphen
case 0x205F: // Medium mathematical space
case 0x25CC: // Dotted circle (combining mark)
return true;
}
if ((code & ~0xFF) === 0x0E00) { // Thai/Lao chars (with combining mark)
return true;
}
return false;
// Even index means code in problematic range.
return !(i & 1);
}
/**
@ -17816,13 +17972,17 @@ var Font = (function FontClosure() {
var charCodeToGlyphId = [], charCode;
var toUnicode = properties.toUnicode, widths = properties.widths;
var isIdentityUnicode = toUnicode instanceof IdentityToUnicodeMap;
var skipToUnicode = (toUnicode instanceof IdentityToUnicodeMap ||
toUnicode.length === 0x10000);
// Helper function to try to skip mapping of empty glyphs.
// Note: In some cases, just relying on the glyph data doesn't work,
// hence we also use a few heuristics to fix various PDF files.
function hasGlyph(glyphId, charCode, widthCode) {
if (!missingGlyphs[glyphId]) {
return true;
}
if (!isIdentityUnicode && charCode >= 0 && toUnicode.has(charCode)) {
if (!skipToUnicode && charCode >= 0 && toUnicode.has(charCode)) {
return true;
}
if (widths && widthCode >= 0 && isNum(widths[widthCode])) {

View File

@ -69,6 +69,7 @@ var NetworkManager = (function NetworkManagerClosure() {
return array.buffer;
}
NetworkManager.prototype = {
requestRange: function NetworkManager_requestRange(begin, end, listeners) {
var args = {
@ -109,17 +110,11 @@ var NetworkManager = (function NetworkManagerClosure() {
pendingRequest.expectedStatus = 200;
}
if (args.onProgressiveData) {
// Some legacy browsers might throw an exception.
try {
xhr.responseType = 'moz-chunked-arraybuffer';
} catch(e) {}
if (xhr.responseType === 'moz-chunked-arraybuffer') {
pendingRequest.onProgressiveData = args.onProgressiveData;
pendingRequest.mozChunked = true;
} else {
xhr.responseType = 'arraybuffer';
}
var useMozChunkedLoading = !!args.onProgressiveData;
if (useMozChunkedLoading) {
xhr.responseType = 'moz-chunked-arraybuffer';
pendingRequest.onProgressiveData = args.onProgressiveData;
pendingRequest.mozChunked = true;
} else {
xhr.responseType = 'arraybuffer';
}

View File

@ -14,8 +14,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Adobe CMap resources are covered by their own copyright and license:
http://sourceforge.net/adobe/cmap/wiki/License/
Adobe CMap resources are covered by their own copyright but the same license:
Copyright 1990-2015 Adobe Systems Incorporated.
See https://github.com/adobe-type-tools/cmap-resources
-->
<html dir="ltr" mozdisallowselectionprint moznomarginboxes>
<head>

View File

@ -22,8 +22,8 @@
Promise, PDFLinkService, PDFOutlineView, PDFAttachmentView,
OverlayManager, PDFFindController, PDFFindBar, getVisibleElements,
watchScroll, PDFViewer, PDFRenderingQueue, PresentationModeState,
parseQueryString, RenderingStates, DEFAULT_SCALE, UNKNOWN_SCALE,
IGNORE_CURRENT_POSITION_ON_ZOOM: true */
parseQueryString, RenderingStates, UNKNOWN_SCALE,
DEFAULT_SCALE_VALUE, IGNORE_CURRENT_POSITION_ON_ZOOM: true */
'use strict';
@ -46,7 +46,8 @@ var mozL10n = document.mozL10n || document.webL10n;
var CSS_UNITS = 96.0 / 72.0;
var DEFAULT_SCALE = 'auto';
var DEFAULT_SCALE_VALUE = 'auto';
var DEFAULT_SCALE = 1.0;
var UNKNOWN_SCALE = 0;
var MAX_AUTO_SCALE = 1.25;
var SCROLLBAR_PADDING = 40;
@ -601,7 +602,6 @@ var Preferences = {
var FirefoxCom = (function FirefoxComClosure() {
return {
/**
@ -729,7 +729,6 @@ Preferences._readFromStorage = function (prefObj) {
* The way that the view parameters are stored depends on how PDF.js is built,
* for 'node make <flag>' the following cases exist:
* - FIREFOX or MOZCENTRAL - uses sessionStorage.
* - B2G - uses asyncStorage.
* - GENERIC or CHROME - uses localStorage, if it is available.
*/
var ViewHistory = (function ViewHistoryClosure() {
@ -768,7 +767,6 @@ var ViewHistory = (function ViewHistoryClosure() {
return new Promise(function (resolve) {
var databaseStr = JSON.stringify(this.database);
sessionStorage.setItem('pdfjsHistory', databaseStr);
resolve();
@ -777,7 +775,6 @@ var ViewHistory = (function ViewHistoryClosure() {
_readFromStorage: function ViewHistory_readFromStorage() {
return new Promise(function (resolve) {
resolve(sessionStorage.getItem('pdfjsHistory'));
});
@ -2153,6 +2150,7 @@ var CONTROLS_SELECTOR = 'pdfPresentationModeControls';
* @typedef {Object} PDFPresentationModeOptions
* @property {HTMLDivElement} container - The container for the viewer element.
* @property {HTMLDivElement} viewer - (optional) The viewer element.
* @property {PDFViewer} pdfViewer - The document viewer.
* @property {PDFThumbnailViewer} pdfThumbnailViewer - (optional) The thumbnail
* viewer.
* @property {Array} contextMenuItems - (optional) The menuitems that are added
@ -2170,6 +2168,7 @@ var PDFPresentationMode = (function PDFPresentationModeClosure() {
function PDFPresentationMode(options) {
this.container = options.container;
this.viewer = options.viewer || options.container.firstElementChild;
this.pdfViewer = options.pdfViewer;
this.pdfThumbnailViewer = options.pdfThumbnailViewer || null;
var contextMenuItems = options.contextMenuItems || null;
@ -2217,8 +2216,8 @@ var PDFPresentationMode = (function PDFPresentationModeClosure() {
}
this.args = {
page: PDFViewerApplication.page,
previousScale: PDFViewerApplication.currentScaleValue
page: this.pdfViewer.currentPageNumber,
previousScale: this.pdfViewer.currentScaleValue,
};
return true;
@ -2258,16 +2257,16 @@ var PDFPresentationMode = (function PDFPresentationModeClosure() {
if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) {
var pageSwitchDirection = (this.mouseScrollDelta > 0) ?
PageSwitchDirection.UP : PageSwitchDirection.DOWN;
var page = PDFViewerApplication.page;
var page = this.pdfViewer.currentPageNumber;
this._resetMouseScrollState();
// If we're at the first/last page, we don't need to do anything.
if ((page === 1 && pageSwitchDirection === PageSwitchDirection.UP) ||
(page === PDFViewerApplication.pagesCount &&
(page === this.pdfViewer.pagesCount &&
pageSwitchDirection === PageSwitchDirection.DOWN)) {
return;
}
PDFViewerApplication.page = (page + pageSwitchDirection);
this.pdfViewer.currentPageNumber = (page + pageSwitchDirection);
this.mouseScrollTimeStamp = currentTime;
}
},
@ -2333,8 +2332,8 @@ var PDFPresentationMode = (function PDFPresentationModeClosure() {
// Ensure that the correct page is scrolled into view when entering
// Presentation Mode, by waiting until fullscreen mode in enabled.
setTimeout(function enterPresentationModeTimeout() {
PDFViewerApplication.page = this.args.page;
PDFViewerApplication.setScale('page-fit', true);
this.pdfViewer.currentPageNumber = this.args.page;
this.pdfViewer.currentScaleValue = 'page-fit';
}.bind(this), 0);
this._addWindowListeners();
@ -2352,7 +2351,7 @@ var PDFPresentationMode = (function PDFPresentationModeClosure() {
* @private
*/
_exit: function PDFPresentationMode_exit() {
var page = PDFViewerApplication.page;
var page = this.pdfViewer.currentPageNumber;
this.container.classList.remove(ACTIVE_SELECTOR);
// Ensure that the correct page is scrolled into view when exiting
@ -2362,8 +2361,8 @@ var PDFPresentationMode = (function PDFPresentationModeClosure() {
this._removeFullscreenChangeListeners();
this._notifyStateChange();
PDFViewerApplication.setScale(this.args.previousScale, true);
PDFViewerApplication.page = page;
this.pdfViewer.currentScaleValue = this.args.previousScale;
this.pdfViewer.currentPageNumber = page;
this.args = null;
}.bind(this), 0);
@ -2395,7 +2394,7 @@ var PDFPresentationMode = (function PDFPresentationModeClosure() {
if (!isInternalLink) {
// Unless an internal link was clicked, advance one page.
evt.preventDefault();
PDFViewerApplication.page += (evt.shiftKey ? -1 : 1);
this.pdfViewer.currentPageNumber += (evt.shiftKey ? -1 : 1);
}
}
},
@ -4493,6 +4492,18 @@ var PDFViewer = (function pdfViewer() {
};
}
function isSameScale(oldScale, newScale) {
if (newScale === oldScale) {
return true;
}
if (Math.abs(newScale - oldScale) < 1e-15) {
// Prevent unnecessary re-rendering of all pages when the scale
// changes only because of limited numerical precision.
return true;
}
return false;
}
/**
* @constructs PDFViewer
* @param {PDFViewerOptions} options
@ -4556,13 +4567,20 @@ var PDFViewer = (function pdfViewer() {
this._currentPageNumber = val;
event.pageNumber = val;
this.container.dispatchEvent(event);
// Check if the caller is `PDFViewer_update`, to avoid breaking scrolling.
if (this.updateInProgress) {
return;
}
this.scrollPageIntoView(val);
},
/**
* @returns {number}
*/
get currentScale() {
return this._currentScale;
return this._currentScale !== UNKNOWN_SCALE ? this._currentScale :
DEFAULT_SCALE;
},
/**
@ -4574,7 +4592,7 @@ var PDFViewer = (function pdfViewer() {
}
if (!this.pdfDocument) {
this._currentScale = val;
this._currentScaleValue = val.toString();
this._currentScaleValue = val !== UNKNOWN_SCALE ? val.toString() : null;
return;
}
this._setScale(val, false);
@ -4678,7 +4696,7 @@ var PDFViewer = (function pdfViewer() {
// Fetch a single page so we can get a viewport that will be the default
// viewport for all pages
return firstPagePromise.then(function(pdfPage) {
var scale = this._currentScale || 1.0;
var scale = this.currentScale;
var viewport = pdfPage.getViewport(scale * CSS_UNITS);
for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
var textLayerFactory = null;
@ -4779,7 +4797,8 @@ var PDFViewer = (function pdfViewer() {
_setScaleUpdatePages: function pdfViewer_setScaleUpdatePages(
newScale, newValue, noScroll, preset) {
this._currentScaleValue = newValue;
if (newScale === this._currentScale) {
if (isSameScale(this._currentScale, newScale)) {
if (preset) {
this._setScaleDispatchEvent(newScale, newValue, true);
}
@ -4936,10 +4955,10 @@ var PDFViewer = (function pdfViewer() {
return;
}
if (scale && scale !== this.currentScale) {
if (scale && scale !== this._currentScale) {
this.currentScaleValue = scale;
} else if (this.currentScale === UNKNOWN_SCALE) {
this.currentScaleValue = DEFAULT_SCALE;
} else if (this._currentScale === UNKNOWN_SCALE) {
this.currentScaleValue = DEFAULT_SCALE_VALUE;
}
if (scale === 'page-fit' && !dest[4]) {
@ -4985,7 +5004,7 @@ var PDFViewer = (function pdfViewer() {
};
},
update: function () {
update: function PDFViewer_update() {
var visible = this._getVisiblePages();
var visiblePages = visible.views;
if (visiblePages.length === 0) {
@ -5000,7 +5019,7 @@ var PDFViewer = (function pdfViewer() {
this.renderingQueue.renderHighestPriority(visible);
var currentId = this.currentPageNumber;
var currentId = this._currentPageNumber;
var firstPage = visible.first;
for (var i = 0, ii = visiblePages.length, stillFullyVisible = false;
@ -6013,6 +6032,7 @@ var PDFViewerApplication = {
this.pdfPresentationMode = new PDFPresentationMode({
container: container,
viewer: viewer,
pdfViewer: this.pdfViewer,
pdfThumbnailViewer: this.pdfThumbnailViewer,
contextMenuItems: [
{ element: document.getElementById('contextFirstPage'),
@ -6104,10 +6124,6 @@ var PDFViewerApplication = {
this.setScale(newScale, true);
},
get currentScaleValue() {
return this.pdfViewer.currentScaleValue;
},
get pagesCount() {
return this.pdfDocument.numPages;
},
@ -6299,7 +6315,6 @@ var PDFViewerApplication = {
}
var self = this;
self.loading = true;
self.downloadComplete = false;
var passwordNeeded = function passwordNeeded(updatePassword, reason) {
@ -6316,7 +6331,6 @@ var PDFViewerApplication = {
getDocumentProgress).then(
function getDocumentCallback(pdfDocument) {
self.load(pdfDocument, scale);
self.loading = false;
},
function getDocumentError(exception) {
var message = exception && exception.message;
@ -6340,7 +6354,6 @@ var PDFViewerApplication = {
message: message
};
self.error(loadingErrorMessage, moreInfo);
self.loading = false;
}
);
@ -6710,10 +6723,10 @@ var PDFViewerApplication = {
this.page = 1;
}
if (this.pdfViewer.currentScale === UNKNOWN_SCALE) {
if (!this.pdfViewer.currentScaleValue) {
// Scale was not initialized: invalid bookmark or scale was not specified.
// Setting the default one.
this.setScale(DEFAULT_SCALE, true);
this.setScale(DEFAULT_SCALE_VALUE, true);
}
},
@ -7382,16 +7395,6 @@ window.addEventListener('pagechange', function pagechange(evt) {
Stats.add(page, pageView.stats);
}
}
// checking if the this.page was called from the updateViewarea function
if (evt.updateInProgress) {
return;
}
// Avoid scrolling the first page during loading
if (this.loading && page === 1) {
return;
}
PDFViewerApplication.pdfViewer.scrollPageIntoView(page);
}, true);
function handleMouseWheel(evt) {
@ -7400,14 +7403,31 @@ function handleMouseWheel(evt) {
evt.wheelDelta / MOUSE_WHEEL_DELTA_FACTOR;
var direction = (ticks < 0) ? 'zoomOut' : 'zoomIn';
if (PDFViewerApplication.pdfViewer.isInPresentationMode) {
var pdfViewer = PDFViewerApplication.pdfViewer;
if (pdfViewer.isInPresentationMode) {
evt.preventDefault();
PDFViewerApplication.scrollPresentationMode(ticks *
MOUSE_WHEEL_DELTA_FACTOR);
} else if (evt.ctrlKey || evt.metaKey) {
// Only zoom the pages, not the entire viewer.
evt.preventDefault();
var previousScale = pdfViewer.currentScale;
PDFViewerApplication[direction](Math.abs(ticks));
var currentScale = pdfViewer.currentScale;
if (previousScale !== currentScale) {
// After scaling the page via zoomIn/zoomOut, the position of the upper-
// left corner is restored. When the mouse wheel is used, the position
// under the cursor should be restored instead.
var scaleCorrectionFactor = currentScale / previousScale - 1;
var rect = pdfViewer.container.getBoundingClientRect();
var dx = evt.clientX - rect.left;
var dy = evt.clientY - rect.top;
pdfViewer.container.scrollLeft += dx * scaleCorrectionFactor;
pdfViewer.container.scrollTop += dy * scaleCorrectionFactor;
}
}
}
@ -7476,7 +7496,7 @@ window.addEventListener('keydown', function keydown(evt) {
// keeping it unhandled (to restore page zoom to 100%)
setTimeout(function () {
// ... and resetting the scale after browser adjusts its scale
PDFViewerApplication.setScale(DEFAULT_SCALE, true);
PDFViewerApplication.setScale(DEFAULT_SCALE_VALUE, true);
});
handled = false;
}
@ -7524,7 +7544,7 @@ window.addEventListener('keydown', function keydown(evt) {
case 33: // pg up
case 8: // backspace
if (!isViewerInPresentationMode &&
PDFViewerApplication.currentScaleValue !== 'page-fit') {
pdfViewer.currentScaleValue !== 'page-fit') {
break;
}
/* in presentation mode */
@ -7555,7 +7575,7 @@ window.addEventListener('keydown', function keydown(evt) {
case 34: // pg down
case 32: // spacebar
if (!isViewerInPresentationMode &&
PDFViewerApplication.currentScaleValue !== 'page-fit') {
pdfViewer.currentScaleValue !== 'page-fit') {
break;
}
/* falls through */
@ -7600,7 +7620,7 @@ window.addEventListener('keydown', function keydown(evt) {
switch (evt.keyCode) {
case 32: // spacebar
if (!isViewerInPresentationMode &&
PDFViewerApplication.currentScaleValue !== 'page-fit') {
pdfViewer.currentScaleValue !== 'page-fit') {
break;
}
PDFViewerApplication.page--;
@ -7669,4 +7689,3 @@ window.addEventListener('afterprint', function afterPrint(evt) {
});
})();