diff --git a/examples/node/domstubs.js b/examples/node/domstubs.js index 4918a4af9..5eb186b8d 100644 --- a/examples/node/domstubs.js +++ b/examples/node/domstubs.js @@ -1,17 +1,6 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ -var sheet = { - cssRules: [], - insertRule: function(rule) { - this.cssRules.push(rule); - }, -}; - -var style = { - sheet: sheet, -}; - function xmlEncode(s){ var i = 0, ch; s = String(s); @@ -75,6 +64,15 @@ function DOMElement(name) { this.childNodes = []; this.attributes = {}; this.textContent = ''; + + if (name === 'style') { + this.sheet = { + cssRules: [], + insertRule: function (rule) { + this.cssRules.push(rule); + }, + }; + } } DOMElement.prototype = { @@ -125,14 +123,23 @@ DOMElement.prototype = { global.document = { childNodes : [], - getElementById: function (id) { - if (id === 'PDFJS_FONT_STYLE_TAG') { - return style; - } + get documentElement() { + return this; }, createElementNS: function (NS, element) { var elObject = new DOMElement(element); return elObject; }, + + createElement: function (element) { + return this.createElementNS('', element); + }, + + getElementsByTagName: function (element) { + if (element === 'head') { + return [this.head || (this.head = new DOMElement('head'))]; + } + return []; + } }; diff --git a/src/core/evaluator.js b/src/core/evaluator.js index 51ff19741..7e80ecf42 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -529,7 +529,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { // Keep track of each font we translated so the caller can // load them asynchronously before calling display on a page. - font.loadedName = 'g_font_' + (fontRefIsDict ? + font.loadedName = 'g_' + this.pdfManager.docId + '_f' + (fontRefIsDict ? fontName.replace(/\W/g, '') : fontID); font.translated = fontCapability.promise; diff --git a/src/core/pdf_manager.js b/src/core/pdf_manager.js index 7fbe57732..90e3d78e2 100644 --- a/src/core/pdf_manager.js +++ b/src/core/pdf_manager.js @@ -24,6 +24,10 @@ var BasePdfManager = (function BasePdfManagerClosure() { } BasePdfManager.prototype = { + get docId() { + return this._docId; + }, + onLoadedStream: function BasePdfManager_onLoadedStream() { throw new NotImplementedException(); }, @@ -85,7 +89,8 @@ var BasePdfManager = (function BasePdfManagerClosure() { })(); var LocalPdfManager = (function LocalPdfManagerClosure() { - function LocalPdfManager(data, password) { + function LocalPdfManager(docId, data, password) { + this._docId = docId; var stream = new Stream(data); this.pdfDocument = new PDFDocument(this, stream, password); this._loadedStreamCapability = createPromiseCapability(); @@ -136,8 +141,8 @@ var LocalPdfManager = (function LocalPdfManagerClosure() { })(); var NetworkPdfManager = (function NetworkPdfManagerClosure() { - function NetworkPdfManager(args, msgHandler) { - + function NetworkPdfManager(docId, args, msgHandler) { + this._docId = docId; this.msgHandler = msgHandler; var params = { diff --git a/src/core/worker.js b/src/core/worker.js index 8474e97a9..08fa18981 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -92,9 +92,9 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = { var cancelXHRs = null; var WorkerTasks = []; - var mainHandlerName = data.docId; + var docId = data.docId; var workerHandlerName = data.docId + '_worker'; - var handler = new MessageHandler(workerHandlerName, mainHandlerName, port); + var handler = new MessageHandler(workerHandlerName, docId, port); function ensureNotTerminated() { if (terminated) { @@ -153,7 +153,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = { var disableRange = data.disableRange; if (source.data) { try { - pdfManager = new LocalPdfManager(source.data, source.password); + pdfManager = new LocalPdfManager(docId, source.data, source.password); pdfManagerCapability.resolve(pdfManager); } catch (ex) { pdfManagerCapability.reject(ex); @@ -161,7 +161,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = { return pdfManagerCapability.promise; } else if (source.chunkedViewerLoading) { try { - pdfManager = new NetworkPdfManager(source, handler); + pdfManager = new NetworkPdfManager(docId, source, handler); pdfManagerCapability.resolve(pdfManager); } catch (ex) { pdfManagerCapability.reject(ex); @@ -218,7 +218,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = { } try { - pdfManager = new NetworkPdfManager(source, handler); + pdfManager = new NetworkPdfManager(docId, source, handler); pdfManagerCapability.resolve(pdfManager); } catch (ex) { pdfManagerCapability.reject(ex); @@ -263,7 +263,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = { // the data is array, instantiating directly from it try { - pdfManager = new LocalPdfManager(pdfFile, source.password); + pdfManager = new LocalPdfManager(docId, pdfFile, source.password); pdfManagerCapability.resolve(pdfManager); } catch (ex) { pdfManagerCapability.reject(ex); diff --git a/src/display/api.js b/src/display/api.js index 68eeab9a2..970481dd9 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -1299,6 +1299,7 @@ var WorkerTransport = (function WorkerTransportClosure() { this.loadingTask = loadingTask; this.pdfDataRangeTransport = pdfDataRangeTransport; this.commonObjs = new PDFObjects(); + this.fontLoader = new FontLoader(loadingTask.docId); this.destroyed = false; this.destroyCapability = null; @@ -1333,7 +1334,7 @@ var WorkerTransport = (function WorkerTransportClosure() { var terminated = this.messageHandler.sendWithPromise('Terminate', null); waitOn.push(terminated); Promise.all(waitOn).then(function () { - FontLoader.clear(); + self.fontLoader.clear(); if (self.pdfDataRangeTransport) { self.pdfDataRangeTransport.abort(); self.pdfDataRangeTransport = null; @@ -1489,7 +1490,7 @@ var WorkerTransport = (function WorkerTransportClosure() { font = new FontFaceObject(exportedData); } - FontLoader.bind( + this.fontLoader.bind( [font], function fontReady(fontObjs) { this.commonObjs.resolve(id, font); @@ -1697,7 +1698,7 @@ var WorkerTransport = (function WorkerTransportClosure() { } } this.commonObjs.clear(); - FontLoader.clear(); + this.fontLoader.clear(); }.bind(this)); } }; diff --git a/src/display/font_loader.js b/src/display/font_loader.js index b800bf012..73f902fba 100644 --- a/src/display/font_loader.js +++ b/src/display/font_loader.js @@ -19,12 +19,24 @@ PDFJS.disableFontFace = false; -var FontLoader = { +function FontLoader(docId) { + this.docId = docId; + this.styleElement = null; +//#if !(MOZCENTRAL) + this.nativeFontFaces = []; + this.loadTestFontId = 0; + this.loadingContext = { + requests: [], + nextRequestId: 0 + }; +//#endif +} +FontLoader.prototype = { insertRule: function fontLoaderInsertRule(rule) { - var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG'); + var styleElement = this.styleElement; if (!styleElement) { - styleElement = document.createElement('style'); - styleElement.id = 'PDFJS_FONT_STYLE_TAG'; + styleElement = this.styleElement = document.createElement('style'); + styleElement.id = 'PDFJS_FONT_STYLE_TAG_' + this.docId; document.documentElement.getElementsByTagName('head')[0].appendChild( styleElement); } @@ -34,7 +46,7 @@ var FontLoader = { }, clear: function fontLoaderClear() { - var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG'); + var styleElement = this.styleElement; if (styleElement) { styleElement.parentNode.removeChild(styleElement); } @@ -75,49 +87,6 @@ var FontLoader = { )); }, - get isEvalSupported() { - var evalSupport = false; - if (PDFJS.isEvalSupported) { - try { - /* jshint evil: true */ - new Function(''); - evalSupport = true; - } catch (e) {} - } - return shadow(this, 'isEvalSupported', evalSupport); - }, - - loadTestFontId: 0, - - loadingContext: { - requests: [], - nextRequestId: 0 - }, - - isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() { - if (isWorker) { - return false; - } - - // User agent string sniffing is bad, but there is no reliable way to tell - // if font is fully loaded and ready to be used with canvas. - var userAgent = window.navigator.userAgent; - var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent); - if (m && m[1] >= 14) { - return true; - } - // TODO other browsers - if (userAgent === 'node') { - return true; - } - return false; - })(), - - nativeFontFaces: [], - - isFontLoadingAPISupported: (!isWorker && typeof document !== 'undefined' && - !!document.fonts), - addNativeFontFace: function fontLoader_addNativeFontFace(nativeFontFace) { this.nativeFontFaces.push(nativeFontFace); document.fonts.add(nativeFontFace); @@ -146,27 +115,29 @@ var FontLoader = { } font.attached = true; - if (this.isFontLoadingAPISupported) { + if (FontLoader.isFontLoadingAPISupported) { var nativeFontFace = font.createNativeFontFace(); if (nativeFontFace) { + this.addNativeFontFace(nativeFontFace); fontLoadPromises.push(getNativeFontPromise(nativeFontFace)); } } else { - var rule = font.bindDOM(); + var rule = font.createFontFaceRule(); if (rule) { + this.insertRule(rule); rules.push(rule); fontsToLoad.push(font); } } } - var request = FontLoader.queueLoadingCallback(callback); - if (this.isFontLoadingAPISupported) { + var request = this.queueLoadingCallback(callback); + if (FontLoader.isFontLoadingAPISupported) { Promise.all(fontLoadPromises).then(function() { request.complete(); }); - } else if (rules.length > 0 && !this.isSyncFontLoadingSupported) { - FontLoader.prepareFontLoadEvent(rules, fontsToLoad, request); + } else if (rules.length > 0 && !FontLoader.isSyncFontLoadingSupported) { + this.prepareFontLoadEvent(rules, fontsToLoad, request); } else { request.complete(); } @@ -184,7 +155,7 @@ var FontLoader = { } } - var context = FontLoader.loadingContext; + var context = this.loadingContext; var requestId = 'pdfjs-font-loading-' + (context.nextRequestId++); var request = { id: requestId, @@ -271,7 +242,7 @@ var FontLoader = { var url = 'url(data:font/opentype;base64,' + btoa(data) + ');'; var rule = '@font-face { font-family:"' + loadTestFontId + '";src:' + url + '}'; - FontLoader.insertRule(rule); + this.insertRule(rule); var names = []; for (i = 0, ii = fonts.length; i < ii; i++) { @@ -316,19 +287,56 @@ var FontLoader = { //} //#endif }; +//#if !(MOZCENTRAL) +FontLoader.isFontLoadingAPISupported = (!isWorker && + typeof document !== 'undefined' && !!document.fonts); +//#endif +//#if !(MOZCENTRAL || CHROME) +Object.defineProperty(FontLoader, 'isSyncFontLoadingSupported', { + get: function () { + var supported = false; + + // User agent string sniffing is bad, but there is no reliable way to tell + // if font is fully loaded and ready to be used with canvas. + var userAgent = window.navigator.userAgent; + var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent); + if (m && m[1] >= 14) { + supported = true; + } + // TODO other browsers + if (userAgent === 'node') { + supported = true; + } + return shadow(FontLoader, 'isSyncFontLoadingSupported', supported); + }, + enumerable: true, + configurable: true +}); +//#endif var FontFaceObject = (function FontFaceObjectClosure() { - function FontFaceObject(name, file, properties) { + function FontFaceObject(translatedData) { this.compiledGlyphs = {}; - if (arguments.length === 1) { - // importing translated data - var data = arguments[0]; - for (var i in data) { - this[i] = data[i]; - } - return; + // importing translated data + for (var i in translatedData) { + this[i] = translatedData[i]; } } + Object.defineProperty(FontFaceObject, 'isEvalSupported', { + get: function () { + var evalSupport = false; + if (PDFJS.isEvalSupported) { + try { + /* jshint evil: true */ + new Function(''); + evalSupport = true; + } catch (e) {} + } + return shadow(this, 'isEvalSupported', evalSupport); + }, + enumerable: true, + configurable: true + }); FontFaceObject.prototype = { //#if !(MOZCENTRAL) createNativeFontFace: function FontFaceObject_createNativeFontFace() { @@ -343,8 +351,6 @@ var FontFaceObject = (function FontFaceObjectClosure() { var nativeFontFace = new FontFace(this.loadedName, this.data, {}); - FontLoader.addNativeFontFace(nativeFontFace); - if (PDFJS.pdfBug && 'FontInspector' in globalScope && globalScope['FontInspector'].enabled) { globalScope['FontInspector'].fontAdded(this); @@ -353,7 +359,7 @@ var FontFaceObject = (function FontFaceObjectClosure() { }, //#endif - bindDOM: function FontFaceObject_bindDOM() { + createFontFaceRule: function FontFaceObject_createFontFaceRule() { if (!this.data) { return null; } @@ -370,7 +376,6 @@ var FontFaceObject = (function FontFaceObjectClosure() { var url = ('url(data:' + this.mimetype + ';base64,' + window.btoa(data) + ');'); var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}'; - FontLoader.insertRule(rule); if (PDFJS.pdfBug && 'FontInspector' in globalScope && globalScope['FontInspector'].enabled) { @@ -380,13 +385,14 @@ var FontFaceObject = (function FontFaceObjectClosure() { return rule; }, - getPathGenerator: function FontLoader_getPathGenerator(objs, character) { + getPathGenerator: + function FontFaceObject_getPathGenerator(objs, character) { if (!(character in this.compiledGlyphs)) { var cmds = objs.get(this.loadedName + '_path_' + character); var current, i, len; // If we can, compile cmds into JS for MAXIMUM SPEED - if (FontLoader.isEvalSupported) { + if (FontFaceObject.isEvalSupported) { var args, js = ''; for (i = 0, len = cmds.length; i < len; i++) { current = cmds[i];