Merge pull request #9479 from Snuffleupagus/refactor-viewer-options

[api-major] Refactor viewer components initialization to reduce their dependency on the global `PDFJS` object
This commit is contained in:
Tim van der Meij 2018-02-14 22:47:33 +01:00 committed by GitHub
commit 538dda1096
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 256 additions and 274 deletions

View File

@ -21,8 +21,8 @@ if (typeof PDFJS === 'undefined' || !PDFJS.PDFViewer || !PDFJS.getDocument) {
' `gulp dist-install`'); ' `gulp dist-install`');
} }
PDFJS.useOnlyCssZoom = true; var USE_ONLY_CSS_ZOOM = true;
PDFJS.disableTextLayer = true; var TEXT_LAYER_MODE = 0; // DISABLE
PDFJS.maxImageSize = 1024 * 1024; PDFJS.maxImageSize = 1024 * 1024;
PDFJS.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js'; PDFJS.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js';
PDFJS.cMapUrl = '../../node_modules/pdfjs-dist/cmaps/'; PDFJS.cMapUrl = '../../node_modules/pdfjs-dist/cmaps/';
@ -298,6 +298,8 @@ var PDFViewerApplication = {
container: container, container: container,
linkService: linkService, linkService: linkService,
l10n: this.l10n, l10n: this.l10n,
useOnlyCssZoom: USE_ONLY_CSS_ZOOM,
textLayerMode: TEXT_LAYER_MODE,
}); });
this.pdfViewer = pdfViewer; this.pdfViewer = pdfViewer;
linkService.setViewer(pdfViewer); linkService.setViewer(pdfViewer);

View File

@ -70,11 +70,16 @@
"type": "boolean", "type": "boolean",
"default": false "default": false
}, },
"disableTextLayer": { "textLayerMode": {
"title": "Disable text selection layer", "title": "Text layer mode",
"description": "Whether to disable the text selection layer.", "description": "Controls if the text layer is enabled, and the selection mode that is used.\n 0 = Disabled.\n 1 = Enabled.\n 2 = (Experimental) Enabled, with enhanced text selection.",
"type": "boolean", "type": "integer",
"default": false "enum": [
0,
1,
2
],
"default": 1
}, },
"useOnlyCssZoom": { "useOnlyCssZoom": {
"type": "boolean", "type": "boolean",
@ -107,10 +112,6 @@
"description": "Whether to prevent the extension from reporting the extension and browser version to the extension developers.", "description": "Whether to prevent the extension from reporting the extension and browser version to the extension developers.",
"default": false "default": false
}, },
"enhanceTextSelection": {
"type": "boolean",
"default": false
},
"renderer": { "renderer": {
"type": "string", "type": "string",
"enum": [ "enum": [

View File

@ -14,8 +14,7 @@
*/ */
import { import {
addLinkAttributes, DOMSVGFactory, getDefaultSetting, getFilenameFromUrl, addLinkAttributes, DOMSVGFactory, getFilenameFromUrl, LinkTarget
LinkTarget
} from './dom_utils'; } from './dom_utils';
import { import {
AnnotationBorderStyleType, AnnotationType, stringToPDFString, unreachable, AnnotationBorderStyleType, AnnotationType, stringToPDFString, unreachable,
@ -30,7 +29,8 @@ import {
* @property {PageViewport} viewport * @property {PageViewport} viewport
* @property {IPDFLinkService} linkService * @property {IPDFLinkService} linkService
* @property {DownloadManager} downloadManager * @property {DownloadManager} downloadManager
* @property {string} imageResourcesPath * @property {string} imageResourcesPath - (optional) Path for image resources,
* mainly for annotation icons. Include trailing slash.
* @property {boolean} renderInteractiveForms * @property {boolean} renderInteractiveForms
* @property {Object} svgFactory * @property {Object} svgFactory
*/ */
@ -281,17 +281,21 @@ class LinkAnnotationElement extends AnnotationElement {
render() { render() {
this.container.className = 'linkAnnotation'; this.container.className = 'linkAnnotation';
let { data, linkService, } = this;
let link = document.createElement('a'); let link = document.createElement('a');
addLinkAttributes(link, { addLinkAttributes(link, {
url: this.data.url, url: data.url,
target: (this.data.newWindow ? LinkTarget.BLANK : undefined), target: (data.newWindow ?
LinkTarget.BLANK : linkService.externalLinkTarget),
rel: linkService.externalLinkRel,
}); });
if (!this.data.url) { if (!data.url) {
if (this.data.action) { if (data.action) {
this._bindNamedAction(link, this.data.action); this._bindNamedAction(link, data.action);
} else { } else {
this._bindLink(link, this.data.dest); this._bindLink(link, data.dest);
} }
} }
@ -1183,7 +1187,9 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
* @property {Array} annotations * @property {Array} annotations
* @property {PDFPage} page * @property {PDFPage} page
* @property {IPDFLinkService} linkService * @property {IPDFLinkService} linkService
* @property {string} imageResourcesPath * @property {DownloadManager} downloadManager
* @property {string} imageResourcesPath - (optional) Path for image resources,
* mainly for annotation icons. Include trailing slash.
* @property {boolean} renderInteractiveForms * @property {boolean} renderInteractiveForms
*/ */
@ -1208,8 +1214,7 @@ class AnnotationLayer {
viewport: parameters.viewport, viewport: parameters.viewport,
linkService: parameters.linkService, linkService: parameters.linkService,
downloadManager: parameters.downloadManager, downloadManager: parameters.downloadManager,
imageResourcesPath: parameters.imageResourcesPath || imageResourcesPath: parameters.imageResourcesPath || '',
getDefaultSetting('imageResourcesPath'),
renderInteractiveForms: parameters.renderInteractiveForms || false, renderInteractiveForms: parameters.renderInteractiveForms || false,
svgFactory: new DOMSVGFactory(), svgFactory: new DOMSVGFactory(),
}); });

View File

@ -707,6 +707,8 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
* calling of PDFPage.getViewport method. * calling of PDFPage.getViewport method.
* @property {string} intent - Rendering intent, can be 'display' or 'print' * @property {string} intent - Rendering intent, can be 'display' or 'print'
* (default value is 'display'). * (default value is 'display').
* @property {boolean} enableWebGL - (optional) Enables WebGL accelerated
* rendering for some operations. The default value is `false`.
* @property {boolean} renderInteractiveForms - (optional) Whether or not * @property {boolean} renderInteractiveForms - (optional) Whether or not
* interactive form elements are rendered in the display * interactive form elements are rendered in the display
* layer. If so, we do not render them on canvas as well. * layer. If so, we do not render them on canvas as well.
@ -743,7 +745,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
this.pageIndex = pageIndex; this.pageIndex = pageIndex;
this.pageInfo = pageInfo; this.pageInfo = pageInfo;
this.transport = transport; this.transport = transport;
this._stats = (getDefaultSetting('enableStats') ? this._stats = (getDefaultSetting('pdfBug') ?
new StatTimer() : DummyStatTimer); new StatTimer() : DummyStatTimer);
this.commonObjs = transport.commonObjs; this.commonObjs = transport.commonObjs;
this.objs = new PDFObjects(); this.objs = new PDFObjects();
@ -828,9 +830,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
var renderingIntent = (params.intent === 'print' ? 'print' : 'display'); var renderingIntent = (params.intent === 'print' ? 'print' : 'display');
var canvasFactory = params.canvasFactory || new DOMCanvasFactory(); var canvasFactory = params.canvasFactory || new DOMCanvasFactory();
let webGLContext = new WebGLContext({ let webGLContext = new WebGLContext({
// TODO: When moving this parameter from `PDFJS` to {RenderParameters}, enable: params.enableWebGL,
// change its name to `enableWebGL` instead.
enable: !getDefaultSetting('disableWebGL'),
}); });
if (!this.intentStates[renderingIntent]) { if (!this.intentStates[renderingIntent]) {

View File

@ -274,7 +274,7 @@ var RenderingCancelledException = (function RenderingCancelledException() {
return RenderingCancelledException; return RenderingCancelledException;
})(); })();
var LinkTarget = { const LinkTarget = {
NONE: 0, // Default value. NONE: 0, // Default value.
SELF: 1, SELF: 1,
BLANK: 2, BLANK: 2,
@ -282,7 +282,7 @@ var LinkTarget = {
TOP: 4, TOP: 4,
}; };
var LinkTargetStringMap = [ const LinkTargetStringMap = [
'', '',
'_self', '_self',
'_blank', '_blank',
@ -294,8 +294,10 @@ var LinkTargetStringMap = [
* @typedef ExternalLinkParameters * @typedef ExternalLinkParameters
* @typedef {Object} ExternalLinkParameters * @typedef {Object} ExternalLinkParameters
* @property {string} url - An absolute URL. * @property {string} url - An absolute URL.
* @property {LinkTarget} target - The link target. * @property {LinkTarget} target - (optional) The link target.
* @property {string} rel - The link relationship. * The default value is `LinkTarget.NONE`.
* @property {string} rel - (optional) The link relationship.
* The default value is `DEFAULT_LINK_REL`.
*/ */
/** /**
@ -303,22 +305,16 @@ var LinkTargetStringMap = [
* @param {HTMLLinkElement} link - The link element. * @param {HTMLLinkElement} link - The link element.
* @param {ExternalLinkParameters} params * @param {ExternalLinkParameters} params
*/ */
function addLinkAttributes(link, params) { function addLinkAttributes(link, { url, target, rel, } = {}) {
var url = params && params.url;
link.href = link.title = (url ? removeNullCharacters(url) : ''); link.href = link.title = (url ? removeNullCharacters(url) : '');
if (url) { if (url) {
var target = params.target; const LinkTargetValues = Object.values(LinkTarget);
if (typeof target === 'undefined') { let targetIndex =
target = getDefaultSetting('externalLinkTarget'); LinkTargetValues.includes(target) ? target : LinkTarget.NONE;
} link.target = LinkTargetStringMap[targetIndex];
link.target = LinkTargetStringMap[target];
var rel = params.rel; link.rel = (typeof rel === 'string' ? rel : DEFAULT_LINK_REL);
if (typeof rel === 'undefined') {
rel = getDefaultSetting('externalLinkRel');
}
link.rel = rel;
} }
} }
@ -349,8 +345,6 @@ function getDefaultSetting(id) {
return globalSettings ? globalSettings.disableFontFace : false; return globalSettings ? globalSettings.disableFontFace : false;
case 'disableCreateObjectURL': case 'disableCreateObjectURL':
return globalSettings ? globalSettings.disableCreateObjectURL : false; return globalSettings ? globalSettings.disableCreateObjectURL : false;
case 'disableWebGL':
return globalSettings ? globalSettings.disableWebGL : true;
case 'cMapUrl': case 'cMapUrl':
return globalSettings ? globalSettings.cMapUrl : null; return globalSettings ? globalSettings.cMapUrl : null;
case 'cMapPacked': case 'cMapPacked':
@ -363,49 +357,13 @@ function getDefaultSetting(id) {
return globalSettings ? globalSettings.workerSrc : null; return globalSettings ? globalSettings.workerSrc : null;
case 'maxImageSize': case 'maxImageSize':
return globalSettings ? globalSettings.maxImageSize : -1; return globalSettings ? globalSettings.maxImageSize : -1;
case 'imageResourcesPath':
return globalSettings ? globalSettings.imageResourcesPath : '';
case 'isEvalSupported': case 'isEvalSupported':
return globalSettings ? globalSettings.isEvalSupported : true; return globalSettings ? globalSettings.isEvalSupported : true;
case 'externalLinkTarget':
if (!globalSettings) {
return LinkTarget.NONE;
}
switch (globalSettings.externalLinkTarget) {
case LinkTarget.NONE:
case LinkTarget.SELF:
case LinkTarget.BLANK:
case LinkTarget.PARENT:
case LinkTarget.TOP:
return globalSettings.externalLinkTarget;
}
warn('PDFJS.externalLinkTarget is invalid: ' +
globalSettings.externalLinkTarget);
// Reset the external link target, to suppress further warnings.
globalSettings.externalLinkTarget = LinkTarget.NONE;
return LinkTarget.NONE;
case 'externalLinkRel':
return globalSettings ? globalSettings.externalLinkRel : DEFAULT_LINK_REL;
case 'enableStats':
return !!(globalSettings && globalSettings.enableStats);
default: default:
throw new Error('Unknown default setting: ' + id); throw new Error('Unknown default setting: ' + id);
} }
} }
function isExternalLinkTargetSet() {
var externalLinkTarget = getDefaultSetting('externalLinkTarget');
switch (externalLinkTarget) {
case LinkTarget.NONE:
return false;
case LinkTarget.SELF:
case LinkTarget.BLANK:
case LinkTarget.PARENT:
case LinkTarget.TOP:
return true;
}
}
class StatTimer { class StatTimer {
constructor(enable = true) { constructor(enable = true) {
this.enabled = !!enable; this.enabled = !!enable;
@ -483,7 +441,6 @@ class DummyStatTimer {
export { export {
RenderingCancelledException, RenderingCancelledException,
addLinkAttributes, addLinkAttributes,
isExternalLinkTargetSet,
getFilenameFromUrl, getFilenameFromUrl,
LinkTarget, LinkTarget,
getDefaultSetting, getDefaultSetting,

View File

@ -13,10 +13,6 @@
* limitations under the License. * limitations under the License.
*/ */
import {
addLinkAttributes, DEFAULT_LINK_REL, getFilenameFromUrl,
isExternalLinkTargetSet, isValidUrl, LinkTarget
} from './dom_utils';
import { import {
createBlob, createObjectURL, createPromiseCapability, getVerbosityLevel, createBlob, createObjectURL, createPromiseCapability, getVerbosityLevel,
InvalidPDFException, isLittleEndian, MissingPDFException, OPS, PageViewport, InvalidPDFException, isLittleEndian, MissingPDFException, OPS, PageViewport,
@ -24,6 +20,7 @@ import {
shadow, UnexpectedResponseException, UnknownErrorException, shadow, UnexpectedResponseException, UnknownErrorException,
UNSUPPORTED_FEATURES, Util, VERBOSITY_LEVELS UNSUPPORTED_FEATURES, Util, VERBOSITY_LEVELS
} from '../shared/util'; } from '../shared/util';
import { DEFAULT_LINK_REL, getFilenameFromUrl, LinkTarget } from './dom_utils';
import { import {
getDocument, LoopbackPort, PDFDataRangeTransport, PDFWorker getDocument, LoopbackPort, PDFDataRangeTransport, PDFWorker
} from './api'; } from './api';
@ -42,11 +39,6 @@ if (!globalScope.PDFJS) {
} }
var PDFJS = globalScope.PDFJS; var PDFJS = globalScope.PDFJS;
if (typeof PDFJSDev !== 'undefined') {
PDFJS.version = PDFJSDev.eval('BUNDLE_VERSION');
PDFJS.build = PDFJSDev.eval('BUNDLE_BUILD');
}
PDFJS.pdfBug = false; PDFJS.pdfBug = false;
if (PDFJS.verbosity !== undefined) { if (PDFJS.verbosity !== undefined) {
@ -67,7 +59,6 @@ Object.defineProperty(PDFJS, 'verbosity', {
PDFJS.VERBOSITY_LEVELS = VERBOSITY_LEVELS; PDFJS.VERBOSITY_LEVELS = VERBOSITY_LEVELS;
PDFJS.OPS = OPS; PDFJS.OPS = OPS;
PDFJS.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES; PDFJS.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
PDFJS.isValidUrl = isValidUrl;
PDFJS.shadow = shadow; PDFJS.shadow = shadow;
PDFJS.createBlob = createBlob; PDFJS.createBlob = createBlob;
PDFJS.createObjectURL = function PDFJS_createObjectURL(data, contentType) { PDFJS.createObjectURL = function PDFJS_createObjectURL(data, contentType) {
@ -120,14 +111,6 @@ PDFJS.cMapPacked = PDFJS.cMapPacked === undefined ? false : PDFJS.cMapPacked;
PDFJS.disableFontFace = (PDFJS.disableFontFace === undefined ? PDFJS.disableFontFace = (PDFJS.disableFontFace === undefined ?
false : PDFJS.disableFontFace); false : PDFJS.disableFontFace);
/**
* Path for image resources, mainly for annotation icons. Include trailing
* slash.
* @var {string}
*/
PDFJS.imageResourcesPath = (PDFJS.imageResourcesPath === undefined ?
'' : PDFJS.imageResourcesPath);
/** /**
* Path and filename of the worker file. Required when the worker is enabled * Path and filename of the worker file. Required when the worker is enabled
* in development mode. If unspecified in the production build, the worker * in development mode. If unspecified in the production build, the worker
@ -192,16 +175,9 @@ PDFJS.postMessageTransfers = (PDFJS.postMessageTransfers === undefined ?
PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ? PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ?
false : PDFJS.disableCreateObjectURL); false : PDFJS.disableCreateObjectURL);
/**
* Disables WebGL usage.
* @var {boolean}
*/
PDFJS.disableWebGL = (PDFJS.disableWebGL === undefined ?
true : PDFJS.disableWebGL);
/** /**
* Specifies the |target| attribute for external links. * Specifies the |target| attribute for external links.
* The constants from PDFJS.LinkTarget should be used: * The constants from {LinkTarget} should be used:
* - NONE [default] * - NONE [default]
* - SELF * - SELF
* - BLANK * - BLANK
@ -233,10 +209,7 @@ PDFJS.LoopbackPort = LoopbackPort;
PDFJS.PDFDataRangeTransport = PDFDataRangeTransport; PDFJS.PDFDataRangeTransport = PDFDataRangeTransport;
PDFJS.PDFWorker = PDFWorker; PDFJS.PDFWorker = PDFWorker;
PDFJS.LinkTarget = LinkTarget;
PDFJS.addLinkAttributes = addLinkAttributes;
PDFJS.getFilenameFromUrl = getFilenameFromUrl; PDFJS.getFilenameFromUrl = getFilenameFromUrl;
PDFJS.isExternalLinkTargetSet = isExternalLinkTargetSet;
PDFJS.AnnotationLayer = AnnotationLayer; PDFJS.AnnotationLayer = AnnotationLayer;

View File

@ -91,4 +91,5 @@ exports.createBlob = pdfjsSharedUtil.createBlob;
exports.RenderingCancelledException = exports.RenderingCancelledException =
pdfjsDisplayDOMUtils.RenderingCancelledException; pdfjsDisplayDOMUtils.RenderingCancelledException;
exports.getFilenameFromUrl = pdfjsDisplayDOMUtils.getFilenameFromUrl; exports.getFilenameFromUrl = pdfjsDisplayDOMUtils.getFilenameFromUrl;
exports.LinkTarget = pdfjsDisplayDOMUtils.LinkTarget;
exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes; exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes;

View File

@ -26,12 +26,10 @@ if ((typeof PDFJSDev === 'undefined' ||
// users - https://github.com/mozilla/pdf.js/issues/9397 // users - https://github.com/mozilla/pdf.js/issues/9397
if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('CHROME')) { if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('CHROME')) {
var globalScope = require('./global_scope'); const globalScope = require('./global_scope');
const isNodeJS = require('./is_node'); const isNodeJS = require('./is_node');
var userAgent = (typeof navigator !== 'undefined' && navigator.userAgent) || ''; var userAgent = (typeof navigator !== 'undefined' && navigator.userAgent) || '';
var isAndroid = /Android/.test(userAgent);
var isIOSChrome = userAgent.indexOf('CriOS') >= 0; var isIOSChrome = userAgent.indexOf('CriOS') >= 0;
var isIE = userAgent.indexOf('Trident') >= 0; var isIE = userAgent.indexOf('Trident') >= 0;
var isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent); var isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent);
@ -80,18 +78,6 @@ PDFJS.compatibilityChecked = true;
} }
})(); })();
// Checks if navigator.language is supported
// Support: IE<11
(function checkNavigatorLanguage() {
if (typeof navigator === 'undefined') {
return;
}
if ('language' in navigator) {
return;
}
PDFJS.locale = navigator.userLanguage || 'en-US';
})();
// Support: Safari 6.0+, iOS // Support: Safari 6.0+, iOS
(function checkRangeRequests() { (function checkRangeRequests() {
// Safari has issues with cached range requests see: // Safari has issues with cached range requests see:
@ -103,25 +89,6 @@ PDFJS.compatibilityChecked = true;
} }
})(); })();
// Support: Android, iOS
(function checkCanvasSizeLimitation() {
if (isIOS || isAndroid) {
// 5MP
PDFJS.maxCanvasPixels = 5242880;
}
})();
// Disable fullscreen support for certain problematic configurations.
// Support: IE11+ (when embedded).
(function checkFullscreenSupport() {
if (!hasDOM) {
return;
}
if (isIE && window.parent !== window) {
PDFJS.disableFullscreen = true;
}
})();
// Provides document.currentScript support // Provides document.currentScript support
// Support: IE, Chrome<29. // Support: IE, Chrome<29.
(function checkCurrentScript() { (function checkCurrentScript() {

View File

@ -18,6 +18,7 @@
var WAITING_TIME = 100; // ms var WAITING_TIME = 100; // ms
var PDF_TO_CSS_UNITS = 96.0 / 72.0; var PDF_TO_CSS_UNITS = 96.0 / 72.0;
const IMAGE_RESOURCES_PATH = '/web/images/';
/** /**
* @class * @class
@ -164,6 +165,7 @@ var rasterizeAnnotationLayer = (function rasterizeAnnotationLayerClosure() {
} }
function rasterizeAnnotationLayer(ctx, viewport, annotations, page, function rasterizeAnnotationLayer(ctx, viewport, annotations, page,
imageResourcesPath,
renderInteractiveForms) { renderInteractiveForms) {
return new Promise(function (resolve) { return new Promise(function (resolve) {
// Building SVG with size of the viewport. // Building SVG with size of the viewport.
@ -194,6 +196,7 @@ var rasterizeAnnotationLayer = (function rasterizeAnnotationLayerClosure() {
annotations, annotations,
page, page,
linkService: new PDFJS.SimpleLinkService(), linkService: new PDFJS.SimpleLinkService(),
imageResourcesPath,
renderInteractiveForms, renderInteractiveForms,
}; };
PDFJS.AnnotationLayer.render(parameters); PDFJS.AnnotationLayer.render(parameters);
@ -251,8 +254,7 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars
PDFJS.workerSrc = '../build/generic/build/pdf.worker.js'; PDFJS.workerSrc = '../build/generic/build/pdf.worker.js';
PDFJS.cMapPacked = true; PDFJS.cMapPacked = true;
PDFJS.cMapUrl = '../external/bcmaps/'; PDFJS.cMapUrl = '../external/bcmaps/';
PDFJS.enableStats = true; PDFJS.pdfBug = true;
PDFJS.imageResourcesPath = '/web/images/';
// Set the passed options // Set the passed options
this.inflight = options.inflight; this.inflight = options.inflight;
@ -506,7 +508,9 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars
function(annotations) { function(annotations) {
return rasterizeAnnotationLayer(annotationLayerContext, return rasterizeAnnotationLayer(annotationLayerContext,
viewport, annotations, viewport, annotations,
page, renderForms); page,
IMAGE_RESOURCES_PATH,
renderForms);
}); });
} else { } else {
annotationLayerCanvas = null; annotationLayerCanvas = null;

View File

@ -13,11 +13,8 @@
* limitations under the License. * limitations under the License.
*/ */
import { import { DOMSVGFactory, getFilenameFromUrl } from '../../src/display/dom_utils';
DOMSVGFactory, getFilenameFromUrl, isExternalLinkTargetSet, LinkTarget
} from '../../src/display/dom_utils';
import isNodeJS from '../../src/shared/is_node'; import isNodeJS from '../../src/shared/is_node';
import { PDFJS } from '../../src/display/global';
describe('dom_utils', function() { describe('dom_utils', function() {
describe('DOMSVGFactory', function() { describe('DOMSVGFactory', function() {
@ -95,37 +92,4 @@ describe('dom_utils', function() {
expect(result).toEqual(expected); expect(result).toEqual(expected);
}); });
}); });
describe('isExternalLinkTargetSet', function() {
var savedExternalLinkTarget;
beforeAll(function (done) {
savedExternalLinkTarget = PDFJS.externalLinkTarget;
done();
});
afterAll(function () {
PDFJS.externalLinkTarget = savedExternalLinkTarget;
});
it('handles the predefined LinkTargets', function() {
for (var key in LinkTarget) {
var linkTarget = LinkTarget[key];
PDFJS.externalLinkTarget = linkTarget;
expect(isExternalLinkTargetSet()).toEqual(!!linkTarget);
}
});
it('handles incorrect LinkTargets', function() {
var targets = [true, '', false, -1, '_blank', null];
for (var i = 0, ii = targets.length; i < ii; i++) {
var linkTarget = targets[i];
PDFJS.externalLinkTarget = linkTarget;
expect(isExternalLinkTargetSet()).toEqual(false);
}
});
});
}); });

View File

@ -21,6 +21,8 @@ import { SimpleLinkService } from './pdf_link_service';
* @typedef {Object} AnnotationLayerBuilderOptions * @typedef {Object} AnnotationLayerBuilderOptions
* @property {HTMLDivElement} pageDiv * @property {HTMLDivElement} pageDiv
* @property {PDFPage} pdfPage * @property {PDFPage} pdfPage
* @property {string} imageResourcesPath - (optional) Path for image resources,
* mainly for annotation icons. Include trailing slash.
* @property {boolean} renderInteractiveForms * @property {boolean} renderInteractiveForms
* @property {IPDFLinkService} linkService * @property {IPDFLinkService} linkService
* @property {DownloadManager} downloadManager * @property {DownloadManager} downloadManager
@ -32,11 +34,13 @@ class AnnotationLayerBuilder {
* @param {AnnotationLayerBuilderOptions} options * @param {AnnotationLayerBuilderOptions} options
*/ */
constructor({ pageDiv, pdfPage, linkService, downloadManager, constructor({ pageDiv, pdfPage, linkService, downloadManager,
renderInteractiveForms = false, l10n = NullL10n, }) { imageResourcesPath = '', renderInteractiveForms = false,
l10n = NullL10n, }) {
this.pageDiv = pageDiv; this.pageDiv = pageDiv;
this.pdfPage = pdfPage; this.pdfPage = pdfPage;
this.linkService = linkService; this.linkService = linkService;
this.downloadManager = downloadManager; this.downloadManager = downloadManager;
this.imageResourcesPath = imageResourcesPath;
this.renderInteractiveForms = renderInteractiveForms; this.renderInteractiveForms = renderInteractiveForms;
this.l10n = l10n; this.l10n = l10n;
@ -59,6 +63,7 @@ class AnnotationLayerBuilder {
div: this.div, div: this.div,
annotations, annotations,
page: this.pdfPage, page: this.pdfPage,
imageResourcesPath: this.imageResourcesPath,
renderInteractiveForms: this.renderInteractiveForms, renderInteractiveForms: this.renderInteractiveForms,
linkService: this.linkService, linkService: this.linkService,
downloadManager: this.downloadManager, downloadManager: this.downloadManager,
@ -104,15 +109,19 @@ class DefaultAnnotationLayerFactory {
/** /**
* @param {HTMLDivElement} pageDiv * @param {HTMLDivElement} pageDiv
* @param {PDFPage} pdfPage * @param {PDFPage} pdfPage
* @param {string} imageResourcesPath - (optional) Path for image resources,
* mainly for annotation icons. Include trailing slash.
* @param {boolean} renderInteractiveForms * @param {boolean} renderInteractiveForms
* @param {IL10n} l10n * @param {IL10n} l10n
* @returns {AnnotationLayerBuilder} * @returns {AnnotationLayerBuilder}
*/ */
createAnnotationLayerBuilder(pageDiv, pdfPage, renderInteractiveForms = false, createAnnotationLayerBuilder(pageDiv, pdfPage, imageResourcesPath = '',
renderInteractiveForms = false,
l10n = NullL10n) { l10n = NullL10n) {
return new AnnotationLayerBuilder({ return new AnnotationLayerBuilder({
pageDiv, pageDiv,
pdfPage, pdfPage,
imageResourcesPath,
renderInteractiveForms, renderInteractiveForms,
linkService: new SimpleLinkService(), linkService: new SimpleLinkService(),
l10n, l10n,

View File

@ -18,11 +18,11 @@ import {
animationStarted, DEFAULT_SCALE_VALUE, getPDFFileNameFromURL, isFileSchema, animationStarted, DEFAULT_SCALE_VALUE, getPDFFileNameFromURL, isFileSchema,
isValidRotation, MAX_SCALE, MIN_SCALE, noContextMenuHandler, isValidRotation, MAX_SCALE, MIN_SCALE, noContextMenuHandler,
normalizeWheelEventDelta, parseQueryString, PresentationModeState, normalizeWheelEventDelta, parseQueryString, PresentationModeState,
ProgressBar, RendererType ProgressBar, RendererType, TextLayerMode
} from './ui_utils'; } from './ui_utils';
import { import {
build, createBlob, getDocument, getFilenameFromUrl, InvalidPDFException, build, createBlob, getDocument, getFilenameFromUrl, InvalidPDFException,
MissingPDFException, OPS, PDFJS, PDFWorker, shadow, LinkTarget, MissingPDFException, OPS, PDFJS, PDFWorker, shadow,
UnexpectedResponseException, UNSUPPORTED_FEATURES, version UnexpectedResponseException, UNSUPPORTED_FEATURES, version
} from 'pdfjs-lib'; } from 'pdfjs-lib';
import { CursorTool, PDFCursorTools } from './pdf_cursor_tools'; import { CursorTool, PDFCursorTools } from './pdf_cursor_tools';
@ -44,6 +44,7 @@ import { PDFThumbnailViewer } from './pdf_thumbnail_viewer';
import { PDFViewer } from './pdf_viewer'; import { PDFViewer } from './pdf_viewer';
import { SecondaryToolbar } from './secondary_toolbar'; import { SecondaryToolbar } from './secondary_toolbar';
import { Toolbar } from './toolbar'; import { Toolbar } from './toolbar';
import { viewerCompatibilityParams } from './viewer_compatibility';
import { ViewHistory } from './view_history'; import { ViewHistory } from './view_history';
const DEFAULT_SCALE_DELTA = 1.1; const DEFAULT_SCALE_DELTA = 1.1;
@ -138,6 +139,7 @@ let PDFViewerApplication = {
isInitialViewSet: false, isInitialViewSet: false,
downloadComplete: false, downloadComplete: false,
viewerPrefs: { viewerPrefs: {
enableWebGL: false,
sidebarViewOnLoad: SidebarView.NONE, sidebarViewOnLoad: SidebarView.NONE,
pdfBugEnabled: false, pdfBugEnabled: false,
showPreviousViewOnLoad: true, showPreviousViewOnLoad: true,
@ -145,7 +147,7 @@ let PDFViewerApplication = {
disablePageMode: false, disablePageMode: false,
disablePageLabels: false, disablePageLabels: false,
renderer: 'canvas', renderer: 'canvas',
enhanceTextSelection: false, textLayerMode: TextLayerMode.ENABLE,
renderInteractiveForms: false, renderInteractiveForms: false,
enablePrintAutoRotate: false, enablePrintAutoRotate: false,
}, },
@ -183,10 +185,11 @@ let PDFViewerApplication = {
this.eventBus.dispatch('localized'); this.eventBus.dispatch('localized');
}); });
if (this.isViewerEmbedded && !PDFJS.isExternalLinkTargetSet()) { if (this.isViewerEmbedded &&
PDFJS.externalLinkTarget === LinkTarget.NONE) {
// Prevent external links from "replacing" the viewer, // Prevent external links from "replacing" the viewer,
// when it's embedded in e.g. an iframe or an object. // when it's embedded in e.g. an iframe or an object.
PDFJS.externalLinkTarget = PDFJS.LinkTarget.TOP; PDFJS.externalLinkTarget = LinkTarget.TOP;
} }
this.initialized = true; this.initialized = true;
@ -201,7 +204,7 @@ let PDFViewerApplication = {
return Promise.all([ return Promise.all([
preferences.get('enableWebGL').then(function resolved(value) { preferences.get('enableWebGL').then(function resolved(value) {
PDFJS.disableWebGL = !value; viewerPrefs['enableWebGL'] = value;
}), }),
preferences.get('sidebarViewOnLoad').then(function resolved(value) { preferences.get('sidebarViewOnLoad').then(function resolved(value) {
viewerPrefs['sidebarViewOnLoad'] = value; viewerPrefs['sidebarViewOnLoad'] = value;
@ -215,14 +218,11 @@ let PDFViewerApplication = {
preferences.get('defaultZoomValue').then(function resolved(value) { preferences.get('defaultZoomValue').then(function resolved(value) {
viewerPrefs['defaultZoomValue'] = value; viewerPrefs['defaultZoomValue'] = value;
}), }),
preferences.get('enhanceTextSelection').then(function resolved(value) { preferences.get('textLayerMode').then(function resolved(value) {
viewerPrefs['enhanceTextSelection'] = value; if (viewerPrefs['textLayerMode'] === TextLayerMode.DISABLE) {
}),
preferences.get('disableTextLayer').then(function resolved(value) {
if (PDFJS.disableTextLayer === true) {
return; return;
} }
PDFJS.disableTextLayer = value; viewerPrefs['textLayerMode'] = value;
}), }),
preferences.get('disableRange').then(function resolved(value) { preferences.get('disableRange').then(function resolved(value) {
if (PDFJS.disableRange === true) { if (PDFJS.disableRange === true) {
@ -249,7 +249,7 @@ let PDFViewerApplication = {
PDFJS.useOnlyCssZoom = value; PDFJS.useOnlyCssZoom = value;
}), }),
preferences.get('externalLinkTarget').then(function resolved(value) { preferences.get('externalLinkTarget').then(function resolved(value) {
if (PDFJS.isExternalLinkTargetSet()) { if (PDFJS.externalLinkTarget !== LinkTarget.NONE) {
return; return;
} }
PDFJS.externalLinkTarget = value; PDFJS.externalLinkTarget = value;
@ -305,7 +305,7 @@ let PDFViewerApplication = {
PDFJS.disableHistory = (hashParams['disablehistory'] === 'true'); PDFJS.disableHistory = (hashParams['disablehistory'] === 'true');
} }
if ('webgl' in hashParams) { if ('webgl' in hashParams) {
PDFJS.disableWebGL = (hashParams['webgl'] !== 'true'); viewerPrefs['enableWebGL'] = (hashParams['webgl'] === 'true');
} }
if ('useonlycsszoom' in hashParams) { if ('useonlycsszoom' in hashParams) {
PDFJS.useOnlyCssZoom = (hashParams['useonlycsszoom'] === 'true'); PDFJS.useOnlyCssZoom = (hashParams['useonlycsszoom'] === 'true');
@ -321,7 +321,7 @@ let PDFViewerApplication = {
if ('textlayer' in hashParams) { if ('textlayer' in hashParams) {
switch (hashParams['textlayer']) { switch (hashParams['textlayer']) {
case 'off': case 'off':
PDFJS.disableTextLayer = true; viewerPrefs['textLayerMode'] = TextLayerMode.DISABLE;
break; break;
case 'visible': case 'visible':
case 'shadow': case 'shadow':
@ -333,8 +333,7 @@ let PDFViewerApplication = {
} }
if ('pdfbug' in hashParams) { if ('pdfbug' in hashParams) {
PDFJS.pdfBug = true; PDFJS.pdfBug = true;
let pdfBug = hashParams['pdfbug']; let enabled = hashParams['pdfbug'].split(',');
let enabled = pdfBug.split(',');
waitOn.push(loadAndEnablePDFBug(enabled)); waitOn.push(loadAndEnablePDFBug(enabled));
} }
// Locale can be changed only when special debugging flags is present in // Locale can be changed only when special debugging flags is present in
@ -353,7 +352,9 @@ let PDFViewerApplication = {
* @private * @private
*/ */
_initializeL10n() { _initializeL10n() {
this.l10n = this.externalServices.createL10n(); this.l10n = this.externalServices.createL10n({
locale: PDFJS.locale,
});
return this.l10n.getDirection().then((dir) => { return this.l10n.getDirection().then((dir) => {
document.getElementsByTagName('html')[0].dir = dir; document.getElementsByTagName('html')[0].dir = dir;
}); });
@ -377,6 +378,8 @@ let PDFViewerApplication = {
let pdfLinkService = new PDFLinkService({ let pdfLinkService = new PDFLinkService({
eventBus, eventBus,
externalLinkTarget: PDFJS.externalLinkTarget,
externalLinkRel: PDFJS.externalLinkRel,
}); });
this.pdfLinkService = pdfLinkService; this.pdfLinkService = pdfLinkService;
@ -393,10 +396,14 @@ let PDFViewerApplication = {
linkService: pdfLinkService, linkService: pdfLinkService,
downloadManager, downloadManager,
renderer: viewerPrefs['renderer'], renderer: viewerPrefs['renderer'],
enableWebGL: viewerPrefs['enableWebGL'],
l10n: this.l10n, l10n: this.l10n,
enhanceTextSelection: viewerPrefs['enhanceTextSelection'], textLayerMode: viewerPrefs['textLayerMode'],
imageResourcesPath: PDFJS.imageResourcesPath,
renderInteractiveForms: viewerPrefs['renderInteractiveForms'], renderInteractiveForms: viewerPrefs['renderInteractiveForms'],
enablePrintAutoRotate: viewerPrefs['enablePrintAutoRotate'], enablePrintAutoRotate: viewerPrefs['enablePrintAutoRotate'],
useOnlyCssZoom: PDFJS.useOnlyCssZoom,
maxCanvasPixels: PDFJS.maxCanvasPixels,
}); });
pdfRenderingQueue.setViewer(this.pdfViewer); pdfRenderingQueue.setViewer(this.pdfViewer);
pdfLinkService.setViewer(this.pdfViewer); pdfLinkService.setViewer(this.pdfViewer);
@ -561,7 +568,7 @@ let PDFViewerApplication = {
support = false; support = false;
} }
} }
if (support && PDFJS.disableFullscreen === true) { if (support && viewerCompatibilityParams['disableFullscreen'] === true) {
support = false; support = false;
} }
@ -1168,7 +1175,7 @@ let PDFViewerApplication = {
info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() + info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() +
' / ' + (info.Creator || '-').trim() + ']' + ' / ' + (info.Creator || '-').trim() + ']' +
' (PDF.js: ' + (version || '-') + ' (PDF.js: ' + (version || '-') +
(!PDFJS.disableWebGL ? ' [WebGL]' : '') + ')'); (this.viewerPrefs['enableWebGL'] ? ' [WebGL]' : '') + ')');
let pdfTitle; let pdfTitle;
if (metadata && metadata.has('dc:title')) { if (metadata && metadata.has('dc:title')) {
@ -1550,7 +1557,6 @@ function loadAndEnablePDFBug(enabledTabs) {
script.onload = function () { script.onload = function () {
PDFBug.enable(enabledTabs); PDFBug.enable(enabledTabs);
PDFBug.init({ PDFBug.init({
PDFJS,
OPS, OPS,
}, appConfig.mainContainer); }, appConfig.mainContainer);
resolve(); resolve();
@ -1715,8 +1721,7 @@ function webViewerPageRendered(evt) {
thumbnailView.setImage(pageView); thumbnailView.setImage(pageView);
} }
if (PDFJS.pdfBug && typeof Stats !== 'undefined' && Stats.enabled && if (typeof Stats !== 'undefined' && Stats.enabled && pageView.stats) {
pageView.stats) {
Stats.add(pageNumber, pageView.stats); Stats.add(pageNumber, pageView.stats);
} }
@ -2005,7 +2010,7 @@ function webViewerPageChanging(evt) {
} }
// we need to update stats // we need to update stats
if (PDFJS.pdfBug && typeof Stats !== 'undefined' && Stats.enabled) { if (typeof Stats !== 'undefined' && Stats.enabled) {
let pageView = PDFViewerApplication.pdfViewer.getPageView(page - 1); let pageView = PDFViewerApplication.pdfViewer.getPageView(page - 1);
if (pageView && pageView.stats) { if (pageView && pageView.stats) {
Stats.add(page, pageView.stats); Stats.add(page, pageView.stats);

View File

@ -17,7 +17,7 @@ import { createPromiseCapability, PDFJS } from 'pdfjs-lib';
import { import {
CSS_UNITS, DEFAULT_SCALE, DEFAULT_SCALE_VALUE, isValidRotation, CSS_UNITS, DEFAULT_SCALE, DEFAULT_SCALE_VALUE, isValidRotation,
MAX_AUTO_SCALE, NullL10n, PresentationModeState, RendererType, MAX_AUTO_SCALE, NullL10n, PresentationModeState, RendererType,
SCROLLBAR_PADDING, UNKNOWN_SCALE, VERTICAL_PADDING, watchScroll SCROLLBAR_PADDING, TextLayerMode, UNKNOWN_SCALE, VERTICAL_PADDING, watchScroll
} from './ui_utils'; } from './ui_utils';
import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue'; import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue';
import { AnnotationLayerBuilder } from './annotation_layer_builder'; import { AnnotationLayerBuilder } from './annotation_layer_builder';
@ -39,15 +39,26 @@ const DEFAULT_CACHE_SIZE = 10;
* @property {PDFRenderingQueue} renderingQueue - (optional) The rendering * @property {PDFRenderingQueue} renderingQueue - (optional) The rendering
* queue object. * queue object.
* @property {boolean} removePageBorders - (optional) Removes the border shadow * @property {boolean} removePageBorders - (optional) Removes the border shadow
* around the pages. The default is false. * around the pages. The default value is `false`.
* @property {boolean} enhanceTextSelection - (optional) Enables the improved * @property {number} textLayerMode - (optional) Controls if the text layer used
* text selection behaviour. The default is `false`. * for selection and searching is created, and if the improved text selection
* behaviour is enabled. The constants from {TextLayerMode} should be used.
* The default value is `TextLayerMode.ENABLE`.
* @property {string} imageResourcesPath - (optional) Path for image resources,
* mainly for annotation icons. Include trailing slash.
* @property {boolean} renderInteractiveForms - (optional) Enables rendering of * @property {boolean} renderInteractiveForms - (optional) Enables rendering of
* interactive form elements. The default is `false`. * interactive form elements. The default is `false`.
* @property {boolean} enablePrintAutoRotate - (optional) Enables automatic * @property {boolean} enablePrintAutoRotate - (optional) Enables automatic
* rotation of pages whose orientation differ from the first page upon * rotation of pages whose orientation differ from the first page upon
* printing. The default is `false`. * printing. The default is `false`.
* @property {string} renderer - 'canvas' or 'svg'. The default is 'canvas'. * @property {string} renderer - 'canvas' or 'svg'. The default is 'canvas'.
* @property {boolean} enableWebGL - (optional) Enables WebGL accelerated
* rendering for some operations. The default value is `false`.
* @property {boolean} useOnlyCssZoom - (optional) Enables CSS only zooming.
* The default value is `false`.
* @property {number} maxCanvasPixels - (optional) The maximum supported canvas
* size in total pixels, i.e. width * height. Use -1 for no limit.
* The default value is 4096 * 4096 (16 mega-pixels).
* @property {IL10n} l10n - Localization service. * @property {IL10n} l10n - Localization service.
*/ */
@ -107,10 +118,16 @@ class BaseViewer {
this.linkService = options.linkService || new SimpleLinkService(); this.linkService = options.linkService || new SimpleLinkService();
this.downloadManager = options.downloadManager || null; this.downloadManager = options.downloadManager || null;
this.removePageBorders = options.removePageBorders || false; this.removePageBorders = options.removePageBorders || false;
this.textLayerMode = Number.isInteger(options.textLayerMode) ?
options.textLayerMode : TextLayerMode.ENABLE;
this.enhanceTextSelection = options.enhanceTextSelection || false; this.enhanceTextSelection = options.enhanceTextSelection || false;
this.imageResourcesPath = options.imageResourcesPath || '';
this.renderInteractiveForms = options.renderInteractiveForms || false; this.renderInteractiveForms = options.renderInteractiveForms || false;
this.enablePrintAutoRotate = options.enablePrintAutoRotate || false; this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
this.renderer = options.renderer || RendererType.CANVAS; this.renderer = options.renderer || RendererType.CANVAS;
this.enableWebGL = options.enableWebGL || false;
this.useOnlyCssZoom = options.useOnlyCssZoom || false;
this.maxCanvasPixels = options.maxCanvasPixels;
this.l10n = options.l10n || NullL10n; this.l10n = options.l10n || NullL10n;
this.defaultRenderingQueue = !options.renderingQueue; this.defaultRenderingQueue = !options.renderingQueue;
@ -362,7 +379,7 @@ class BaseViewer {
let viewport = pdfPage.getViewport(scale * CSS_UNITS); let viewport = pdfPage.getViewport(scale * CSS_UNITS);
for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
let textLayerFactory = null; let textLayerFactory = null;
if (!PDFJS.disableTextLayer) { if (this.textLayerMode !== TextLayerMode.DISABLE) {
textLayerFactory = this; textLayerFactory = this;
} }
let pageView = new PDFPageView({ let pageView = new PDFPageView({
@ -373,10 +390,14 @@ class BaseViewer {
defaultViewport: viewport.clone(), defaultViewport: viewport.clone(),
renderingQueue: this.renderingQueue, renderingQueue: this.renderingQueue,
textLayerFactory, textLayerFactory,
textLayerMode: this.textLayerMode,
annotationLayerFactory: this, annotationLayerFactory: this,
enhanceTextSelection: this.enhanceTextSelection, imageResourcesPath: this.imageResourcesPath,
renderInteractiveForms: this.renderInteractiveForms, renderInteractiveForms: this.renderInteractiveForms,
renderer: this.renderer, renderer: this.renderer,
enableWebGL: this.enableWebGL,
useOnlyCssZoom: this.useOnlyCssZoom,
maxCanvasPixels: this.maxCanvasPixels,
l10n: this.l10n, l10n: this.l10n,
}); });
bindOnAfterAndBeforeDraw(pageView); bindOnAfterAndBeforeDraw(pageView);
@ -872,15 +893,19 @@ class BaseViewer {
/** /**
* @param {HTMLDivElement} pageDiv * @param {HTMLDivElement} pageDiv
* @param {PDFPage} pdfPage * @param {PDFPage} pdfPage
* @param {string} imageResourcesPath - (optional) Path for image resources,
* mainly for annotation icons. Include trailing slash.
* @param {boolean} renderInteractiveForms * @param {boolean} renderInteractiveForms
* @param {IL10n} l10n * @param {IL10n} l10n
* @returns {AnnotationLayerBuilder} * @returns {AnnotationLayerBuilder}
*/ */
createAnnotationLayerBuilder(pageDiv, pdfPage, renderInteractiveForms = false, createAnnotationLayerBuilder(pageDiv, pdfPage, imageResourcesPath = '',
renderInteractiveForms = false,
l10n = NullL10n) { l10n = NullL10n) {
return new AnnotationLayerBuilder({ return new AnnotationLayerBuilder({
pageDiv, pageDiv,
pdfPage, pdfPage,
imageResourcesPath,
renderInteractiveForms, renderInteractiveForms,
linkService: this.linkService, linkService: this.linkService,
downloadManager: this.downloadManager, downloadManager: this.downloadManager,

View File

@ -342,7 +342,7 @@ ChromeExternalServices.createDownloadManager = function() {
ChromeExternalServices.createPreferences = function() { ChromeExternalServices.createPreferences = function() {
return new ChromePreferences(); return new ChromePreferences();
}; };
ChromeExternalServices.createL10n = function() { ChromeExternalServices.createL10n = function(options) {
return new GenericL10n(navigator.language); return new GenericL10n(navigator.language);
}; };
PDFViewerApplication.externalServices = ChromeExternalServices; PDFViewerApplication.externalServices = ChromeExternalServices;

View File

@ -462,7 +462,6 @@ var Stats = (function Stats() {
manager: null, manager: null,
init(pdfjsLib) { init(pdfjsLib) {
this.panel.setAttribute('style', 'padding: 5px;'); this.panel.setAttribute('style', 'padding: 5px;');
pdfjsLib.PDFJS.enableStats = true;
}, },
enabled: false, enabled: false,
active: false, active: false,

View File

@ -9,10 +9,9 @@
"disableStream": false, "disableStream": false,
"disableAutoFetch": false, "disableAutoFetch": false,
"disableFontFace": false, "disableFontFace": false,
"disableTextLayer": false, "textLayerMode": 1,
"useOnlyCssZoom": false, "useOnlyCssZoom": false,
"externalLinkTarget": 0, "externalLinkTarget": 0,
"enhanceTextSelection": false,
"renderer": "canvas", "renderer": "canvas",
"renderInteractiveForms": false, "renderInteractiveForms": false,
"enablePrintAutoRotate": false, "enablePrintAutoRotate": false,

View File

@ -264,7 +264,7 @@ PDFViewerApplication.externalServices = {
return new FirefoxPreferences(); return new FirefoxPreferences();
}, },
createL10n() { createL10n(options) {
let mozL10n = document.mozL10n; let mozL10n = document.mozL10n;
// TODO refactor mozL10n.setExternalLocalizerServices // TODO refactor mozL10n.setExternalLocalizerServices
return new MozL10n(mozL10n); return new MozL10n(mozL10n);

View File

@ -17,7 +17,6 @@ import { DefaultExternalServices, PDFViewerApplication } from './app';
import { BasePreferences } from './preferences'; import { BasePreferences } from './preferences';
import { DownloadManager } from './download_manager'; import { DownloadManager } from './download_manager';
import { GenericL10n } from './genericl10n'; import { GenericL10n } from './genericl10n';
import { PDFJS } from 'pdfjs-lib';
if (typeof PDFJSDev !== 'undefined' && !PDFJSDev.test('GENERIC')) { if (typeof PDFJSDev !== 'undefined' && !PDFJSDev.test('GENERIC')) {
throw new Error('Module "pdfjs-web/genericcom" shall not be used outside ' + throw new Error('Module "pdfjs-web/genericcom" shall not be used outside ' +
@ -49,8 +48,8 @@ GenericExternalServices.createDownloadManager = function() {
GenericExternalServices.createPreferences = function() { GenericExternalServices.createPreferences = function() {
return new GenericPreferences(); return new GenericPreferences();
}; };
GenericExternalServices.createL10n = function () { GenericExternalServices.createL10n = function(options) {
return new GenericL10n(PDFJS.locale); return new GenericL10n(options.locale);
}; };
PDFViewerApplication.externalServices = GenericExternalServices; PDFViewerApplication.externalServices = GenericExternalServices;

View File

@ -145,11 +145,13 @@ class IPDFAnnotationLayerFactory {
/** /**
* @param {HTMLDivElement} pageDiv * @param {HTMLDivElement} pageDiv
* @param {PDFPage} pdfPage * @param {PDFPage} pdfPage
* @param {IL10n} l10n * @param {string} imageResourcesPath - (optional) Path for image resources,
* mainly for annotation icons. Include trailing slash.
* @param {boolean} renderInteractiveForms * @param {boolean} renderInteractiveForms
* @param {IL10n} l10n
* @returns {AnnotationLayerBuilder} * @returns {AnnotationLayerBuilder}
*/ */
createAnnotationLayerBuilder(pageDiv, pdfPage, createAnnotationLayerBuilder(pageDiv, pdfPage, imageResourcesPath = '',
renderInteractiveForms = false, renderInteractiveForms = false,
l10n = undefined) {} l10n = undefined) {}
} }

View File

@ -19,6 +19,11 @@ import { parseQueryString } from './ui_utils';
/** /**
* @typedef {Object} PDFLinkServiceOptions * @typedef {Object} PDFLinkServiceOptions
* @property {EventBus} eventBus - The application event bus. * @property {EventBus} eventBus - The application event bus.
* @property {number} externalLinkTarget - (optional) Specifies the `target`
* attribute for external links. Must use one of the values from {LinkTarget}.
* Defaults to using no target.
* @property {string} externalLinkRel - (optional) Specifies the `rel` attribute
* for external links. Defaults to stripping the referrer.
*/ */
/** /**
@ -30,8 +35,12 @@ class PDFLinkService {
/** /**
* @param {PDFLinkServiceOptions} options * @param {PDFLinkServiceOptions} options
*/ */
constructor({ eventBus, } = {}) { constructor({ eventBus, externalLinkTarget = null,
externalLinkRel = null, } = {}) {
this.eventBus = eventBus || getGlobalEventBus(); this.eventBus = eventBus || getGlobalEventBus();
this.externalLinkTarget = externalLinkTarget;
this.externalLinkRel = externalLinkRel;
this.baseUrl = null; this.baseUrl = null;
this.pdfDocument = null; this.pdfDocument = null;
this.pdfViewer = null; this.pdfViewer = null;
@ -409,6 +418,11 @@ function isValidExplicitDestination(dest) {
} }
class SimpleLinkService { class SimpleLinkService {
constructor() {
this.externalLinkTarget = null;
this.externalLinkRel = null;
}
/** /**
* @returns {number} * @returns {number}
*/ */

View File

@ -13,9 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { import { addLinkAttributes, LinkTarget, removeNullCharacters } from 'pdfjs-lib';
addLinkAttributes, PDFJS, removeNullCharacters
} from 'pdfjs-lib';
const DEFAULT_TITLE = '\u2013'; const DEFAULT_TITLE = '\u2013';
@ -68,20 +66,22 @@ class PDFOutlineViewer {
/** /**
* @private * @private
*/ */
_bindLink(element, item) { _bindLink(element, { url, newWindow, dest, }) {
if (item.url) { let { linkService, } = this;
if (url) {
addLinkAttributes(element, { addLinkAttributes(element, {
url: item.url, url,
target: (item.newWindow ? PDFJS.LinkTarget.BLANK : undefined), target: (newWindow ? LinkTarget.BLANK : linkService.externalLinkTarget),
rel: linkService.externalLinkRel,
}); });
return; return;
} }
let destination = item.dest;
element.href = this.linkService.getDestinationHash(destination); element.href = this.linkService.getDestinationHash(dest);
element.onclick = () => { element.onclick = () => {
if (destination) { if (dest) {
this.linkService.navigateTo(destination); this.linkService.navigateTo(dest);
} }
return false; return false;
}; };
@ -90,12 +90,12 @@ class PDFOutlineViewer {
/** /**
* @private * @private
*/ */
_setStyles(element, item) { _setStyles(element, { bold, italic, }) {
let styleStr = ''; let styleStr = '';
if (item.bold) { if (bold) {
styleStr += 'font-weight: bold;'; styleStr += 'font-weight: bold;';
} }
if (item.italic) { if (italic) {
styleStr += 'font-style: italic;'; styleStr += 'font-style: italic;';
} }

View File

@ -15,13 +15,14 @@
import { import {
approximateFraction, CSS_UNITS, DEFAULT_SCALE, getOutputScale, NullL10n, approximateFraction, CSS_UNITS, DEFAULT_SCALE, getOutputScale, NullL10n,
RendererType, roundToDivide RendererType, roundToDivide, TextLayerMode
} from './ui_utils'; } from './ui_utils';
import { import {
createPromiseCapability, PDFJS, RenderingCancelledException, SVGGraphics createPromiseCapability, RenderingCancelledException, SVGGraphics
} from 'pdfjs-lib'; } from 'pdfjs-lib';
import { getGlobalEventBus } from './dom_events'; import { getGlobalEventBus } from './dom_events';
import { RenderingStates } from './pdf_rendering_queue'; import { RenderingStates } from './pdf_rendering_queue';
import { viewerCompatibilityParams } from './viewer_compatibility';
/** /**
* @typedef {Object} PDFPageViewOptions * @typedef {Object} PDFPageViewOptions
@ -32,15 +33,28 @@ import { RenderingStates } from './pdf_rendering_queue';
* @property {PageViewport} defaultViewport - The page viewport. * @property {PageViewport} defaultViewport - The page viewport.
* @property {PDFRenderingQueue} renderingQueue - The rendering queue object. * @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
* @property {IPDFTextLayerFactory} textLayerFactory * @property {IPDFTextLayerFactory} textLayerFactory
* @property {number} textLayerMode - (optional) Controls if the text layer used
* for selection and searching is created, and if the improved text selection
* behaviour is enabled. The constants from {TextLayerMode} should be used.
* The default value is `TextLayerMode.ENABLE`.
* @property {IPDFAnnotationLayerFactory} annotationLayerFactory * @property {IPDFAnnotationLayerFactory} annotationLayerFactory
* @property {boolean} enhanceTextSelection - Turns on the text selection * @property {string} imageResourcesPath - (optional) Path for image resources,
* enhancement. The default is `false`. * mainly for annotation icons. Include trailing slash.
* @property {boolean} renderInteractiveForms - Turns on rendering of * @property {boolean} renderInteractiveForms - Turns on rendering of
* interactive form elements. The default is `false`. * interactive form elements. The default is `false`.
* @property {string} renderer - 'canvas' or 'svg'. The default is 'canvas'. * @property {string} renderer - 'canvas' or 'svg'. The default is 'canvas'.
* @property {boolean} enableWebGL - (optional) Enables WebGL accelerated
* rendering for some operations. The default value is `false`.
* @property {boolean} useOnlyCssZoom - (optional) Enables CSS only zooming.
* The default value is `false`.
* @property {number} maxCanvasPixels - (optional) The maximum supported canvas
* size in total pixels, i.e. width * height. Use -1 for no limit.
* The default value is 4096 * 4096 (16 mega-pixels).
* @property {IL10n} l10n - Localization service. * @property {IL10n} l10n - Localization service.
*/ */
const MAX_CANVAS_PIXELS = viewerCompatibilityParams.maxCanvasPixels || 16777216;
/** /**
* @implements {IRenderableView} * @implements {IRenderableView}
*/ */
@ -62,14 +76,19 @@ class PDFPageView {
this.viewport = defaultViewport; this.viewport = defaultViewport;
this.pdfPageRotate = defaultViewport.rotation; this.pdfPageRotate = defaultViewport.rotation;
this.hasRestrictedScaling = false; this.hasRestrictedScaling = false;
this.enhanceTextSelection = options.enhanceTextSelection || false; this.textLayerMode = Number.isInteger(options.textLayerMode) ?
options.textLayerMode : TextLayerMode.ENABLE;
this.imageResourcesPath = options.imageResourcesPath || '';
this.renderInteractiveForms = options.renderInteractiveForms || false; this.renderInteractiveForms = options.renderInteractiveForms || false;
this.useOnlyCssZoom = options.useOnlyCssZoom || false;
this.maxCanvasPixels = options.maxCanvasPixels || MAX_CANVAS_PIXELS;
this.eventBus = options.eventBus || getGlobalEventBus(); this.eventBus = options.eventBus || getGlobalEventBus();
this.renderingQueue = options.renderingQueue; this.renderingQueue = options.renderingQueue;
this.textLayerFactory = options.textLayerFactory; this.textLayerFactory = options.textLayerFactory;
this.annotationLayerFactory = options.annotationLayerFactory; this.annotationLayerFactory = options.annotationLayerFactory;
this.renderer = options.renderer || RendererType.CANVAS; this.renderer = options.renderer || RendererType.CANVAS;
this.enableWebGL = options.enableWebGL || false;
this.l10n = options.l10n || NullL10n; this.l10n = options.l10n || NullL10n;
this.paintTask = null; this.paintTask = null;
@ -208,17 +227,17 @@ class PDFPageView {
} }
let isScalingRestricted = false; let isScalingRestricted = false;
if (this.canvas && PDFJS.maxCanvasPixels > 0) { if (this.canvas && this.maxCanvasPixels > 0) {
let outputScale = this.outputScale; let outputScale = this.outputScale;
if (((Math.floor(this.viewport.width) * outputScale.sx) | 0) * if (((Math.floor(this.viewport.width) * outputScale.sx) | 0) *
((Math.floor(this.viewport.height) * outputScale.sy) | 0) > ((Math.floor(this.viewport.height) * outputScale.sy) | 0) >
PDFJS.maxCanvasPixels) { this.maxCanvasPixels) {
isScalingRestricted = true; isScalingRestricted = true;
} }
} }
if (this.canvas) { if (this.canvas) {
if (PDFJS.useOnlyCssZoom || if (this.useOnlyCssZoom ||
(this.hasRestrictedScaling && isScalingRestricted)) { (this.hasRestrictedScaling && isScalingRestricted)) {
this.cssTransform(this.canvas, true); this.cssTransform(this.canvas, true);
@ -371,7 +390,7 @@ class PDFPageView {
} }
let textLayer = null; let textLayer = null;
if (this.textLayerFactory) { if (this.textLayerMode !== TextLayerMode.DISABLE && this.textLayerFactory) {
let textLayerDiv = document.createElement('div'); let textLayerDiv = document.createElement('div');
textLayerDiv.className = 'textLayer'; textLayerDiv.className = 'textLayer';
textLayerDiv.style.width = canvasWrapper.style.width; textLayerDiv.style.width = canvasWrapper.style.width;
@ -385,7 +404,7 @@ class PDFPageView {
textLayer = this.textLayerFactory. textLayer = this.textLayerFactory.
createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport,
this.enhanceTextSelection); this.textLayerMode === TextLayerMode.ENABLE_ENHANCE);
} }
this.textLayer = textLayer; this.textLayer = textLayer;
@ -465,7 +484,7 @@ class PDFPageView {
if (this.annotationLayerFactory) { if (this.annotationLayerFactory) {
if (!this.annotationLayer) { if (!this.annotationLayer) {
this.annotationLayer = this.annotationLayerFactory. this.annotationLayer = this.annotationLayerFactory.
createAnnotationLayerBuilder(div, pdfPage, createAnnotationLayerBuilder(div, pdfPage, this.imageResourcesPath,
this.renderInteractiveForms, this.l10n); this.renderInteractiveForms, this.l10n);
} }
this.annotationLayer.render(this.viewport, 'display'); this.annotationLayer.render(this.viewport, 'display');
@ -517,7 +536,7 @@ class PDFPageView {
let outputScale = getOutputScale(ctx); let outputScale = getOutputScale(ctx);
this.outputScale = outputScale; this.outputScale = outputScale;
if (PDFJS.useOnlyCssZoom) { if (this.useOnlyCssZoom) {
let actualSizeViewport = viewport.clone({ scale: CSS_UNITS, }); let actualSizeViewport = viewport.clone({ scale: CSS_UNITS, });
// Use a scale that makes the canvas have the originally intended size // Use a scale that makes the canvas have the originally intended size
// of the page. // of the page.
@ -526,9 +545,9 @@ class PDFPageView {
outputScale.scaled = true; outputScale.scaled = true;
} }
if (PDFJS.maxCanvasPixels > 0) { if (this.maxCanvasPixels > 0) {
let pixelsInViewport = viewport.width * viewport.height; let pixelsInViewport = viewport.width * viewport.height;
let maxScale = Math.sqrt(PDFJS.maxCanvasPixels / pixelsInViewport); let maxScale = Math.sqrt(this.maxCanvasPixels / pixelsInViewport);
if (outputScale.sx > maxScale || outputScale.sy > maxScale) { if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
outputScale.sx = maxScale; outputScale.sx = maxScale;
outputScale.sy = maxScale; outputScale.sy = maxScale;
@ -555,6 +574,7 @@ class PDFPageView {
canvasContext: ctx, canvasContext: ctx,
transform, transform,
viewport: this.viewport, viewport: this.viewport,
enableWebGL: this.enableWebGL,
renderInteractiveForms: this.renderInteractiveForms, renderInteractiveForms: this.renderInteractiveForms,
}; };
let renderTask = this.pdfPage.render(renderContext); let renderTask = this.pdfPage.render(renderContext);

View File

@ -37,6 +37,12 @@ const RendererType = {
SVG: 'svg', SVG: 'svg',
}; };
const TextLayerMode = {
DISABLE: 0,
ENABLE: 1,
ENABLE_ENHANCE: 2,
};
// Replaces {{arguments}} with their values. // Replaces {{arguments}} with their values.
function formatL10nValue(text, args) { function formatL10nValue(text, args) {
if (!args) { if (!args) {
@ -65,14 +71,6 @@ let NullL10n = {
}, },
}; };
/**
* Disables fullscreen support, and by extension Presentation Mode,
* in browsers which support the fullscreen API.
* @var {boolean}
*/
PDFJS.disableFullscreen = (PDFJS.disableFullscreen === undefined ?
false : PDFJS.disableFullscreen);
/** /**
* Enables CSS only zooming. * Enables CSS only zooming.
* @var {boolean} * @var {boolean}
@ -95,13 +93,6 @@ PDFJS.maxCanvasPixels = (PDFJS.maxCanvasPixels === undefined ?
PDFJS.disableHistory = (PDFJS.disableHistory === undefined ? PDFJS.disableHistory = (PDFJS.disableHistory === undefined ?
false : PDFJS.disableHistory); false : PDFJS.disableHistory);
/**
* Disables creation of the text layer that used for text selection and search.
* @var {boolean}
*/
PDFJS.disableTextLayer = (PDFJS.disableTextLayer === undefined ?
false : PDFJS.disableTextLayer);
if (typeof PDFJSDev === 'undefined' || if (typeof PDFJSDev === 'undefined' ||
!PDFJSDev.test('FIREFOX || MOZCENTRAL')) { !PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
/** /**
@ -110,7 +101,7 @@ if (typeof PDFJSDev === 'undefined' ||
*/ */
PDFJS.locale = PDFJS.locale =
(PDFJS.locale === undefined && typeof navigator !== 'undefined' ? (PDFJS.locale === undefined && typeof navigator !== 'undefined' ?
navigator.language : PDFJS.locale); navigator.language : PDFJS.locale) || 'en-US';
} }
/** /**
@ -677,6 +668,7 @@ export {
cloneObj, cloneObj,
PresentationModeState, PresentationModeState,
RendererType, RendererType,
TextLayerMode,
mozL10n, mozL10n,
NullL10n, NullL10n,
EventBus, EventBus,

View File

@ -0,0 +1,44 @@
/* Copyright 2018 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* 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.
*/
let compatibilityParams = Object.create(null);
if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
const userAgent =
(typeof navigator !== 'undefined' && navigator.userAgent) || '';
const isAndroid = /Android/.test(userAgent);
const isIE = /Trident/.test(userAgent);
const isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent);
// Disable fullscreen support for certain problematic configurations.
// Support: IE11+ (when embedded).
(function checkFullscreenSupport() {
if (isIE && window.parent !== window) {
compatibilityParams.disableFullscreen = true;
}
})();
// Limit canvas size to 5 mega-pixels on mobile.
// Support: Android, iOS
(function checkCanvasSizeLimitation() {
if (isIOS || isAndroid) {
compatibilityParams.maxCanvasPixels = 5242880;
}
})();
}
const viewerCompatibilityParams = Object.freeze(compatibilityParams);
export {
viewerCompatibilityParams,
};