opentype.js
Version:
OpenType font parser
159 lines (139 loc) • 4.75 kB
JavaScript
// The GlyphSet object
import Glyph from './glyph';
// Define a property on the glyph that depends on the path being loaded.
function defineDependentProperty(glyph, externalName, internalName) {
Object.defineProperty(glyph, externalName, {
get: function() {
// Request the path property to make sure the path is loaded.
glyph.path; // jshint ignore:line
return glyph[internalName];
},
set: function(newValue) {
glyph[internalName] = newValue;
},
enumerable: true,
configurable: true
});
}
/**
* A GlyphSet represents all glyphs available in the font, but modelled using
* a deferred glyph loader, for retrieving glyphs only once they are absolutely
* necessary, to keep the memory footprint down.
* @exports opentype.GlyphSet
* @class
* @param {opentype.Font}
* @param {Array}
*/
function GlyphSet(font, glyphs) {
this.font = font;
this.glyphs = {};
if (Array.isArray(glyphs)) {
for (let i = 0; i < glyphs.length; i++) {
const glyph = glyphs[i];
glyph.path.unitsPerEm = font.unitsPerEm;
this.glyphs[i] = glyph;
}
}
this.length = (glyphs && glyphs.length) || 0;
}
/**
* @param {number} index
* @return {opentype.Glyph}
*/
GlyphSet.prototype.get = function(index) {
// this.glyphs[index] is 'undefined' when low memory mode is on. glyph is pushed on request only.
if (this.glyphs[index] === undefined) {
this.font._push(index);
if (typeof this.glyphs[index] === 'function') {
this.glyphs[index] = this.glyphs[index]();
}
let glyph = this.glyphs[index];
let unicodeObj = this.font._IndexToUnicodeMap[index];
if (unicodeObj) {
for (let j = 0; j < unicodeObj.unicodes.length; j++)
glyph.addUnicode(unicodeObj.unicodes[j]);
}
if (this.font.cffEncoding) {
if (this.font.isCIDFont) {
glyph.name = 'gid' + index;
} else {
glyph.name = this.font.cffEncoding.charset[index];
}
} else if (this.font.glyphNames.names) {
glyph.name = this.font.glyphNames.glyphIndexToName(index);
}
this.glyphs[index].advanceWidth = this.font._hmtxTableData[index].advanceWidth;
this.glyphs[index].leftSideBearing = this.font._hmtxTableData[index].leftSideBearing;
} else {
if (typeof this.glyphs[index] === 'function') {
this.glyphs[index] = this.glyphs[index]();
}
}
return this.glyphs[index];
};
/**
* @param {number} index
* @param {Object}
*/
GlyphSet.prototype.push = function(index, loader) {
this.glyphs[index] = loader;
this.length++;
};
/**
* @alias opentype.glyphLoader
* @param {opentype.Font} font
* @param {number} index
* @return {opentype.Glyph}
*/
function glyphLoader(font, index) {
return new Glyph({index: index, font: font});
}
/**
* Generate a stub glyph that can be filled with all metadata *except*
* the "points" and "path" properties, which must be loaded only once
* the glyph's path is actually requested for text shaping.
* @alias opentype.ttfGlyphLoader
* @param {opentype.Font} font
* @param {number} index
* @param {Function} parseGlyph
* @param {Object} data
* @param {number} position
* @param {Function} buildPath
* @return {opentype.Glyph}
*/
function ttfGlyphLoader(font, index, parseGlyph, data, position, buildPath) {
return function() {
const glyph = new Glyph({index: index, font: font});
glyph.path = function() {
parseGlyph(glyph, data, position);
const path = buildPath(font.glyphs, glyph);
path.unitsPerEm = font.unitsPerEm;
return path;
};
defineDependentProperty(glyph, 'xMin', '_xMin');
defineDependentProperty(glyph, 'xMax', '_xMax');
defineDependentProperty(glyph, 'yMin', '_yMin');
defineDependentProperty(glyph, 'yMax', '_yMax');
return glyph;
};
}
/**
* @alias opentype.cffGlyphLoader
* @param {opentype.Font} font
* @param {number} index
* @param {Function} parseCFFCharstring
* @param {string} charstring
* @return {opentype.Glyph}
*/
function cffGlyphLoader(font, index, parseCFFCharstring, charstring) {
return function() {
const glyph = new Glyph({index: index, font: font});
glyph.path = function() {
const path = parseCFFCharstring(font, glyph, charstring);
path.unitsPerEm = font.unitsPerEm;
return path;
};
return glyph;
};
}
export default { GlyphSet, glyphLoader, ttfGlyphLoader, cffGlyphLoader };