Merge pull request #11104 from Snuffleupagus/textLayer-style

[TextLayer] Avoid unnecessary font updates in `_layoutText` and remove `setAttribute` usage in `appendText`
This commit is contained in:
Tim van der Meij 2019-08-28 23:25:58 +02:00 committed by GitHub
commit 3dfce2d4ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -48,11 +48,6 @@ var renderTextLayer = (function renderTextLayerClosure() {
return !NonWhitespaceRegexp.test(str); return !NonWhitespaceRegexp.test(str);
} }
// Text layers may contain many thousands of divs, 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) { function appendText(task, geom, styles) {
// Initialize all used properties to keep the caches monomorphic. // Initialize all used properties to keep the caches monomorphic.
var textDiv = document.createElement('span'); var textDiv = document.createElement('span');
@ -97,11 +92,12 @@ var renderTextLayer = (function renderTextLayerClosure() {
left = tx[4] + (fontAscent * Math.sin(angle)); left = tx[4] + (fontAscent * Math.sin(angle));
top = tx[5] - (fontAscent * Math.cos(angle)); top = tx[5] - (fontAscent * Math.cos(angle));
} }
styleBuf[1] = left; // Setting the style properties individually, rather than all at once,
styleBuf[3] = top; // should be OK since the `textDiv` isn't appended to the document yet.
styleBuf[5] = fontHeight; textDiv.style.left = `${left}px`;
styleBuf[7] = style.fontFamily; textDiv.style.top = `${top}px`;
textDiv.setAttribute('style', styleBuf.join('')); textDiv.style.fontSize = `${fontHeight}px`;
textDiv.style.fontFamily = style.fontFamily;
textDiv.textContent = geom.str; textDiv.textContent = geom.str;
// `fontName` is only used by the FontInspector, and we only use `dataset` // `fontName` is only used by the FontInspector, and we only use `dataset`
@ -525,26 +521,25 @@ var renderTextLayer = (function renderTextLayerClosure() {
}, },
_layoutText(textDiv) { _layoutText(textDiv) {
let textLayerFrag = this._container; const textDivProperties = this._textDivProperties.get(textDiv);
let textDivProperties = this._textDivProperties.get(textDiv);
if (textDivProperties.isWhitespace) { if (textDivProperties.isWhitespace) {
return; return;
} }
const { fontSize, fontFamily, } = textDiv.style;
// Only build font string and set to context if different from last.
if (fontSize !== this._layoutTextLastFontSize ||
fontFamily !== this._layoutTextLastFontFamily) {
this._layoutTextCtx.font = `${fontSize} ${fontFamily}`;
this._layoutTextLastFontSize = fontSize;
this._layoutTextLastFontFamily = fontFamily;
}
let transform = ''; let transform = '';
if (textDivProperties.canvasWidth !== 0) { if (textDivProperties.canvasWidth !== 0) {
const { fontSize, fontFamily, } = textDiv.style;
// Only build font string and set to context if different from last.
if (fontSize !== this._layoutTextLastFontSize ||
fontFamily !== this._layoutTextLastFontFamily) {
this._layoutTextCtx.font = `${fontSize} ${fontFamily}`;
this._layoutTextLastFontSize = fontSize;
this._layoutTextLastFontFamily = fontFamily;
}
// Only measure the width for multi-char text divs, see `appendText`. // Only measure the width for multi-char text divs, see `appendText`.
const { width, } = this._layoutTextCtx.measureText(textDiv.textContent); const { width, } = this._layoutTextCtx.measureText(textDiv.textContent);
if (width > 0) { if (width > 0) {
textDivProperties.scale = textDivProperties.canvasWidth / width; textDivProperties.scale = textDivProperties.canvasWidth / width;
transform = `scaleX(${textDivProperties.scale})`; transform = `scaleX(${textDivProperties.scale})`;
@ -560,7 +555,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
textDiv.style.transform = transform; textDiv.style.transform = transform;
} }
this._textDivProperties.set(textDiv, textDivProperties); this._textDivProperties.set(textDiv, textDivProperties);
textLayerFrag.appendChild(textDiv); this._container.appendChild(textDiv);
}, },
_render: function TextLayer_render(timeout) { _render: function TextLayer_render(timeout) {