From 96fff4cc74775f41121b13480370050e9e0407ab Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 17 Jan 2014 13:26:00 -0600 Subject: [PATCH 1/2] Refactors getTextContent return value --- src/core/evaluator.js | 34 +++++++++++++++------------------- test/driver.js | 2 +- web/pdf_find_controller.js | 4 +--- web/text_layer_builder.js | 10 +++++----- 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/core/evaluator.js b/src/core/evaluator.js index bdeb1af80..68126279a 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -597,24 +597,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { }, getTextContent: function PartialEvaluator_getTextContent( - stream, resources, state) { + stream, resources, textState) { - var bidiTexts; + textState = textState || new TextState(); + + var bidiTexts = []; var SPACE_FACTOR = 0.35; var MULTI_SPACE_FACTOR = 1.5; - var textState; - - if (!state) { - textState = new TextState(); - bidiTexts = []; - state = { - textState: textState, - bidiTexts: bidiTexts - }; - } else { - bidiTexts = state.bidiTexts; - textState = state.textState; - } var self = this; var xref = this.xref; @@ -734,11 +723,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { if ('Form' !== type.name) break; - state = this.getTextContent( + var formTexts = this.getTextContent( xobj, xobj.dict.get('Resources') || resources, - state + textState ); + Util.concatenateToArray(bidiTexts, formTexts); break; case OPS.setGState: var dictName = args[0]; @@ -758,7 +748,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { } // switch if (chunk !== '') { - var bidiText = PDFJS.bidi(chunk, -1, font.vertical); + var bidiResult = PDFJS.bidi(chunk, -1, font.vertical); + var bidiText = { + str: bidiResult.str, + dir: bidiResult.dir + }; var renderParams = textState.calcRenderParams(preprocessor.ctm); bidiText.x = renderParams.renderMatrix[4] - (textState.fontSize * renderParams.vScale * Math.sin(renderParams.angle)); @@ -775,13 +769,15 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { bidiText.x += renderParams.vScale / 2; bidiText.y -= renderParams.vScale; } + bidiText.angle = renderParams.angle; + bidiText.size = fontHeight; bidiTexts.push(bidiText); chunk = ''; } } // while - return state; + return bidiTexts; }, extractDataStructures: function diff --git a/test/driver.js b/test/driver.js index 6e936ad52..3d69dc4c2 100644 --- a/test/driver.js +++ b/test/driver.js @@ -210,7 +210,7 @@ SimpleTextLayerBuilder.prototype = { ctx.stroke(); ctx.fill(); ctx.restore(); - var textContent = this.textContent.bidiTexts[this.textCounter].str; + var textContent = this.textContent[this.textCounter].str; ctx.font = fontHeight + 'px ' + geom.fontFamily; ctx.fillStyle = 'black'; ctx.fillText(textContent, geom.x, geom.y); diff --git a/web/pdf_find_controller.js b/web/pdf_find_controller.js index 99b9849dc..99810ec80 100644 --- a/web/pdf_find_controller.js +++ b/web/pdf_find_controller.js @@ -150,9 +150,7 @@ var PDFFindController = { var self = this; function extractPageText(pageIndex) { self.pdfPageSource.pages[pageIndex].getTextContent().then( - function textContentResolved(data) { - // Build the find string. - var bidiTexts = data.bidiTexts; + function textContentResolved(bidiTexts) { var str = ''; for (var i = 0; i < bidiTexts.length; i++) { diff --git a/web/text_layer_builder.js b/web/text_layer_builder.js index 170aa638e..c2f8043ea 100644 --- a/web/text_layer_builder.js +++ b/web/text_layer_builder.js @@ -62,7 +62,7 @@ var TextLayerBuilder = function textLayerBuilder(options) { this.renderLayer = function textLayerBuilderRenderLayer() { var self = this; var textDivs = this.textDivs; - var bidiTexts = this.textContent.bidiTexts; + var bidiTexts = this.textContent; var textLayerDiv = this.textLayerDiv; var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); @@ -149,7 +149,7 @@ var TextLayerBuilder = function textLayerBuilder(options) { this.divContentDone = true; var textDivs = this.textDivs; - var bidiTexts = this.textContent.bidiTexts; + var bidiTexts = this.textContent; for (var i = 0; i < bidiTexts.length; i++) { var bidiText = bidiTexts[i]; @@ -181,7 +181,7 @@ var TextLayerBuilder = function textLayerBuilder(options) { this.convertMatches = function textLayerBuilderConvertMatches(matches) { var i = 0; var iIndex = 0; - var bidiTexts = this.textContent.bidiTexts; + var bidiTexts = this.textContent; var end = bidiTexts.length - 1; var queryLen = PDFFindController === null ? 0 : PDFFindController.state.query.length; @@ -240,7 +240,7 @@ var TextLayerBuilder = function textLayerBuilder(options) { return; } - var bidiTexts = this.textContent.bidiTexts; + var bidiTexts = this.textContent; var textDivs = this.textDivs; var prevEnd = null; var isSelectedPage = PDFFindController === null ? @@ -355,7 +355,7 @@ var TextLayerBuilder = function textLayerBuilder(options) { // Clear out all matches. var matches = this.matches; var textDivs = this.textDivs; - var bidiTexts = this.textContent.bidiTexts; + var bidiTexts = this.textContent; var clearedUntilDivIdx = -1; // Clear out all current matches. From 27573ddbad06e378b043d364c706ccf6d6dc90c8 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 21 Jan 2014 13:28:18 -0600 Subject: [PATCH 2/2] Minor fixes for the jsdocs and removing unused members. --- src/display/api.js | 164 +++++++++++++++++++++++++++------------------ 1 file changed, 100 insertions(+), 64 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index d8b9a5401..0b948c1e6 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -25,7 +25,7 @@ /** * The maximum allowed image size in total pixels e.g. width * height. Images * above this value will not be drawn. Use -1 for no limit. - * @var {Number} + * @var {number} */ PDFJS.maxImageSize = PDFJS.maxImageSize === undefined ? -1 : PDFJS.maxImageSize; @@ -33,7 +33,7 @@ PDFJS.maxImageSize = PDFJS.maxImageSize === undefined ? -1 : PDFJS.maxImageSize; * By default fonts are converted to OpenType fonts and loaded via font face * rules. If disabled, the font will be rendered using a built in font renderer * that constructs the glyphs with primitive path commands. - * @var {Boolean} + * @var {boolean} */ PDFJS.disableFontFace = PDFJS.disableFontFace === undefined ? false : PDFJS.disableFontFace; @@ -41,7 +41,7 @@ PDFJS.disableFontFace = PDFJS.disableFontFace === undefined ? /** * Path for image resources, mainly for annotation icons. Include trailing * slash. - * @var {String} + * @var {string} */ PDFJS.imageResourcesPath = PDFJS.imageResourcesPath === undefined ? '' : PDFJS.imageResourcesPath; @@ -50,7 +50,7 @@ PDFJS.imageResourcesPath = PDFJS.imageResourcesPath === undefined ? * Disable the web worker and run all code on the main thread. This will happen * automatically if the browser doesn't support workers or sending typed arrays * to workers. - * @var {Boolean} + * @var {boolean} */ PDFJS.disableWorker = PDFJS.disableWorker === undefined ? false : PDFJS.disableWorker; @@ -59,7 +59,7 @@ PDFJS.disableWorker = PDFJS.disableWorker === undefined ? * Path and filename of the worker file. Required when the worker is enabled in * development mode. If unspecified in the production build, the worker will be * loaded based on the location of the pdf.js file. - * @var {String} + * @var {string} */ PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc; @@ -67,7 +67,7 @@ PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc; * Disable range request loading of PDF files. When enabled and if the server * supports partial content requests then the PDF will be fetched in chunks. * Enabled (false) by default. - * @var {Boolean} + * @var {boolean} */ PDFJS.disableRange = PDFJS.disableRange === undefined ? false : PDFJS.disableRange; @@ -76,14 +76,14 @@ PDFJS.disableRange = PDFJS.disableRange === undefined ? * Disable pre-fetching of PDF file data. When range requests are enabled PDF.js * will automatically keep fetching more data even if it isn't needed to display * the current page. This default behavior can be disabled. - * @var {Boolean} + * @var {boolean} */ PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ? false : PDFJS.disableAutoFetch; /** * Enables special hooks for debugging PDF.js. - * @var {Boolean} + * @var {boolean} */ PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug; @@ -107,32 +107,38 @@ PDFJS.disableCreateObjectURL = PDFJS.disableCreateObjectURL === undefined ? * - errors * - warnings [default] * - infos - * @var {Number} + * @var {number} */ PDFJS.verbosity = PDFJS.verbosity === undefined ? PDFJS.VERBOSITY_LEVELS.warnings : PDFJS.verbosity; +/** + * Document initialization / loading parameters object. + * + * @typedef {Object} DocumentInitParameters + * @property {string} url - The URL of the PDF. + * @property {TypedArray} data - A typed array with PDF data. + * @property {Object} httpHeaders - Basic authentication headers. + * @property {boolean} withCredentials - Indicates whether or not cross-site + * Access-Control requests should be made using credentials such as cookies + * or authorization headers. The default is false. + * @property {string} password - For decrypting password-protected PDFs. + * @property {TypedArray} initialData - A typed array with the first portion or + * all of the pdf data. Used by the extension since some data is already + * loaded before the switch to range requests. + */ + /** * This is the main entry point for loading a PDF and interacting with it. * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR) * is used, which means it must follow the same origin rules that any XHR does * e.g. No cross domain requests without CORS. * - * @param {string|TypedAray|object} source Can be an url to where a PDF is - * located, a typed array (Uint8Array) already populated with data or - * and parameter object with the following possible fields: - * - url - The URL of the PDF. - * - data - A typed array with PDF data. - * - httpHeaders - Basic authentication headers. - * - withCredentials - Indicates whether or not cross-site Access-Control - * requests should be made using credentials such as - * cookies or authorization headers. The default is false. - * - password - For decrypting password-protected PDFs. - * - initialData - A typed array with the first portion or all of the pdf data. - * Used by the extension since some data is already loaded - * before the switch to range requests. + * @param {string|TypedArray|DocumentInitParameters} source Can be a url to + * where a PDF is located, a typed array (Uint8Array) already populated with + * data or parameter object. * - * @param {object} pdfDataRangeTransport is optional. It is used if you want + * @param {Object} pdfDataRangeTransport is optional. It is used if you want * to manually serve range requests for data in the PDF. See viewer.js for * an example of pdfDataRangeTransport's interface. * @@ -141,7 +147,8 @@ PDFJS.verbosity = PDFJS.verbosity === undefined ? * parameters: function that needs to be called with new password and reason * (see {PasswordResponses}). * - * @return {Promise} A promise that is resolved with {PDFDocumentProxy} object. + * @return {Promise} A promise that is resolved with {@link PDFDocumentProxy} + * object. */ PDFJS.getDocument = function getDocument(source, pdfDataRangeTransport, @@ -185,13 +192,14 @@ PDFJS.getDocument = function getDocument(source, /** * Proxy to a PDFDocument in the worker thread. Also, contains commonly used * properties that can be read synchronously. + * @class */ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { function PDFDocumentProxy(pdfInfo, transport) { this.pdfInfo = pdfInfo; this.transport = transport; } - PDFDocumentProxy.prototype = { + PDFDocumentProxy.prototype = /** @lends PDFDocumentProxy.prototype */ { /** * @return {number} Total number of pages the PDF contains. */ @@ -213,15 +221,16 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { return this.transport.embeddedFontsUsed; }, /** - * @param {number} The page number to get. The first page is 1. - * @return {Promise} A promise that is resolved with a {PDFPageProxy} + * @param {number} pageNumber The page number to get. The first page is 1. + * @return {Promise} A promise that is resolved with a {@link PDFPageProxy} * object. */ - getPage: function PDFDocumentProxy_getPage(number) { - return this.transport.getPage(number); + getPage: function PDFDocumentProxy_getPage(pageNumber) { + return this.transport.getPage(pageNumber); }, /** - * @param {object} Must have 'num' and 'gen' properties. + * @param {{num: number, gen: number}} ref The page reference. Must have + * the 'num' and 'gen' properties. * @return {Promise} A promise that is resolved with the page index that is * associated with the reference. */ @@ -246,7 +255,7 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { return promise; }, /** - * @return {Promise} A promise that is resolved with an {array} that is a + * @return {Promise} A promise that is resolved with an {Array} that is a * tree outline (if it has one) of the PDF. The tree is in the format of: * [ * { @@ -267,8 +276,8 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { return promise; }, /** - * @return {Promise} A promise that is resolved with an {object} that has - * info and metadata properties. Info is an {object} filled with anything + * @return {Promise} A promise that is resolved with an {Object} that has + * info and metadata properties. Info is an {Object} filled with anything * available in the information dictionary and similarly metadata is a * {Metadata} object with information from the metadata section of the PDF. */ @@ -282,11 +291,6 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { }); return promise; }, - isEncrypted: function PDFDocumentProxy_isEncrypted() { - var promise = new PDFJS.LegacyPromise(); - promise.resolve(this.pdfInfo.encrypted); - return promise; - }, /** * @return {Promise} A promise that is resolved with a TypedArray that has * the raw data from the PDF. @@ -303,9 +307,15 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { dataLoaded: function PDFDocumentProxy_dataLoaded() { return this.transport.dataLoaded(); }, + /** + * Cleans up resources allocated by the document, e.g. created @font-face. + */ cleanup: function PDFDocumentProxy_cleanup() { this.transport.startCleanup(); }, + /** + * Destroys current document instance and terminates worker. + */ destroy: function PDFDocumentProxy_destroy() { this.transport.destroy(); } @@ -313,6 +323,22 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { return PDFDocumentProxy; })(); +/** + * Page text content part. + * + * @typedef {Object} BidiText + * @property {string} str - text content. + * @property {string} dir - text direction: 'ttb', 'ltr' or 'rtl'. + * @property {number} x - x position of the text on the page. + * @property {number} y - y position of the text on the page. + * @property {number} angle - text rotation. + * @property {number} size - font size. + */ + +/** + * Proxy to a PDFPage in the worker thread. + * @class + */ var PDFPageProxy = (function PDFPageProxyClosure() { function PDFPageProxy(pageInfo, transport) { this.pageInfo = pageInfo; @@ -326,7 +352,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() { this.pendingDestroy = false; this.renderTasks = []; } - PDFPageProxy.prototype = { + PDFPageProxy.prototype = /** @lends PDFPageProxy.prototype */ { /** * @return {number} Page number of the page. First page is 1. */ @@ -340,14 +366,14 @@ var PDFPageProxy = (function PDFPageProxyClosure() { return this.pageInfo.rotate; }, /** - * @return {object} The reference that points to this page. It has 'num' and + * @return {Object} The reference that points to this page. It has 'num' and * 'gen' properties. */ get ref() { return this.pageInfo.ref; }, /** - * @return {array} An array of the visible portion of the PDF page in the + * @return {Array} An array of the visible portion of the PDF page in the * user space units - [x1, y1, x2, y2]. */ get view() { @@ -366,7 +392,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() { return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0); }, /** - * @return {Promise} A promise that is resolved with an {array} of the + * @return {Promise} A promise that is resolved with an {Array} of the * annotation objects. */ getAnnotations: function PDFPageProxy_getAnnotations() { @@ -380,7 +406,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() { }, /** * Begins the process of rendering a page to the desired context. - * @param {object} params A parameter object that supports: + * @param {Object} params A parameter object that supports: * { * canvasContext(required): A 2D context of a DOM Canvas object., * textLayer(optional): An object that has beginLayout, endLayout, and @@ -465,8 +491,8 @@ var PDFPageProxy = (function PDFPageProxyClosure() { return renderTask; }, /** - * @return {Promise} That is resolved with the a {string} that is the text - * content from the page. + * @return {Promise} That is resolved with the array of {@link BidiText} + * objects that represent the page text content. */ getTextContent: function PDFPageProxy_getTextContent() { var promise = new PDFJS.LegacyPromise(); @@ -479,18 +505,6 @@ var PDFPageProxy = (function PDFPageProxyClosure() { ); return promise; }, - /** - * Stub for future feature. - */ - getOperationList: function PDFPageProxy_getOperationList() { - var promise = new PDFJS.LegacyPromise(); - var operationList = { // not implemented - dependencyFontsID: null, - operatorList: null - }; - promise.resolve(operationList); - return promise; - }, /** * Destroys resources allocated by the page. */ @@ -501,6 +515,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() { /** * For internal use only. Attempts to clean up if rendering is in a state * where that's possible. + * @ignore */ _tryDestroy: function PDFPageProxy__destroy() { if (!this.pendingDestroy || @@ -516,12 +531,14 @@ var PDFPageProxy = (function PDFPageProxyClosure() { }, /** * For internal use only. + * @ignore */ _startRenderPage: function PDFPageProxy_startRenderPage(transparency) { this.displayReadyPromise.resolve(transparency); }, /** * For internal use only. + * @ignore */ _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk) { // Add the new chunk to the current operator list. @@ -544,8 +561,10 @@ var PDFPageProxy = (function PDFPageProxyClosure() { }; return PDFPageProxy; })(); + /** * For internal use only. + * @ignore */ var WorkerTransport = (function WorkerTransportClosure() { function WorkerTransport(workerInitializedPromise, workerReadyPromise, @@ -629,6 +648,7 @@ var WorkerTransport = (function WorkerTransportClosure() { this.pagePromises = []; var self = this; this.messageHandler.send('Terminate', null, function () { + FontLoader.clear(); if (self.worker) { self.worker.terminate(); } @@ -971,6 +991,7 @@ var WorkerTransport = (function WorkerTransportClosure() { * for fonts, images, rendering code and such. These objects might get processed * inside of a worker. The `PDFObjects` implements some basic functions to * manage these objects. + * @ignore */ var PDFObjects = (function PDFObjectsClosure() { function PDFObjects() { @@ -1069,24 +1090,39 @@ var PDFObjects = (function PDFObjectsClosure() { return PDFObjects; })(); +/** + * Allows controlling of the rendering tasks. + * @class + */ var RenderTask = (function RenderTaskClosure() { function RenderTask(internalRenderTask) { this.internalRenderTask = internalRenderTask; + /** + * Promise for rendering task completion. + * @type {Promise} + */ this.promise = new PDFJS.LegacyPromise(); } - /** - * Cancel the rendering task. If the task is curently rendering it will not be - * cancelled until graphics pauses with a timeout. The promise that this - * object extends will resolved when cancelled. - */ - RenderTask.prototype.cancel = function RenderTask_cancel() { - this.internalRenderTask.cancel(); + RenderTask.prototype = /** @lends RenderTask.prototype */ { + /** + * Cancels the rendering task. If the task is currently rendering it will + * not be cancelled until graphics pauses with a timeout. The promise that + * this object extends will resolved when cancelled. + */ + cancel: function RenderTask_cancel() { + this.internalRenderTask.cancel(); + this.reject(new Error('Rendering is cancelled')); + } }; return RenderTask; })(); +/** + * For internal use only. + * @ignore + */ var InternalRenderTask = (function InternalRenderTaskClosure() { function InternalRenderTask(callback, params, objs, commonObjs, operatorList,