Source: FontData/Font.js


/**
 * Represents a font. Data is stored similarly to tilesets in an array, with the ability to remap characters
 * that have a unicode point larger than the array can hold.
 */
class Font {
  constructor( fontData ) {
    /**
     * The standard width for a character. Used as the default if none is specified for a character.
     */
    this.standardWidth = 5;

    /**
     * Number of pixels between each character
     */
    this.letterSpacing = 1;

    /**
     * The tile size of the tile sheet where the characters are drawn
     */
    this.tileSize = 16;

    /**
     * The number of columns in the tile sheet
     */
    this.width = 16;

    /**
     * The number of rows in the tile sheet
     */
    this.height = 16;

    /**
     * The x origin in pixels of the character relative to the bottom left.
     */
    this.originX = 1;

    /**
     * The y origin in pixels of the character relative to the bottom left.
     */
    this.originY = 3;

    /**
     * Object mapping unicode points to character information.
     * Used for changing a characters size or remapping unicode points larger than what fits on the tile sheet.
     */
    this.charData = null;

    /**
     * Uint8ClampedArray of the tile sheet data.
     * Generated by the constructor.
     */
    this.data = null;

    if ( fontData ) {
      this.standardWidth = fontData.standardWidth;
      this.letterSpacing = fontData.letterSpacing;

      this.tileSize = fontData.tileSize;
      this.width = fontData.width;
      this.height = fontData.height;
      this.originX = fontData.originX;
      this.originY = fontData.originY;
      this.charData = fontData.charData;

      this.data = new Uint8ClampedArray( this.width * this.height * this.tileSize * this.tileSize );
      const { data } = fontData;
      let runPosition = 0;
      let dataPosition = 0;
      while ( runPosition < data.length ) {
        const runLength = data[runPosition];
        const paletteId = parseInt( data[runPosition + 1], 10 );
        for ( let j = 0; j < runLength; j += 1 ) {
          this.data[dataPosition] = paletteId;
          dataPosition += 1;
        }
        runPosition += 2;
      }
    }
  }

  /**
   * Get the base index in the data array for the character
   * @param {number} charCode - the unicode point for the character
   */
  baseIndexForChar( charCode ) {
    let codePoint = charCode;
    if ( charCode >= this.width * this.height ) {
      const key = charCode.toString();

      if ( this.charData && this.charData[key] ) {
        if ( this.charData[key] !== undefined ) {
          codePoint = this.charData[key].remap;
        }
      }
    }
    return codePoint * this.tileSize * this.tileSize;
  }

  /**
   * Get the width of a character
   * @param {number} charCode - the unicode point for the character
   */
  widthForChar( charCode ) {
    const charKey = charCode.toString();
    if ( this.charData && this.charData[charKey] ) {
      if ( this.charData[charKey].width !== undefined ) {
        return this.charData[charKey].width;
      }
    }
    return this.standardWidth;
  }
}

export default Font;