diff --git a/src/display/text_layer.js b/src/display/text_layer.js index a1e82e0b2..893c6ea7d 100644 --- a/src/display/text_layer.js +++ b/src/display/text_layer.js @@ -59,14 +59,20 @@ var renderTextLayer = (function renderTextLayerClosure() { return !NonWhitespaceRegexp.test(str); } + // Text layers may contain many thousand div's, and using `styleBuf` avoids + // creating many intermediate strings when building their 'style' properties. + var styleBuf = ['left: ', 0, 'px; top: ', 0, 'px; font-size: ', 0, + 'px; font-family: ', '', ';']; + function appendText(task, geom, styles) { // Initialize all used properties to keep the caches monomorphic. var textDiv = document.createElement('div'); var textDivProperties = { + style: null, angle: 0, canvasWidth: 0, isWhitespace: false, - originalTransform: '', + originalTransform: null, paddingBottom: 0, paddingLeft: 0, paddingRight: 0, @@ -104,10 +110,12 @@ var renderTextLayer = (function renderTextLayerClosure() { 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; + styleBuf[1] = left; + styleBuf[3] = top; + styleBuf[5] = fontHeight; + styleBuf[7] = style.fontFamily; + textDivProperties.style = styleBuf.join(''); + textDiv.setAttribute('style', textDivProperties.style); textDiv.textContent = geom.str; // |fontName| is only used by the Font Inspector. This test will succeed @@ -517,7 +525,6 @@ var renderTextLayer = (function renderTextLayerClosure() { this._renderTimer = null; this._bounds = []; this._enhanceTextSelection = !!enhanceTextSelection; - this._expanded = false; } TextLayerRenderTask.prototype = { get promise() { @@ -555,18 +562,20 @@ var renderTextLayer = (function renderTextLayerClosure() { if (!this._enhanceTextSelection || !this._renderingDone) { return; } - if (!this._expanded) { + if (this._bounds !== null) { expand(this); - this._expanded = true; - this._bounds.length = 0; + this._bounds = null; } for (var i = 0, ii = this._textDivs.length; i < ii; i++) { var div = this._textDivs[i]; var divProperties = this._textDivProperties.get(div); + if (divProperties.isWhitespace) { + continue; + } if (expandDivs) { - var transform = ''; + var transform = '', padding = ''; if (divProperties.scale !== 1) { transform = 'scaleX(' + divProperties.scale + ')'; @@ -575,21 +584,26 @@ var renderTextLayer = (function renderTextLayerClosure() { transform = 'rotate(' + divProperties.angle + 'deg) ' + transform; } if (divProperties.paddingLeft !== 0) { - div.style.paddingLeft = - (divProperties.paddingLeft / divProperties.scale) + 'px'; + padding += ' padding-left: ' + + (divProperties.paddingLeft / divProperties.scale) + 'px;'; transform += ' translateX(' + (-divProperties.paddingLeft / divProperties.scale) + 'px)'; } if (divProperties.paddingTop !== 0) { - div.style.paddingTop = divProperties.paddingTop + 'px'; + padding += ' padding-top: ' + divProperties.paddingTop + 'px;'; transform += ' translateY(' + (-divProperties.paddingTop) + 'px)'; } if (divProperties.paddingRight !== 0) { - div.style.paddingRight = - (divProperties.paddingRight / divProperties.scale) + 'px'; + padding += ' padding-right: ' + + (divProperties.paddingRight / divProperties.scale) + 'px;'; } if (divProperties.paddingBottom !== 0) { - div.style.paddingBottom = divProperties.paddingBottom + 'px'; + padding += ' padding-bottom: ' + + divProperties.paddingBottom + 'px;'; + } + + if (padding !== '') { + div.setAttribute('style', divProperties.style + padding); } if (transform !== '') { CustomStyle.setProp('transform', div, transform); @@ -597,7 +611,7 @@ var renderTextLayer = (function renderTextLayerClosure() { } else { div.style.padding = 0; CustomStyle.setProp('transform', div, - divProperties.originalTransform); + divProperties.originalTransform || ''); } } },