js/Mobilizing/text/Font.js
// Warning: 'opentype.js' is the package name, which differs from 'opentype'
import * as opentype from 'opentype.js';
import { Base64Binary } from '../core/util/Misc';
/**
To be able to use both bitmap rendered font and 3D vector rendering, we use openType.js (https://nodebox.github.io/opentype.js/ big thanks to Frederik!) to load any web compilant font and the use it in other classes.
*/
export default class Font {
/**
@param {Object} params Parameters object, given by the constructor.
@param {Mixed} params.fontFile the font file already loaded, must be loaded with response type setted to arraybuffer
*/
constructor({
fontFile = undefined,
base64String = undefined,
} = {}) {
this.fontFile = fontFile;
this.base64String = base64String;
//@TODO préparer des setters getters pour ce qui doit être accessible depuis l'extérieur, mais garder la syntaxe this._params.xxx dans les classes
if (this.fontFile) {
this.font = opentype.parse(this.fontFile);
}
else if (this.base64String) {
const binary = new Base64Binary();
const fontArrayBuffer = binary.decodeArrayBuffer(this.base64String);
this.font = opentype.parse(fontArrayBuffer);
}
}
/**
* Return the underlying Font.js object to work with it outside of Mobilizing.Font ()
* @method getFont
* @return {Object} Font.js object
*/
getFont() {
return this.font;
}
/**
* Calculates the size (in pixels) that should take the string with this font at the given fontSize. Handy for Label creation.
* @method getTextSize
* @param {String} text the string to use for the size computing
* @param {Number} fontSize the text font size to use
* @return {Object.width, Object.height} width and height
*/
getTextSize(text, fontSize) {
if (!this.font.supported) {
return null;
}
let kerning, fontScale, glyphs, i, glyph, options, kerningValue;
const ymax = [];
let x = 0;
fontSize = (fontSize !== undefined) ? fontSize : 72;
options = options || {};
kerning = options.kerning === undefined ? true : options.kerning;
fontScale = 1 / this.font.unitsPerEm * fontSize;
glyphs = this.font.stringToGlyphs(text);
for (i = 0; i < glyphs.length; i += 1) {
glyph = glyphs[i];
ymax.push((glyph.getMetrics().yMax - glyph.getMetrics().yMin) * fontScale);
if (glyph.advanceWidth) {
x += glyph.advanceWidth * fontScale;
}
if (kerning && i < glyphs.length - 1) {
kerningValue = this.font.getKerningValue(glyph, glyphs[i + 1]);
x += kerningValue * fontScale;
}
}
return {
"width": x,
"height": Math.max.apply(0, ymax)
};
}
}