From 56ccaea99b966e788793eacfac4acae42bf3141c Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 10 Nov 2015 09:45:03 -0600 Subject: [PATCH] Move text layer building logic into src/display/text_layer.js --- examples/acroforms/index.html | 1 + examples/helloworld/index.html | 1 + make.js | 1 + src/display/text_layer.js | 237 +++++++++++++++++++++++++++++++++ test/font/font_test.html | 1 + test/test_slave.html | 1 + test/unit/unit_test.html | 1 + web/text_layer_builder.js | 168 ++++------------------- web/viewer.html | 1 + 9 files changed, 268 insertions(+), 144 deletions(-) create mode 100644 src/display/text_layer.js diff --git a/examples/acroforms/index.html b/examples/acroforms/index.html index 1936ae1e1..d6c644f44 100644 --- a/examples/acroforms/index.html +++ b/examples/acroforms/index.html @@ -13,6 +13,7 @@ + + + diff --git a/test/test_slave.html b/test/test_slave.html index 3677b4e06..7236914d5 100644 --- a/test/test_slave.html +++ b/test/test_slave.html @@ -27,6 +27,7 @@ limitations under the License. + diff --git a/test/unit/unit_test.html b/test/unit/unit_test.html index 687bd5201..fcce65d19 100644 --- a/test/unit/unit_test.html +++ b/test/unit/unit_test.html @@ -38,6 +38,7 @@ + diff --git a/web/text_layer_builder.js b/web/text_layer_builder.js index 805498de5..6ef873684 100644 --- a/web/text_layer_builder.js +++ b/web/text_layer_builder.js @@ -16,14 +16,6 @@ 'use strict'; -var MAX_TEXT_DIVS_TO_RENDER = 100000; - -var NonWhitespaceRegexp = /\S/; - -function isAllWhitespace(str) { - return !NonWhitespaceRegexp.test(str); -} - /** * @typedef {Object} TextLayerBuilderOptions * @property {HTMLDivElement} textLayerDiv - The text layer container. @@ -50,6 +42,7 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() { this.viewport = options.viewport; this.textDivs = []; this.findController = options.findController || null; + this.textLayerRenderTask = null; this._bindMouse(); } @@ -68,67 +61,6 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() { this.textLayerDiv.dispatchEvent(event); }, - renderLayer: function TextLayerBuilder_renderLayer() { - var textLayerFrag = document.createDocumentFragment(); - var textDivs = this.textDivs; - var textDivsLength = textDivs.length; - var canvas = document.createElement('canvas'); -//#if MOZCENTRAL || FIREFOX || GENERIC - canvas.mozOpaque = true; -//#endif - var ctx = canvas.getContext('2d', {alpha: false}); - - // No point in rendering many divs as it would make the browser - // unusable even after the divs are rendered. - if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) { - this._finishRendering(); - return; - } - - var lastFontSize; - var lastFontFamily; - for (var i = 0; i < textDivsLength; i++) { - var textDiv = textDivs[i]; - if (textDiv.dataset.isWhitespace !== undefined) { - continue; - } - - var fontSize = textDiv.style.fontSize; - var fontFamily = textDiv.style.fontFamily; - - // Only build font string and set to context if different from last. - if (fontSize !== lastFontSize || fontFamily !== lastFontFamily) { - ctx.font = fontSize + ' ' + fontFamily; - lastFontSize = fontSize; - lastFontFamily = fontFamily; - } - - var width = ctx.measureText(textDiv.textContent).width; - if (width > 0) { - textLayerFrag.appendChild(textDiv); - var transform; - if (textDiv.dataset.canvasWidth !== undefined) { - // Dataset values come of type string. - var textScale = textDiv.dataset.canvasWidth / width; - transform = 'scaleX(' + textScale + ')'; - } else { - transform = ''; - } - var rotation = textDiv.dataset.angle; - if (rotation) { - transform = 'rotate(' + rotation + 'deg) ' + transform; - } - if (transform) { - PDFJS.CustomStyle.setProp('transform' , textDiv, transform); - } - } - } - - this.textLayerDiv.appendChild(textLayerFrag); - this._finishRendering(); - this.updateMatches(); - }, - /** * Renders the text layer. * @param {number} timeout (optional) if specified, the rendering waits @@ -139,87 +71,35 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() { return; } - if (this.renderTimer) { - clearTimeout(this.renderTimer); - this.renderTimer = null; + if (this.textLayerRenderTask) { + this.textLayerRenderTask.cancel(); + this.textLayerRenderTask = null; } - if (!timeout) { // Render right away - this.renderLayer(); - } else { // Schedule - var self = this; - this.renderTimer = setTimeout(function() { - self.renderLayer(); - self.renderTimer = null; - }, timeout); - } - }, - - appendText: function TextLayerBuilder_appendText(geom, styles) { - var style = styles[geom.fontName]; - var textDiv = document.createElement('div'); - this.textDivs.push(textDiv); - if (isAllWhitespace(geom.str)) { - textDiv.dataset.isWhitespace = true; - return; - } - var tx = PDFJS.Util.transform(this.viewport.transform, geom.transform); - var angle = Math.atan2(tx[1], tx[0]); - if (style.vertical) { - angle += Math.PI / 2; - } - var fontHeight = Math.sqrt((tx[2] * tx[2]) + (tx[3] * tx[3])); - var fontAscent = fontHeight; - if (style.ascent) { - fontAscent = style.ascent * fontAscent; - } else if (style.descent) { - fontAscent = (1 + style.descent) * fontAscent; - } - - var left; - var top; - if (angle === 0) { - left = tx[4]; - top = tx[5] - fontAscent; - } else { - left = tx[4] + (fontAscent * Math.sin(angle)); - top = tx[5] - (fontAscent * Math.cos(angle)); - } - textDiv.style.left = left + 'px'; - textDiv.style.top = top + 'px'; - textDiv.style.fontSize = fontHeight + 'px'; - textDiv.style.fontFamily = style.fontFamily; - - textDiv.textContent = geom.str; - // |fontName| is only used by the Font Inspector. This test will succeed - // when e.g. the Font Inspector is off but the Stepper is on, but it's - // not worth the effort to do a more accurate test. - if (PDFJS.pdfBug) { - textDiv.dataset.fontName = geom.fontName; - } - // Storing into dataset will convert number into string. - if (angle !== 0) { - textDiv.dataset.angle = angle * (180 / Math.PI); - } - // We don't bother scaling single-char text divs, because it has very - // little effect on text highlighting. This makes scrolling on docs with - // lots of such divs a lot faster. - if (geom.str.length > 1) { - if (style.vertical) { - textDiv.dataset.canvasWidth = geom.height * this.viewport.scale; - } else { - textDiv.dataset.canvasWidth = geom.width * this.viewport.scale; - } - } + this.textDivs = []; + var textLayerFrag = document.createDocumentFragment(); + this.textLayerRenderTask = PDFJS.renderTextLayer({ + textContent: this.textContent, + container: textLayerFrag, + viewport: this.viewport, + textDivs: this.textDivs, + timeout: timeout + }); + this.textLayerRenderTask.promise.then(function () { + this.textLayerDiv.appendChild(textLayerFrag); + this._finishRendering(); + this.updateMatches(); + }.bind(this), function (reason) { + // canceled or failed to render text layer -- skipping errors + }); }, setTextContent: function TextLayerBuilder_setTextContent(textContent) { - this.textContent = textContent; - - var textItems = textContent.items; - for (var i = 0, len = textItems.length; i < len; i++) { - this.appendText(textItems[i], textContent.styles); + if (this.textLayerRenderTask) { + this.textLayerRenderTask.cancel(); + this.textLayerRenderTask = null; } + this.textContent = textContent; this.divContentDone = true; }, diff --git a/web/viewer.html b/web/viewer.html index 217d3f2a3..dbbaece08 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -62,6 +62,7 @@ See https://github.com/adobe-type-tools/cmap-resources +