Skip to content

Commit

Permalink
extract cache
Browse files Browse the repository at this point in the history
  • Loading branch information
ShaMan123 committed Aug 27, 2022
1 parent 9fb08eb commit 146fa5e
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 68 deletions.
22 changes: 0 additions & 22 deletions HEADER.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,28 +92,6 @@ config.configure({
1
});

/**
* Cache Object for widths of chars in text rendering.
*/
fabric.charWidthsCache = {};

/**
* This object contains the result of arc to bezier conversion for faster retrieving if the same arc needs to be converted again.
* It was an internal variable, is accessible since version 2.3.4
*/
fabric.arcToSegmentsCache = { };

/**
* This object keeps the results of the boundsOfCurve calculation mapped by the joined arguments necessary to calculate it.
* It does speed up calculation, if you parse and add always the same paths, but in case of heavy usage of freedrawing
* you do not get any speed benefit and you get a big object in memory.
* The object was a private variable before, while now is appended to the lib so that you have access to it and you
* can eventually clear it.
* It was an internal variable, is accessible since version 2.3.4
*/
fabric.boundsOfCurveCache = { };


fabric.initFilterBackend = function() {
if (config.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(config.textureSize)) {
console.log(`fabric: max texture size: ${config.maxTextureSize}`);
Expand Down
48 changes: 48 additions & 0 deletions src/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

export class Cache {
/**
* Cache Object for widths of chars in text rendering.
*/
charWidthsCache = {}


/**
* Clear char widths cache for the given font family or all the cache if no
* fontFamily is specified.
* Use it if you know you are loading fonts in a lazy way and you are not waiting
* for custom fonts to load properly when adding text objects to the canvas.
* If a text object is added when its own font is not loaded yet, you will get wrong
* measurement and so wrong bounding boxes.
* After the font cache is cleared, either change the textObject text content or call
* initDimensions() to trigger a recalculation
* @memberOf fabric.util
* @param {String} [fontFamily] font family to clear
*/
clearFontCache(fontFamily?: string) {
fontFamily = (fontFamily || '').toLowerCase();
if (!fontFamily) {
this.charWidthsCache = {};
}
else if (this.charWidthsCache[fontFamily]) {
delete this.charWidthsCache[fontFamily];
}
}

/**
* This object contains the result of arc to bezier conversion for faster retrieving if the same arc needs to be converted again.
* It was an internal variable, is accessible since version 2.3.4
*/
arcToSegmentsCache = {}

/**
* This object keeps the results of the boundsOfCurve calculation mapped by the joined arguments necessary to calculate it.
* It does speed up calculation, if you parse and add always the same paths, but in case of heavy usage of freedrawing
* you do not get any speed benefit and you get a big object in memory.
* The object was a private variable before, while now is appended to the lib so that you have access to it and you
* can eventually clear it.
* It was an internal variable, is accessible since version 2.3.4
*/
boundsOfCurveCache = {}
}

export const cache = new Cache();
7 changes: 4 additions & 3 deletions src/shapes/text.class.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//@ts-nocheck

import { cache } from "../cache";
import { DEFAULT_SVG_FONT_SIZE } from "../constants";


Expand Down Expand Up @@ -705,10 +706,10 @@ import { DEFAULT_SVG_FONT_SIZE } from "../constants";
*/
getFontCache: function(decl) {
var fontFamily = decl.fontFamily.toLowerCase();
if (!fabric.charWidthsCache[fontFamily]) {
fabric.charWidthsCache[fontFamily] = { };
if (!cache.charWidthsCache[fontFamily]) {
cache.charWidthsCache[fontFamily] = { };
}
var cache = fabric.charWidthsCache[fontFamily],
var cache = cache.charWidthsCache[fontFamily],
cacheProp = decl.fontStyle.toLowerCase() + '_' + (decl.fontWeight + '').toLowerCase();
if (!cache[cacheProp]) {
cache[cacheProp] = { };
Expand Down
22 changes: 0 additions & 22 deletions src/util/misc/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,28 +367,6 @@ import { makeBoundingBoxFromPoints } from './boundingBoxFromPoints';
return _isTransparent;
},

/**
* Clear char widths cache for the given font family or all the cache if no
* fontFamily is specified.
* Use it if you know you are loading fonts in a lazy way and you are not waiting
* for custom fonts to load properly when adding text objects to the canvas.
* If a text object is added when its own font is not loaded yet, you will get wrong
* measurement and so wrong bounding boxes.
* After the font cache is cleared, either change the textObject text content or call
* initDimensions() to trigger a recalculation
* @memberOf fabric.util
* @param {String} [fontFamily] font family to clear
*/
clearFabricFontCache: function(fontFamily) {
fontFamily = (fontFamily || '').toLowerCase();
if (!fontFamily) {
fabric.charWidthsCache = { };
}
else if (fabric.charWidthsCache[fontFamily]) {
delete fabric.charWidthsCache[fontFamily];
}
},

/**
* Given current aspect ratio, determines the max width and height that can
* respect the total allowed area for the cache.
Expand Down
7 changes: 4 additions & 3 deletions src/util/path.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//@ts-nocheck

import { cache } from "../cache";
import { config } from "../config";
import { commaWsp, rePathCommand } from "../parser/constants";
import { Point } from '../point.class';
Expand Down Expand Up @@ -131,8 +132,8 @@ import { Point } from '../point.class';
var argsString;
if (config.cachesBoundsOfCurve) {
argsString = _join.call(arguments);
if (fabric.boundsOfCurveCache[argsString]) {
return fabric.boundsOfCurveCache[argsString];
if (cache.boundsOfCurveCache[argsString]) {
return cache.boundsOfCurveCache[argsString];
}
}

Expand Down Expand Up @@ -204,7 +205,7 @@ import { Point } from '../point.class';
}
];
if (config.cachesBoundsOfCurve) {
fabric.boundsOfCurveCache[argsString] = result;
cache.boundsOfCurveCache[argsString] = result;
}
return result;
}
Expand Down
6 changes: 3 additions & 3 deletions test/unit/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@
QUnit.test('getFontCache works with fontWeight numbers', function(assert) {
var text = new fabric.Text('xxx', { fontWeight: 400 });
text.initDimensions();
var cache = fabric.charWidthsCache[text.fontFamily.toLowerCase()];
var cache = fabric.cache.charWidthsCache[text.fontFamily.toLowerCase()];
var cacheProp = text.fontStyle + '_400';
assert.equal(cacheProp in cache, true, '400 is converted to string');
});
Expand Down Expand Up @@ -741,13 +741,13 @@
});

QUnit.test('_measureChar handles 0 width chars', function(assert) {
fabric.charWidthsCache = {};
fabric.cache.clearFontCache();
var zwc = '\u200b';
var text = new fabric.Text('');
var style = text.getCompleteStyleDeclaration(0, 0);
var box = text._measureChar('a', style, zwc, style);
var box2 = text._measureChar('a', style, zwc, style);
assert.equal(fabric.charWidthsCache[text.fontFamily.toLowerCase()].normal_normal[zwc], 0, 'zwc is a 0 width char');
assert.equal(fabric.cache.charWidthsCache[text.fontFamily.toLowerCase()].normal_normal[zwc], 0, 'zwc is a 0 width char');
assert.equal(box.kernedWidth, box2.kernedWidth, '2 measurements of the same string return the same number');
});

Expand Down
30 changes: 15 additions & 15 deletions test/unit/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -711,21 +711,21 @@
assert.equal(fabric.util.getKlass('Sepia2', 'fabric.Image.filters'), fabric.Image.filters.Sepia2);
});

QUnit.test('clearFabricFontCache', function(assert) {
assert.ok(typeof fabric.util.clearFabricFontCache === 'function');
fabric.charWidthsCache = { arial: { some: 'cache'}, helvetica: { some: 'cache'} };
fabric.util.clearFabricFontCache('arial');
assert.equal(fabric.charWidthsCache.arial, undefined, 'arial cache is deleted');
assert.equal(fabric.charWidthsCache.helvetica.some, 'cache', 'helvetica cache is still available');
fabric.util.clearFabricFontCache();
assert.deepEqual(fabric.charWidthsCache, { }, 'all cache is deleted');
});

QUnit.test('clearFabricFontCache wrong case', function(assert) {
fabric.charWidthsCache = { arial: { some: 'cache'}, helvetica: { some: 'cache'} };
fabric.util.clearFabricFontCache('ARIAL');
assert.equal(fabric.charWidthsCache.arial, undefined, 'arial cache is deleted');
assert.equal(fabric.charWidthsCache.helvetica.some, 'cache', 'helvetica cache is still available');
QUnit.test('clearFontCache', function(assert) {
assert.ok(typeof fabric.cache.clearFontCache === 'function');
fabric.cache.charWidthsCache = { arial: { some: 'cache'}, helvetica: { some: 'cache'} };
fabric.cache.clearFontCache('arial');
assert.equal(fabric.cache.charWidthsCache.arial, undefined, 'arial cache is deleted');
assert.equal(fabric.cache.charWidthsCache.helvetica.some, 'cache', 'helvetica cache is still available');
fabric.cache.clearFontCache();
assert.deepEqual(fabric.cache.charWidthsCache, { }, 'all cache is deleted');
});

QUnit.test('clearFontCache wrong case', function(assert) {
fabric.cache.charWidthsCache = { arial: { some: 'cache'}, helvetica: { some: 'cache'} };
fabric.cache.clearFontCache('ARIAL');
assert.equal(fabric.cache.charWidthsCache.arial, undefined, 'arial cache is deleted');
assert.equal(fabric.cache.charWidthsCache.helvetica.some, 'cache', 'helvetica cache is still available');
});

QUnit.test('parsePreserveAspectRatioAttribute', function(assert) {
Expand Down

0 comments on commit 146fa5e

Please sign in to comment.