Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(TS): extract caches from HEADER #8198

Merged
merged 29 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7a0a0fa
Create config.ts
ShaMan123 Aug 26, 2022
7e2c5ff
Update config.ts
ShaMan123 Aug 26, 2022
dfc942d
Update config.ts
ShaMan123 Aug 26, 2022
b6933cb
Update config.ts
ShaMan123 Aug 26, 2022
2c5f1d9
migrate
ShaMan123 Aug 27, 2022
f788895
fontPaths
ShaMan123 Aug 27, 2022
51aef74
verbose flag on node test
ShaMan123 Aug 27, 2022
aa7f78f
Revert "verbose flag on node test"
ShaMan123 Aug 27, 2022
684a4cd
fix import
ShaMan123 Aug 27, 2022
5e15d51
Update HEADER.js
ShaMan123 Aug 27, 2022
c7a5b40
Update config.ts
ShaMan123 Aug 27, 2022
9c324da
fix const enum iteration
ShaMan123 Aug 27, 2022
479a137
fix const enum iteration
ShaMan123 Aug 27, 2022
cea2d93
Update config.ts
ShaMan123 Aug 27, 2022
5287f1a
migrate `NUM_FRACTION_DIGITS`
ShaMan123 Aug 27, 2022
7ac4a54
Update object.js
ShaMan123 Aug 27, 2022
9fb08eb
removed `isWebglSupported` redundant flag
ShaMan123 Aug 27, 2022
146fa5e
extract cache
ShaMan123 Aug 27, 2022
48d64c1
Update config.ts
ShaMan123 Aug 27, 2022
6c06100
move getFontCache
ShaMan123 Aug 27, 2022
5611a87
Revert "move getFontCache"
ShaMan123 Aug 27, 2022
34728bd
Revert "extract cache"
ShaMan123 Aug 27, 2022
47e0eb8
Revert "Revert "extract cache""
ShaMan123 Aug 27, 2022
c8cafa6
Revert "Revert "move getFontCache""
ShaMan123 Aug 27, 2022
7dc9e5d
Update HEADER.js
ShaMan123 Aug 27, 2022
aa4ddf0
Merge branch 'master' into ts-cache
ShaMan123 Aug 28, 2022
9f49937
Merge branch 'master' into ts-cache
ShaMan123 Aug 29, 2022
bc7f5ac
Merge branch 'master' into ts-cache
ShaMan123 Aug 29, 2022
fae425e
merge master
asturur Aug 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 2 additions & 23 deletions HEADER.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */

import { cache } from './src/cache';
import { config } from './src/config';
import { iMatrix, VERSION } from './src/constants';

var fabric = fabric || {
version: VERSION,
config,
cache,
iMatrix
};

Expand Down Expand Up @@ -88,28 +89,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
64 changes: 64 additions & 0 deletions src/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@

export class Cache {
/**
* Cache of widths of chars in text rendering.
*/
charWidthsCache: Record</** fontFamily */ string, Record</** fontStyleCacheKey */ string, Record</** char */ string, /** width */ number>>> = {}

/**
* @return {Object} reference to cache
*/
getFontCache({ fontFamily, fontStyle, fontWeight }: { fontFamily: string, fontStyle: string, fontWeight: string | number }) {
fontFamily = fontFamily.toLowerCase();
if (!this.charWidthsCache[fontFamily]) {
this.charWidthsCache[fontFamily] = {};
}
const fontCache = this.charWidthsCache[fontFamily];
const cacheKey = `${fontStyle.toLowerCase()}_${(fontWeight + '').toLowerCase()}`;
if (!fontCache[cacheKey]) {
fontCache[cacheKey] = {};
}
return fontCache[cacheKey];
}


/**
* 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();
24 changes: 2 additions & 22 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 @@ -695,27 +696,6 @@ import { DEFAULT_SVG_FONT_SIZE } from "../constants";
this._removeShadow(ctx);
},

/**
* @private
* @param {Object} decl style declaration for cache
* @param {String} decl.fontFamily fontFamily
* @param {String} decl.fontStyle fontStyle
* @param {String} decl.fontWeight fontWeight
* @return {Object} reference to cache
*/
getFontCache: function(decl) {
var fontFamily = decl.fontFamily.toLowerCase();
if (!fabric.charWidthsCache[fontFamily]) {
fabric.charWidthsCache[fontFamily] = { };
}
var cache = fabric.charWidthsCache[fontFamily],
cacheProp = decl.fontStyle.toLowerCase() + '_' + (decl.fontWeight + '').toLowerCase();
if (!cache[cacheProp]) {
cache[cacheProp] = { };
}
return cache[cacheProp];
},

/**
* measure and return the width of a single character.
* possibly overridden to accommodate different measure logic or
Expand All @@ -728,7 +708,7 @@ import { DEFAULT_SVG_FONT_SIZE } from "../constants";
*/
_measureChar: function(_char, charStyle, previousChar, prevCharStyle) {
// first i try to return from cache
var fontCache = this.getFontCache(charStyle), fontDeclaration = this._getFontDeclaration(charStyle),
var fontCache = cache.getFontCache(charStyle), fontDeclaration = this._getFontDeclaration(charStyle),
previousFontDeclaration = this._getFontDeclaration(prevCharStyle), couple = previousChar + _char,
stylesAreEqual = fontDeclaration === previousFontDeclaration, width, coupleWidth, previousWidth,
fontMultiplier = charStyle.fontSize / this.CACHE_FONT_SIZE, kernedWidth;
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 @@ -227,28 +227,6 @@ import {
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
8 changes: 5 additions & 3 deletions src/util/path.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//@ts-nocheck

import { cache } from "../cache";
import { config } from "../config";
import { fabric } from '../../HEADER';
import { halfPI, PiBy180 } from "../constants";
Expand Down Expand Up @@ -137,8 +139,8 @@ export function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) {
if (config.cachesBoundsOfCurve) {
// eslint-disable-next-line
argsString = [...arguments].join();
if (fabric.boundsOfCurveCache[argsString]) {
return fabric.boundsOfCurveCache[argsString];
if (cache.boundsOfCurveCache[argsString]) {
return cache.boundsOfCurveCache[argsString];
}
}

Expand Down Expand Up @@ -206,7 +208,7 @@ export function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) {
}
];
if (config.cachesBoundsOfCurve) {
fabric.boundsOfCurveCache[argsString] = result;
cache.boundsOfCurveCache[argsString] = result;
}
return result;
}
Expand Down
10 changes: 5 additions & 5 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 All @@ -400,8 +400,8 @@
text.initDimensions();
var text2 = new fabric.Text('xxx', { fontWeight: 'bOLd', fontStyle: 'nORMAl' });
text2.initDimensions();
var cache = text.getFontCache(text);
var cache2 = text2.getFontCache(text2);
var cache = fabric.cache.getFontCache(text);
var cache2 = fabric.cache.getFontCache(text2);
assert.equal(cache, cache2, 'you get the same cache');
});
// moved
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 @@ -701,21 +701,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