Add a cache for glyphs.
This reduces memory consumption for text heavy documents. I tested five documents and saw hit rates ranging from 97.4% to 99.8% (most of the misses are due to |width| varying even when |fontChar| matches). On two of those documents I saw improvements of 40 and 50 MiB. The patch also introduces the Glyph constructor, and renames the |unicodeChars| local variable as |unicode| for consistency with the corresponding Glyph property.
This commit is contained in:
parent
e5cd75083f
commit
0866ad5bff
@ -2127,6 +2127,29 @@ function adjustWidths(properties) {
|
|||||||
properties.defaultWidth *= scale;
|
properties.defaultWidth *= scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Glyph = (function GlyphClosure() {
|
||||||
|
function Glyph(fontChar, unicode, accent, width, vmetric, operatorList) {
|
||||||
|
this.fontChar = fontChar;
|
||||||
|
this.unicode = unicode;
|
||||||
|
this.accent = accent;
|
||||||
|
this.width = width;
|
||||||
|
this.vmetric = vmetric;
|
||||||
|
this.operatorList = operatorList;
|
||||||
|
}
|
||||||
|
|
||||||
|
Glyph.prototype.matchesForCache =
|
||||||
|
function(fontChar, unicode, accent, width, vmetric, operatorList) {
|
||||||
|
return this.fontChar === fontChar &&
|
||||||
|
this.unicode === unicode &&
|
||||||
|
this.accent === accent &&
|
||||||
|
this.width === width &&
|
||||||
|
this.vmetric === vmetric &&
|
||||||
|
this.operatorList === operatorList;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Glyph;
|
||||||
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 'Font' is the class the outside world should use, it encapsulate all the font
|
* 'Font' is the class the outside world should use, it encapsulate all the font
|
||||||
* decoding logics whatever type it is (assuming the font type is supported).
|
* decoding logics whatever type it is (assuming the font type is supported).
|
||||||
@ -2144,6 +2167,8 @@ var Font = (function FontClosure() {
|
|||||||
this.loadCharProcs = properties.coded;
|
this.loadCharProcs = properties.coded;
|
||||||
this.sizes = [];
|
this.sizes = [];
|
||||||
|
|
||||||
|
this.glyphCache = {};
|
||||||
|
|
||||||
var names = name.split('+');
|
var names = name.split('+');
|
||||||
names = names.length > 1 ? names[1] : names[0];
|
names = names.length > 1 ? names[1] : names[0];
|
||||||
names = names.split(/[-,_]/g)[0];
|
names = names.split(/[-,_]/g)[0];
|
||||||
@ -4305,9 +4330,9 @@ var Font = (function FontClosure() {
|
|||||||
width = isNum(width) ? width : this.defaultWidth;
|
width = isNum(width) ? width : this.defaultWidth;
|
||||||
var vmetric = this.vmetrics && this.vmetrics[widthCode];
|
var vmetric = this.vmetrics && this.vmetrics[widthCode];
|
||||||
|
|
||||||
var unicodeChars = this.toUnicode[charcode] || charcode;
|
var unicode = this.toUnicode[charcode] || charcode;
|
||||||
if (typeof unicodeChars === 'number') {
|
if (typeof unicode === 'number') {
|
||||||
unicodeChars = String.fromCharCode(unicodeChars);
|
unicode = String.fromCharCode(unicode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// First try the toFontChar map, if it's not there then try falling
|
// First try the toFontChar map, if it's not there then try falling
|
||||||
@ -4332,14 +4357,17 @@ var Font = (function FontClosure() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
var fontChar = String.fromCharCode(fontCharCode);
|
||||||
fontChar: String.fromCharCode(fontCharCode),
|
|
||||||
unicode: unicodeChars,
|
var glyph = this.glyphCache[charcode];
|
||||||
accent: accent,
|
if (!glyph ||
|
||||||
width: width,
|
!glyph.matchesForCache(fontChar, unicode, accent, width, vmetric,
|
||||||
vmetric: vmetric,
|
operatorList)) {
|
||||||
operatorList: operatorList
|
glyph = new Glyph(fontChar, unicode, accent, width, vmetric,
|
||||||
};
|
operatorList);
|
||||||
|
this.glyphCache[charcode] = glyph;
|
||||||
|
}
|
||||||
|
return glyph;
|
||||||
},
|
},
|
||||||
|
|
||||||
charsToGlyphs: function Font_charsToGlyphs(chars) {
|
charsToGlyphs: function Font_charsToGlyphs(chars) {
|
||||||
|
Loading…
Reference in New Issue
Block a user