From f2acc9fbc8d92b8b8ecaf397ec051ad24663eea9 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 27 Jun 2017 09:10:09 -0400 Subject: [PATCH] Bug 1376427 - Update pdf.js to version 1.8.497. r=bdahl --- browser/extensions/pdfjs/README.mozilla | 4 +- browser/extensions/pdfjs/content/build/pdf.js | 211 +++++++++++++----- .../pdfjs/content/build/pdf.worker.js | 116 +++++++--- .../extensions/pdfjs/content/web/viewer.js | 86 +++---- 4 files changed, 276 insertions(+), 141 deletions(-) diff --git a/browser/extensions/pdfjs/README.mozilla b/browser/extensions/pdfjs/README.mozilla index 27754a55af52..3c8b03a55677 100644 --- a/browser/extensions/pdfjs/README.mozilla +++ b/browser/extensions/pdfjs/README.mozilla @@ -1,5 +1,5 @@ This is the PDF.js project output, https://github.com/mozilla/pdf.js -Current extension version is: 1.8.480 +Current extension version is: 1.8.497 -Taken from upstream commit: 2f2e539b +Taken from upstream commit: f2fcf2a5 diff --git a/browser/extensions/pdfjs/content/build/pdf.js b/browser/extensions/pdfjs/content/build/pdf.js index 51b121440124..11e203825423 100644 --- a/browser/extensions/pdfjs/content/build/pdf.js +++ b/browser/extensions/pdfjs/content/build/pdf.js @@ -1128,7 +1128,8 @@ MessageHandler.prototype = { let startCapability = createPromiseCapability(); this.streamControllers[streamId] = { controller, - startCall: startCapability + startCall: startCapability, + isClosed: false }; this.postMessage({ sourceName, @@ -1155,6 +1156,7 @@ MessageHandler.prototype = { cancel: reason => { let cancelCapability = createPromiseCapability(); this.streamControllers[streamId].cancelCall = cancelCapability; + this.streamControllers[streamId].isClosed = true; this.postMessage({ sourceName, targetName, @@ -1284,9 +1286,15 @@ MessageHandler.prototype = { }); break; case 'enqueue': - this.streamControllers[data.streamId].controller.enqueue(data.chunk); + if (!this.streamControllers[data.streamId].isClosed) { + this.streamControllers[data.streamId].controller.enqueue(data.chunk); + } break; case 'close': + if (this.streamControllers[data.streamId].isClosed) { + break; + } + this.streamControllers[data.streamId].isClosed = true; this.streamControllers[data.streamId].controller.close(); deleteStreamController(); break; @@ -1299,6 +1307,9 @@ MessageHandler.prototype = { deleteStreamController(); break; case 'cancel': + if (!this.streamSinks[data.streamId]) { + break; + } resolveCall(this.streamSinks[data.streamId].onCancel, [data.reason]).then(() => { sendStreamResponse({ stream: 'cancel_complete', @@ -2371,6 +2382,7 @@ function getDocument(src, pdfDataRangeTransport, passwordCallback, progressCallb var params = {}; var rangeTransport = null; var worker = null; + var CMapReaderFactory = _dom_utils.DOMCMapReaderFactory; for (var key in source) { if (key === 'url' && typeof window !== 'undefined') { params[key] = new URL(source[key], window.location).href; @@ -2393,12 +2405,14 @@ function getDocument(src, pdfDataRangeTransport, passwordCallback, progressCallb (0, _util.error)('Invalid PDF binary data: either typed array, string or ' + 'array-like object is expected in the data property.'); } continue; + } else if (key === 'CMapReaderFactory') { + CMapReaderFactory = source[key]; + continue; } params[key] = source[key]; } params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE; params.ignoreErrors = params.stopAtErrors !== true; - var CMapReaderFactory = params.CMapReaderFactory || _dom_utils.DOMCMapReaderFactory; if (params.disableNativeImageDecoder !== undefined) { (0, _util.deprecated)('parameter disableNativeImageDecoder, ' + 'use nativeImageDecoderSupport instead'); } @@ -2743,12 +2757,40 @@ var PDFPageProxy = function PDFPageProxyClosure() { } return intentState.opListReadCapability.promise; }, - getTextContent: function PDFPageProxy_getTextContent(params) { - params = params || {}; - return this.transport.messageHandler.sendWithPromise('GetTextContent', { + streamTextContent(params = {}) { + const TEXT_CONTENT_CHUNK_SIZE = 100; + return this.transport.messageHandler.sendWithStream('GetTextContent', { pageIndex: this.pageNumber - 1, normalizeWhitespace: params.normalizeWhitespace === true, combineTextItems: params.disableCombineTextItems !== true + }, { + highWaterMark: TEXT_CONTENT_CHUNK_SIZE, + size(textContent) { + return textContent.items.length; + } + }); + }, + getTextContent: function PDFPageProxy_getTextContent(params) { + params = params || {}; + let readableStream = this.streamTextContent(params); + return new Promise(function (resolve, reject) { + function pump() { + reader.read().then(function ({ value, done }) { + if (done) { + resolve(textContent); + return; + } + _util.Util.extendObj(textContent.styles, value.styles); + _util.Util.appendToArray(textContent.items, value.items); + pump(); + }, reject); + } + let reader = readableStream.getReader(); + let textContent = { + items: [], + styles: Object.create(null) + }; + pump(); }); }, _destroy: function PDFPageProxy_destroy() { @@ -3656,8 +3698,8 @@ var _UnsupportedManager = function UnsupportedManagerClosure() { }(); var version, build; { - exports.version = version = '1.8.480'; - exports.build = build = '2f2e539b'; + exports.version = version = '1.8.497'; + exports.build = build = 'f2fcf2a5'; } exports.getDocument = getDocument; exports.LoopbackPort = LoopbackPort; @@ -3775,6 +3817,9 @@ var renderTextLayer = function renderTextLayerClosure() { } } task._textDivProperties.set(textDiv, textDivProperties); + if (task._textContentStream) { + task._layoutText(textDiv); + } if (task._enhanceTextSelection) { var angleCos = 1, angleSin = 0; @@ -3806,7 +3851,6 @@ var renderTextLayer = function renderTextLayerClosure() { if (task._canceled) { return; } - var textLayerFrag = task._container; var textDivs = task._textDivs; var capability = task._capability; var textDivsLength = textDivs.length; @@ -3815,39 +3859,10 @@ var renderTextLayer = function renderTextLayerClosure() { capability.resolve(); return; } - var canvas = document.createElement('canvas'); - canvas.mozOpaque = true; - var ctx = canvas.getContext('2d', { alpha: false }); - var lastFontSize; - var lastFontFamily; - for (var i = 0; i < textDivsLength; i++) { - var textDiv = textDivs[i]; - var textDivProperties = task._textDivProperties.get(textDiv); - if (textDivProperties.isWhitespace) { - continue; + if (!task._textContentStream) { + for (var i = 0; i < textDivsLength; i++) { + task._layoutText(textDivs[i]); } - var fontSize = textDiv.style.fontSize; - var fontFamily = textDiv.style.fontFamily; - if (fontSize !== lastFontSize || fontFamily !== lastFontFamily) { - ctx.font = fontSize + ' ' + fontFamily; - lastFontSize = fontSize; - lastFontFamily = fontFamily; - } - var width = ctx.measureText(textDiv.textContent).width; - textLayerFrag.appendChild(textDiv); - var transform = ''; - if (textDivProperties.canvasWidth !== 0 && width > 0) { - textDivProperties.scale = textDivProperties.canvasWidth / width; - transform = 'scaleX(' + textDivProperties.scale + ')'; - } - if (textDivProperties.angle !== 0) { - transform = 'rotate(' + textDivProperties.angle + 'deg) ' + transform; - } - if (transform !== '') { - textDivProperties.originalTransform = transform; - _dom_utils.CustomStyle.setProp('transform', textDiv, transform); - } - task._textDivProperties.set(textDiv, textDivProperties); } task._renderingDone = true; capability.resolve(); @@ -4077,24 +4092,34 @@ var renderTextLayer = function renderTextLayerClosure() { } }); } - function TextLayerRenderTask(textContent, container, viewport, textDivs, enhanceTextSelection) { + function TextLayerRenderTask({ textContent, textContentStream, container, viewport, textDivs, textContentItemsStr, enhanceTextSelection }) { this._textContent = textContent; + this._textContentStream = textContentStream; this._container = container; this._viewport = viewport; this._textDivs = textDivs || []; + this._textContentItemsStr = textContentItemsStr || []; + this._enhanceTextSelection = !!enhanceTextSelection; + this._reader = null; + this._layoutTextLastFontSize = null; + this._layoutTextLastFontFamily = null; + this._layoutTextCtx = null; this._textDivProperties = new WeakMap(); this._renderingDone = false; this._canceled = false; this._capability = (0, _util.createPromiseCapability)(); this._renderTimer = null; this._bounds = []; - this._enhanceTextSelection = !!enhanceTextSelection; } TextLayerRenderTask.prototype = { get promise() { return this._capability.promise; }, cancel: function TextLayer_cancel() { + if (this._reader) { + this._reader.cancel(); + this._reader = null; + } this._canceled = true; if (this._renderTimer !== null) { clearTimeout(this._renderTimer); @@ -4102,20 +4127,80 @@ var renderTextLayer = function renderTextLayerClosure() { } this._capability.reject('canceled'); }, + _processItems(items, styleCache) { + for (let i = 0, len = items.length; i < len; i++) { + this._textContentItemsStr.push(items[i].str); + appendText(this, items[i], styleCache); + } + }, + _layoutText(textDiv) { + let textLayerFrag = this._container; + let textDivProperties = this._textDivProperties.get(textDiv); + if (textDivProperties.isWhitespace) { + return; + } + let fontSize = textDiv.style.fontSize; + let fontFamily = textDiv.style.fontFamily; + if (fontSize !== this._layoutTextLastFontSize || fontFamily !== this._layoutTextLastFontFamily) { + this._layoutTextCtx.font = fontSize + ' ' + fontFamily; + this._lastFontSize = fontSize; + this._lastFontFamily = fontFamily; + } + let width = this._layoutTextCtx.measureText(textDiv.textContent).width; + let transform = ''; + if (textDivProperties.canvasWidth !== 0 && width > 0) { + textDivProperties.scale = textDivProperties.canvasWidth / width; + transform = 'scaleX(' + textDivProperties.scale + ')'; + } + if (textDivProperties.angle !== 0) { + transform = 'rotate(' + textDivProperties.angle + 'deg) ' + transform; + } + if (transform !== '') { + textDivProperties.originalTransform = transform; + _dom_utils.CustomStyle.setProp('transform', textDiv, transform); + } + this._textDivProperties.set(textDiv, textDivProperties); + textLayerFrag.appendChild(textDiv); + }, _render: function TextLayer_render(timeout) { - var textItems = this._textContent.items; - var textStyles = this._textContent.styles; - for (var i = 0, len = textItems.length; i < len; i++) { - appendText(this, textItems[i], textStyles); - } - if (!timeout) { - render(this); + let capability = (0, _util.createPromiseCapability)(); + let styleCache = Object.create(null); + let canvas = document.createElement('canvas'); + canvas.mozOpaque = true; + this._layoutTextCtx = canvas.getContext('2d', { alpha: false }); + if (this._textContent) { + let textItems = this._textContent.items; + let textStyles = this._textContent.styles; + this._processItems(textItems, textStyles); + capability.resolve(); + } else if (this._textContentStream) { + let pump = () => { + this._reader.read().then(({ value, done }) => { + if (done) { + capability.resolve(); + return; + } + _util.Util.extendObj(styleCache, value.styles); + this._processItems(value.items, styleCache); + pump(); + }, capability.reject); + }; + this._reader = this._textContentStream.getReader(); + pump(); } else { - this._renderTimer = setTimeout(() => { - render(this); - this._renderTimer = null; - }, timeout); + throw new Error('Neither "textContent" nor "textContentStream"' + ' parameters specified.'); } + capability.promise.then(() => { + styleCache = null; + if (!timeout) { + render(this); + } else { + this._renderTimer = setTimeout(() => { + render(this); + this._renderTimer = null; + }, timeout); + } + }, this._capability.reject); }, expandTextDivs: function TextLayer_expandTextDivs(expandDivs) { if (!this._enhanceTextSelection || !this._renderingDone) { @@ -4168,7 +4253,15 @@ var renderTextLayer = function renderTextLayerClosure() { } }; function renderTextLayer(renderParameters) { - var task = new TextLayerRenderTask(renderParameters.textContent, renderParameters.container, renderParameters.viewport, renderParameters.textDivs, renderParameters.enhanceTextSelection); + var task = new TextLayerRenderTask({ + textContent: renderParameters.textContent, + textContentStream: renderParameters.textContentStream, + container: renderParameters.container, + viewport: renderParameters.viewport, + textDivs: renderParameters.textDivs, + textContentItemsStr: renderParameters.textContentItemsStr, + enhanceTextSelection: renderParameters.enhanceTextSelection + }); task._render(renderParameters.timeout); return task; } @@ -4659,8 +4752,8 @@ if (!_util.globalScope.PDFJS) { } var PDFJS = _util.globalScope.PDFJS; { - PDFJS.version = '1.8.480'; - PDFJS.build = '2f2e539b'; + PDFJS.version = '1.8.497'; + PDFJS.build = 'f2fcf2a5'; } PDFJS.pdfBug = false; if (PDFJS.verbosity !== undefined) { @@ -10007,8 +10100,8 @@ exports.TilingPattern = TilingPattern; "use strict"; -var pdfjsVersion = '1.8.480'; -var pdfjsBuild = '2f2e539b'; +var pdfjsVersion = '1.8.497'; +var pdfjsBuild = 'f2fcf2a5'; var pdfjsSharedUtil = __w_pdfjs_require__(0); var pdfjsDisplayGlobal = __w_pdfjs_require__(8); var pdfjsDisplayAPI = __w_pdfjs_require__(3); diff --git a/browser/extensions/pdfjs/content/build/pdf.worker.js b/browser/extensions/pdfjs/content/build/pdf.worker.js index 16962fe4c7a6..d0bb1f4052a7 100644 --- a/browser/extensions/pdfjs/content/build/pdf.worker.js +++ b/browser/extensions/pdfjs/content/build/pdf.worker.js @@ -1128,7 +1128,8 @@ MessageHandler.prototype = { let startCapability = createPromiseCapability(); this.streamControllers[streamId] = { controller, - startCall: startCapability + startCall: startCapability, + isClosed: false }; this.postMessage({ sourceName, @@ -1155,6 +1156,7 @@ MessageHandler.prototype = { cancel: reason => { let cancelCapability = createPromiseCapability(); this.streamControllers[streamId].cancelCall = cancelCapability; + this.streamControllers[streamId].isClosed = true; this.postMessage({ sourceName, targetName, @@ -1284,9 +1286,15 @@ MessageHandler.prototype = { }); break; case 'enqueue': - this.streamControllers[data.streamId].controller.enqueue(data.chunk); + if (!this.streamControllers[data.streamId].isClosed) { + this.streamControllers[data.streamId].controller.enqueue(data.chunk); + } break; case 'close': + if (this.streamControllers[data.streamId].isClosed) { + break; + } + this.streamControllers[data.streamId].isClosed = true; this.streamControllers[data.streamId].controller.close(); deleteStreamController(); break; @@ -1299,6 +1307,9 @@ MessageHandler.prototype = { deleteStreamController(); break; case 'cancel': + if (!this.streamSinks[data.streamId]) { + break; + } resolveCall(this.streamSinks[data.streamId].onCancel, [data.reason]).then(() => { sendStreamResponse({ stream: 'cancel_complete', @@ -17476,7 +17487,7 @@ var PartialEvaluator = function PartialEvaluatorClosure() { throw reason; }); }, - getTextContent({ stream, task, resources, stateManager = null, normalizeWhitespace = false, combineTextItems = false }) { + getTextContent({ stream, task, resources, stateManager = null, normalizeWhitespace = false, combineTextItems = false, sink, seenStyles = Object.create(null) }) { resources = resources || _primitives.Dict.empty; stateManager = stateManager || new StateManager(new TextState()); var WhitespaceRegexp = /\s/g; @@ -17507,7 +17518,7 @@ var PartialEvaluator = function PartialEvaluatorClosure() { var self = this; var xref = this.xref; var xobjs = null; - var xobjsCache = Object.create(null); + var skipEmptyXObjs = Object.create(null); var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); var textState; function ensureTextContentItem() { @@ -17515,7 +17526,8 @@ var PartialEvaluator = function PartialEvaluatorClosure() { return textContentItem; } var font = textState.font; - if (!(font.loadedName in textContent.styles)) { + if (!(font.loadedName in seenStyles)) { + seenStyles[font.loadedName] = true; textContent.styles[font.loadedName] = { fontFamily: font.fallbackName, ascent: font.ascent, @@ -17670,10 +17682,19 @@ var PartialEvaluator = function PartialEvaluatorClosure() { textContentItem.initialized = false; textContentItem.str.length = 0; } + function enqueueChunk() { + let length = textContent.items.length; + if (length > 0) { + sink.enqueue(textContent, length); + textContent.items = []; + textContent.styles = Object.create(null); + } + } var timeSlotManager = new TimeSlotManager(); return new Promise(function promiseBody(resolve, reject) { - var next = function (promise) { - promise.then(function () { + let next = function (promise) { + enqueueChunk(); + Promise.all([promise, sink.ready]).then(function () { try { promiseBody(resolve, reject); } catch (ex) { @@ -17828,11 +17849,7 @@ var PartialEvaluator = function PartialEvaluatorClosure() { xobjs = resources.get('XObject') || _primitives.Dict.empty; } var name = args[0].name; - if (xobjsCache.key === name) { - if (xobjsCache.texts) { - _util.Util.appendToArray(textContent.items, xobjsCache.texts.items); - _util.Util.extendObj(textContent.styles, xobjsCache.texts.styles); - } + if (name in skipEmptyXObjs) { break; } var xobj = xobjs.get(name); @@ -17843,8 +17860,7 @@ var PartialEvaluator = function PartialEvaluatorClosure() { var type = xobj.dict.get('Subtype'); (0, _util.assert)((0, _primitives.isName)(type), 'XObject should have a Name subtype'); if (type.name !== 'Form') { - xobjsCache.key = name; - xobjsCache.texts = null; + skipEmptyXObjs[name] = true; break; } var currentState = stateManager.state.clone(); @@ -17853,18 +17869,33 @@ var PartialEvaluator = function PartialEvaluatorClosure() { if ((0, _util.isArray)(matrix) && matrix.length === 6) { xObjStateManager.transform(matrix); } + enqueueChunk(); + let sinkWrapper = { + enqueueInvoked: false, + enqueue(chunk, size) { + this.enqueueInvoked = true; + sink.enqueue(chunk, size); + }, + get desiredSize() { + return sink.desiredSize; + }, + get ready() { + return sink.ready; + } + }; next(self.getTextContent({ stream: xobj, task, resources: xobj.dict.get('Resources') || resources, stateManager: xObjStateManager, normalizeWhitespace, - combineTextItems - }).then(function (formTextContent) { - _util.Util.appendToArray(textContent.items, formTextContent.items); - _util.Util.extendObj(textContent.styles, formTextContent.styles); - xobjsCache.key = name; - xobjsCache.texts = formTextContent; + combineTextItems, + sink: sinkWrapper, + seenStyles + }).then(function () { + if (!sinkWrapper.enqueueInvoked) { + skipEmptyXObjs[name] = true; + } })); return; case _util.OPS.setGState: @@ -17887,18 +17918,24 @@ var PartialEvaluator = function PartialEvaluatorClosure() { } break; } + if (textContent.items.length >= sink.desiredSize) { + stop = true; + break; + } } if (stop) { next(deferred); return; } flushTextContentItem(); - resolve(textContent); + enqueueChunk(); + resolve(); }).catch(reason => { if (this.options.ignoreErrors) { (0, _util.warn)('getTextContent - ignoring errors during task: ' + task.name); flushTextContentItem(); - return textContent; + enqueueChunk(); + return; } throw reason; }); @@ -24126,27 +24163,31 @@ var WorkerMessageHandler = { }); }); }, this); - handler.on('GetTextContent', function wphExtractText(data) { + handler.on('GetTextContent', function wphExtractText(data, sink) { var pageIndex = data.pageIndex; - return pdfManager.getPage(pageIndex).then(function (page) { + sink.onPull = function (desiredSize) {}; + sink.onCancel = function (reason) {}; + pdfManager.getPage(pageIndex).then(function (page) { var task = new WorkerTask('GetTextContent: page ' + pageIndex); startWorkerTask(task); var pageNum = pageIndex + 1; var start = Date.now(); - return page.extractTextContent({ + page.extractTextContent({ handler, task, + sink, normalizeWhitespace: data.normalizeWhitespace, combineTextItems: data.combineTextItems - }).then(function (textContent) { + }).then(function () { finishWorkerTask(task); (0, _util.info)('text indexing: page=' + pageNum + ' - time=' + (Date.now() - start) + 'ms'); - return textContent; + sink.close(); }, function (reason) { finishWorkerTask(task); if (task.terminated) { return; } + sink.error(reason); throw reason; }); }); @@ -29061,7 +29102,7 @@ var Page = function PageClosure() { }); }); }, - extractTextContent({ handler, task, normalizeWhitespace, combineTextItems }) { + extractTextContent({ handler, task, normalizeWhitespace, sink, combineTextItems }) { var contentStreamPromise = this.pdfManager.ensure(this, 'getContentStream'); var resourcesPromise = this.loadResources(['ExtGState', 'XObject', 'Font']); var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]); @@ -29081,7 +29122,8 @@ var Page = function PageClosure() { task, resources: this.resources, normalizeWhitespace, - combineTextItems + combineTextItems, + sink }); }); }, @@ -30512,24 +30554,24 @@ var Font = function FontClosure() { type = 'Type1'; } } else if (isOpenTypeFile(file)) { - type = subtype = 'OpenType'; + subtype = 'OpenType'; } } if (subtype === 'CIDFontType0C' && type !== 'CIDFontType0') { type = 'CIDFontType0'; } - if (subtype === 'OpenType') { - type = 'OpenType'; - } if (type === 'CIDFontType0') { if (isType1File(file)) { subtype = 'CIDFontType0'; } else if (isOpenTypeFile(file)) { - type = subtype = 'OpenType'; + subtype = 'OpenType'; } else { subtype = 'CIDFontType0C'; } } + if (subtype === 'OpenType' && type !== 'OpenType') { + type = 'OpenType'; + } var data; switch (type) { case 'MMType1': @@ -31672,7 +31714,7 @@ var Font = function FontClosure() { } var isTrueType = !tables['CFF ']; if (!isTrueType) { - if (header.version === 'OTTO' && !properties.composite || !tables['head'] || !tables['hhea'] || !tables['maxp'] || !tables['post']) { + if (header.version === 'OTTO' && !(properties.composite && properties.cidToGidMap) || !tables['head'] || !tables['hhea'] || !tables['maxp'] || !tables['post']) { cffFile = new _stream.Stream(tables['CFF '].data); cff = new CFFFont(cffFile, properties); adjustWidths(properties); @@ -39776,8 +39818,8 @@ exports.Type1Parser = Type1Parser; "use strict"; -var pdfjsVersion = '1.8.480'; -var pdfjsBuild = '2f2e539b'; +var pdfjsVersion = '1.8.497'; +var pdfjsBuild = 'f2fcf2a5'; var pdfjsCoreWorker = __w_pdfjs_require__(17); ; exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler; diff --git a/browser/extensions/pdfjs/content/web/viewer.js b/browser/extensions/pdfjs/content/web/viewer.js index cb759baed5e7..eff47cd73ecb 100644 --- a/browser/extensions/pdfjs/content/web/viewer.js +++ b/browser/extensions/pdfjs/content/web/viewer.js @@ -4886,7 +4886,6 @@ var _dom_events = __webpack_require__(2); var _pdf_rendering_queue = __webpack_require__(3); -const TEXT_LAYER_RENDER_DELAY = 200; class PDFPageView { constructor(options) { let container = options.container; @@ -5190,10 +5189,9 @@ class PDFPageView { let resultPromise = paintTask.promise.then(function () { return finishPaintTask(null).then(function () { if (textLayer) { - pdfPage.getTextContent({ normalizeWhitespace: true }).then(function textContentResolved(textContent) { - textLayer.setTextContent(textContent); - textLayer.render(TEXT_LAYER_RENDER_DELAY); - }); + let readableStream = pdfPage.streamTextContent({ normalizeWhitespace: true }); + textLayer.setTextContentStream(readableStream); + textLayer.render(); } }); }, function (reason) { @@ -7392,6 +7390,8 @@ var TextLayerBuilder = function TextLayerBuilderClosure() { this.textLayerDiv = options.textLayerDiv; this.eventBus = options.eventBus || (0, _dom_events.getGlobalEventBus)(); this.textContent = null; + this.textContentItemsStr = []; + this.textContentStream = null; this.renderingDone = false; this.pageIdx = options.pageIndex; this.pageNumber = this.pageIdx + 1; @@ -7418,7 +7418,7 @@ var TextLayerBuilder = function TextLayerBuilderClosure() { }); }, render: function TextLayerBuilder_render(timeout) { - if (!this.textContent || this.renderingDone) { + if (!(this.textContent || this.textContentStream) || this.renderingDone) { return; } this.cancel(); @@ -7426,9 +7426,11 @@ var TextLayerBuilder = function TextLayerBuilderClosure() { var textLayerFrag = document.createDocumentFragment(); this.textLayerRenderTask = (0, _pdfjsLib.renderTextLayer)({ textContent: this.textContent, + textContentStream: this.textContentStream, container: textLayerFrag, viewport: this.viewport, textDivs: this.textDivs, + textContentItemsStr: this.textContentItemsStr, timeout, enhanceTextSelection: this.enhanceTextSelection }); @@ -7444,6 +7446,10 @@ var TextLayerBuilder = function TextLayerBuilderClosure() { this.textLayerRenderTask = null; } }, + setTextContentStream(readableStream) { + this.cancel(); + this.textContentStream = readableStream; + }, setTextContent: function TextLayerBuilder_setTextContent(textContent) { this.cancel(); this.textContent = textContent; @@ -7451,8 +7457,8 @@ var TextLayerBuilder = function TextLayerBuilderClosure() { convertMatches: function TextLayerBuilder_convertMatches(matches, matchesLength) { var i = 0; var iIndex = 0; - var bidiTexts = this.textContent.items; - var end = bidiTexts.length - 1; + let textContentItemsStr = this.textContentItemsStr; + var end = textContentItemsStr.length - 1; var queryLen = this.findController === null ? 0 : this.findController.state.query.length; var ret = []; if (!matches) { @@ -7460,11 +7466,11 @@ var TextLayerBuilder = function TextLayerBuilderClosure() { } for (var m = 0, len = matches.length; m < len; m++) { var matchIdx = matches[m]; - while (i !== end && matchIdx >= iIndex + bidiTexts[i].str.length) { - iIndex += bidiTexts[i].str.length; + while (i !== end && matchIdx >= iIndex + textContentItemsStr[i].length) { + iIndex += textContentItemsStr[i].length; i++; } - if (i === bidiTexts.length) { + if (i === textContentItemsStr.length) { console.error('Could not find a matching mapping'); } var match = { @@ -7478,8 +7484,8 @@ var TextLayerBuilder = function TextLayerBuilderClosure() { } else { matchIdx += queryLen; } - while (i !== end && matchIdx > iIndex + bidiTexts[i].str.length) { - iIndex += bidiTexts[i].str.length; + while (i !== end && matchIdx > iIndex + textContentItemsStr[i].length) { + iIndex += textContentItemsStr[i].length; i++; } match.end = { @@ -7494,7 +7500,7 @@ var TextLayerBuilder = function TextLayerBuilderClosure() { if (matches.length === 0) { return; } - var bidiTexts = this.textContent.items; + let textContentItemsStr = this.textContentItemsStr; var textDivs = this.textDivs; var prevEnd = null; var pageIdx = this.pageIdx; @@ -7512,7 +7518,7 @@ var TextLayerBuilder = function TextLayerBuilderClosure() { } function appendTextToDiv(divIdx, fromOffset, toOffset, className) { var div = textDivs[divIdx]; - var content = bidiTexts[divIdx].str.substring(fromOffset, toOffset); + var content = textContentItemsStr[divIdx].substring(fromOffset, toOffset); var node = document.createTextNode(content); if (className) { var span = document.createElement('span'); @@ -7569,14 +7575,14 @@ var TextLayerBuilder = function TextLayerBuilderClosure() { } var matches = this.matches; var textDivs = this.textDivs; - var bidiTexts = this.textContent.items; + let textContentItemsStr = this.textContentItemsStr; var clearedUntilDivIdx = -1; for (var i = 0, len = matches.length; i < len; i++) { var match = matches[i]; var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx); for (var n = begin, end = match.end.divIdx; n <= end; n++) { var div = textDivs[n]; - div.textContent = bidiTexts[n].str; + div.textContent = textContentItemsStr[n]; div.className = ''; } clearedUntilDivIdx = match.end.divIdx + 1; @@ -7689,9 +7695,8 @@ class Toolbar { this._updateUIState(true); } _bindListeners() { - let eventBus = this.eventBus; + let { eventBus, items } = this; let self = this; - let items = this.items; items.previous.addEventListener('click', function () { eventBus.dispatch('previouspage'); }); @@ -7748,31 +7753,9 @@ class Toolbar { if (!this._wasLocalized) { return; } - let selectScaleOption = (value, scale) => { - let customScale = Math.round(scale * 10000) / 100; - this.l10n.get('page_scale_percent', { scale: customScale }, '{{scale}}%').then(msg => { - let options = items.scaleSelect.options; - let predefinedValueFound = false; - for (let i = 0, ii = options.length; i < ii; i++) { - let option = options[i]; - if (option.value !== value) { - option.selected = false; - continue; - } - option.selected = true; - predefinedValueFound = true; - } - if (!predefinedValueFound) { - items.customScaleOption.textContent = msg; - items.customScaleOption.selected = true; - } - }); - }; - let pageNumber = this.pageNumber; + let { pageNumber, pagesCount, items } = this; let scaleValue = (this.pageScaleValue || this.pageScale).toString(); let scale = this.pageScale; - let items = this.items; - let pagesCount = this.pagesCount; if (resetNumPages) { if (this.hasPageLabels) { items.pageNumber.type = 'text'; @@ -7799,7 +7782,24 @@ class Toolbar { items.next.disabled = pageNumber >= pagesCount; items.zoomOut.disabled = scale <= _ui_utils.MIN_SCALE; items.zoomIn.disabled = scale >= _ui_utils.MAX_SCALE; - selectScaleOption(scaleValue, scale); + let customScale = Math.round(scale * 10000) / 100; + this.l10n.get('page_scale_percent', { scale: customScale }, '{{scale}}%').then(msg => { + let options = items.scaleSelect.options; + let predefinedValueFound = false; + for (let i = 0, ii = options.length; i < ii; i++) { + let option = options[i]; + if (option.value !== scaleValue) { + option.selected = false; + continue; + } + option.selected = true; + predefinedValueFound = true; + } + if (!predefinedValueFound) { + items.customScaleOption.textContent = msg; + items.customScaleOption.selected = true; + } + }); } updateLoadingIndicatorState(loading = false) { let pageNumberInput = this.items.pageNumber;