diff --git a/HEADER.js b/HEADER.js index 9d544b43..6f4d8c2a 100644 --- a/HEADER.js +++ b/HEADER.js @@ -60,6 +60,11 @@ fabric.DPI = 96; fabric.reNum = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)'; fabric.fontPaths = { }; +/** + * Cache Object for widths of chars in text rendering. + */ +fabric.charWidthsCache = { }; + /** * Device Pixel Ratio * @see https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/SettingUptheCanvas/SettingUptheCanvas.html diff --git a/src/shapes/itext.class.js b/src/shapes/itext.class.js index 26c33cc1..28429e6b 100644 --- a/src/shapes/itext.class.js +++ b/src/shapes/itext.class.js @@ -162,11 +162,6 @@ */ _abortCursorAnimation: false, - /** - * @private - */ - _charWidthsCache: { }, - /** * @private */ @@ -782,11 +777,21 @@ */ _getCacheProp: function(_char, styleDeclaration) { return _char + - styleDeclaration.fontFamily + styleDeclaration.fontSize + styleDeclaration.fontWeight + - styleDeclaration.fontStyle + - styleDeclaration.shadow; + styleDeclaration.fontStyle; + }, + + /** + * @private + * @param {String} fontFamily name + * @return {Object} reference to cache + */ + _getFontCache: function(fontFamily) { + if (!fabric.charWidthsCache[fontFamily]) { + fabric.charWidthsCache[fontFamily] = { }; + } + return fabric.charWidthsCache[fontFamily]; }, /** @@ -799,16 +804,17 @@ */ _applyCharStylesGetWidth: function(ctx, _char, lineIndex, charIndex, decl) { var charDecl = this._getStyleDeclaration(lineIndex, charIndex), - styleDeclaration = (decl && clone(decl)) || clone(charDecl), width; + styleDeclaration = (decl && clone(decl)) || clone(charDecl), + width, cacheProp, charWidthsCache; this._applyFontStyles(styleDeclaration); - - var cacheProp = this._getCacheProp(_char, styleDeclaration); + charWidthsCache = this._getFontCache(styleDeclaration.fontFamily); + cacheProp = this._getCacheProp(_char, styleDeclaration); // short-circuit if no styles for this char // global style from object is always applyed and handled by save and restore - if (!charDecl && this._charWidthsCache[cacheProp] && this.caching) { - return this._charWidthsCache[cacheProp]; + if (!charDecl && charWidthsCache[cacheProp] && this.caching) { + return charWidthsCache[cacheProp]; } if (typeof styleDeclaration.shadow === 'string') { @@ -838,13 +844,13 @@ this._setShadow.call(styleDeclaration, ctx); } - if (!this.caching || !this._charWidthsCache[cacheProp]) { + if (!this.caching || !charWidthsCache[cacheProp]) { width = ctx.measureText(_char).width; - this.caching && (this._charWidthsCache[cacheProp] = width); + this.caching && (charWidthsCache[cacheProp] = width); return width; } - return this._charWidthsCache[cacheProp]; + return charWidthsCache[cacheProp]; }, /** @@ -935,13 +941,14 @@ if (!this._isMeasuring && this.textAlign === 'justify' && this._reSpacesAndTabs.test(_char)) { return this._getWidthOfSpace(ctx, lineIndex); } - - var styleDeclaration = this._getStyleDeclaration(lineIndex, charIndex, true); + var charWidthsCache, cacheProp, + styleDeclaration = this._getStyleDeclaration(lineIndex, charIndex, true); this._applyFontStyles(styleDeclaration); - var cacheProp = this._getCacheProp(_char, styleDeclaration); + charWidthsCache = this._getFontCache(styleDeclaration.fontFamily); + cacheProp = this._getCacheProp(_char, styleDeclaration); - if (this._charWidthsCache[cacheProp] && this.caching) { - return this._charWidthsCache[cacheProp]; + if (charWidthsCache[cacheProp] && this.caching) { + return charWidthsCache[cacheProp]; } else if (ctx) { ctx.save(); diff --git a/src/util/misc.js b/src/util/misc.js index d672a33c..0c8f83fd 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -633,6 +633,17 @@ alignX: alignX, alignY: alignY }; + }, + + /** + * Clear char widths cache for a font family. + * @memberOf fabric.util + * @param {String} fontFamily + */ + clearFabricFontCache: function(fontFamily) { + if (fabric.charWidthsCache[fontFamily]) { + fabric.charWidthsCache[fontFamily] = { }; + } } };