UNPKG

opentype.js

Version:
159 lines (139 loc) 4.75 kB
// 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 };